表值參數

表值參數是 SQL Server 2008 中的新參數類型。表值參數是使用用戶定義的表類型來聲明的。使用表值參數,可以不必創建臨時表或許多參數,即可向 Transact-SQL 語句或例程(如存儲過程或函數)發送多行數據。
??表值參數與 OLE DB 和 ODBC 中的參數數組類似,但具有更高的靈活性,且與 Transact-SQL 的集成更緊密。表值參數的另一個優勢是能夠參與基于數據集的操作。

在 Transact-SQL 中創建和使用表值參數

表值參數具有兩個主要部分:SQL Server 類型以及引用該類型的參數。若要創建和使用表值參數,請執行以下步驟:
??1.創建表類型并定義表結構。
??2.聲明具有表類型參數的例程(CREATE PROCEDURE/FUNCTION)。
??3.聲明表類型變量,并引用該表類型。
??4.使用INSERT語句填充表變量。
??5.創建并填充表變量后,可以將該變量傳遞給例程。

優點
??表值參數具有更高的靈活性,在某些情況下,可比臨時表或其他傳遞參數列表的方法提供更好的性能。表值參數具有以下優勢:

  • 首次從客戶端填充數據時,不獲取鎖。
  • 提供簡單的編程模型。
  • 允許在單個例程中包括復雜的業務邏輯。
  • 減少到服務器的往返。
  • 可以具有不同基數的表結構。
  • 是強類型。
  • 使客戶端可以指定排序順序和唯一鍵。

限制
??表值參數有下面的限制:

  • SQL Server 不維護表值參數列的統計信息。
  • 表值參數必須作為輸入 READONLY 參數傳遞到 Transact-SQL 例程。不能在例程體中對表值參數執行諸如 UPDATE、DELETE 或 INSERT 這樣的 DML 操作。
  • 不能將表值參數用作 SELECT INTO 或 INSERT EXEC 語句的目標。表值參數可以在 SELECT INTO 的 FROM 子句中,也可以在 INSERT EXEC 字符串或存儲過程中。
  • 不能將表值參數指定為 INSERT EXEC 語句的目標;但是,可以將它指定為 INSERT EXEC 字符串或存儲過程中的。

作用域
??就像其他參數一樣,表值參數的作用域也是存儲過程、函數或動態 Transact-SQL 文本。同樣,表類型變量也與使用 DECLARE 語句創建的其他任何局部變量一樣具有作用域??梢栽趧討B Transact-SQL 語句內聲明表值變量,并且可以將這些變量作為表值參數傳遞到存儲過程和函數。

用戶定義表類型

在 SQL Server 2008 中,用戶定義表類型是指用戶所定義的表示表結構定義的類型。您可以使用用戶定義表類型為存儲過程或函數聲明表值參數,或者聲明您要在批處理中或在存儲過程或函數的主體中使用的表變量
??若要創建用戶定義表類型,請使用CREATE TYPE語句。為了確保用戶定義表類型的數據滿足特定要求,您可以對用戶定義表類型創建唯一約束和主鍵
??用戶定義表類型具有下列限制:

  • 用戶定義表類型不能用作表中的列或結構化用戶定義類型中的字段。
  • 基于用戶定義表類型的別名類型(詳見CREATE TYPE語句)
  • [NOT FOR REPLICATION] 選項是不允許的。
  • CHECK 約束要求保留計算列。
  • 計算列的主鍵必須是 PERSISTED 和 NOT NULL。
  • 無法對用戶定義表類型創建非聚集索引,除非該索引是對用戶定義表類型創建 PRIMARY KEY 或 UNIQUE 約束的結果。(SQL Server 使用索引強制實施任何 UNIQUE 或 PRIMARY KEY 約束。)
  • 在創建用戶定義表類型定義后不能對其進行修改。
  • 不能在用戶定義表類型的計算列的定義中調用用戶定義函數。

【示例】
(1)定義用戶表值參數

USE AdventureWorks2008R2;
GO

/* Create a user-defined table type */
CREATE TYPE LocationTableType AS TABLE 
( LocationName VARCHAR(50)
, CostRate INT );
GO

(2)下面的示例使用 Transact-SQL 并演示如何執行以下操作:創建表值參數類型,聲明變量來引用它,填充參數列表,然后將值傳遞到存儲過程。

USE AdventureWorks2008R2;
GO

/* Create a table type. */
CREATE TYPE LocationTableType AS TABLE 
( LocationName VARCHAR(50),
  CostRate INT )
GO

/* Create a procedure to receive data for the table-valued parameter. */
CREATE PROCEDURE usp_InsertProductionLocation
    @TVP LocationTableType READONLY
    AS 
    SET NOCOUNT ON
    INSERT INTO AdventureWorks2008R2.Production.Location
           (Name,
            CostRate,
            Availability,
            ModifiedDate)
        SELECT *, 0, GETDATE()
        FROM  @TVP;
        GO

/* Declare a variable that references the type. */
DECLARE @LocationTVP AS LocationTableType;

/* Add data to the table variable. */
INSERT INTO @LocationTVP (LocationName, CostRate)
    SELECT Name, 0.00
    FROM AdventureWorks2008R2.Person.StateProvince;

/* Pass the table variable data to a stored procedure. */
EXEC usp_InsertProductionLocation @LocationTVP;
GO

(3)

CREATE TYPE SalesByStore_tbl AS TABLE 
     (titleid varchar(80) NOT NULL PRIMARY KEY,
      qty     smallint    NOT NULL)
go
CREATE PROCEDURE SalesByStore @storeid varchar(30) AS
   DECLARE @ret SalesByStore_tbl
   INSERT @ret (titleid, qty)
      SELECT t.titleid, s.store_id 
      FROM   sales s
      JOIN   titles t ON t.titleid = s.titleid
      WHERE  s.store_id = @storeid
   SELECT * FROM @ret
go
CREATE PROCEDURE BigSalesByStore @storeid varchar(30),
                                 @qty     smallint AS
   DECLARE @data SalesByStore_tbl
   INSERT @data
      EXEC SalesByStore @storeid
   SELECT titleid, qty FROM @data WHERE qty>= @qty
go
EXEC SalesByStore '7131'
EXEC BigSalesByStore '7131', 25
go
DROP PROCEDURE SalesByStore, BigSalesByStore
DROP TYPE SalesByStore_tbl

表值參數與 BULK INSERT 操作

表值參數的使用方法與其他基于數據集的變量的使用方法相似,但是,頻繁使用表值參數將比大型數據集要快。大容量操作的啟動開銷比表值參數大,與之相比,表值參數在插入數目少于 1000 的行時具有很好的執行性能。
??重用的表值參數可從臨時表緩存中受益。這一表緩存功能可比對等的 BULK INSERT 操作提供更好的伸縮性。使用小型行插入操作時,可以通過使用參數列表或批量語句(而不是 BULK INSERT 操作或表值參數)來獲得小的性能改進。但是,這些方法在編程上不太方便,并且隨著行的增加,性能會迅速下降。
??表值參數在執行性能上與對等的參數陣列實現相當甚至更好。下表說明根據插入操作的速度應使用哪種技術。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spark SQL, DataFrames and Datasets Guide Overview SQL Dat...
    Joyyx閱讀 8,348評論 0 16
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,765評論 18 399
  • 1. 簡介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優秀的...
    笨鳥慢飛閱讀 5,622評論 0 4
  • 抑郁癥又稱抑郁障礙,以顯著而持久的心境低落為主要臨床特征,是心境障礙的主要類型。臨床可見心境低落與其處境不相稱,情...
    木子火樂_4642閱讀 282評論 0 0
  • 01 這次的題目是TED的演講,主講是一個叫OK GO樂團的主唱,講的是他們樂團那些新奇有趣的MV是如何創作出來的...
    Kayhope86閱讀 191評論 0 1