共用方式為


DECLARE @local_variable (Transact-SQL)

適用於:SQL ServerAzure SQL 資料庫Azure SQL 受控執行個體Azure Synapse Analytics分析平台系統(PDW)Microsoft Fabric 中的 SQL 分析端點Microsoft Fabric 中的倉儲Microsoft Fabric 中的 SQL 資料庫

變數會在批次或程序 DECLARE 的主體中宣告,並使用 a SETSELECT 陳述式來指派值。 資料指標變數可以是利用這個陳述式來宣告,且可以搭配其他與資料指標相關的陳述式來使用。 宣告之後,所有變數都會初始化為 NULL,除非在宣告中提供值。

Transact-SQL 語法慣例

Syntax

下列是 SQL Server 和 Azure SQL Database 的語法:

DECLARE
{
  { @local_variable [AS] data_type [ = value ] }
  | { @cursor_variable_name CURSOR }
| { @table_variable_name [AS] <table_type_definition> }
} [ , ...n ]

<table_type_definition> ::=
    TABLE ( { <column_definition> | <table_constraint> | <table_index> } } [ , ...n ] )

<column_definition> ::=
    column_name { scalar_data_type | AS computed_column_expression }
    [ COLLATE collation_name ]
    [ [ DEFAULT constant_expression ] | IDENTITY [ (seed, increment ) ] ]
    [ ROWGUIDCOL ]
    [ <column_constraint> ]
    [ <column_index> ]

<column_constraint> ::=
{
    [ NULL | NOT NULL ]
    { PRIMARY KEY | UNIQUE }
      [ CLUSTERED | NONCLUSTERED ]
      [ WITH FILLFACTOR = fillfactor
        | WITH ( < index_option > [ , ...n ] )
      [ ON { filegroup | "default" } ]
  | [ CHECK ( logical_expression ) ] [ , ...n ]
}

<column_index> ::=
    INDEX index_name [ CLUSTERED | NONCLUSTERED ]
    [ WITH ( <index_option> [ , ... n ] ) ]
    [ ON { partition_scheme_name (column_name )
         | filegroup_name
         | default
         }
    ]
    [ FILESTREAM_ON { filestream_filegroup_name | partition_scheme_name | "NULL" } ]

<table_constraint> ::=
{
    { PRIMARY KEY | UNIQUE }
      [ CLUSTERED | NONCLUSTERED ]
      ( column_name [ ASC | DESC ] [ , ...n ]
        [ WITH FILLFACTOR = fillfactor
        | WITH ( <index_option> [ , ...n ] )
  | [ CHECK ( logical_expression ) ] [ , ...n ]
}

<table_index> ::=
{
    {
      INDEX index_name  [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ]
         (column_name [ ASC | DESC ] [ , ... n ] )
    | INDEX index_name CLUSTERED COLUMNSTORE
    | INDEX index_name [ NONCLUSTERED ] COLUMNSTORE ( column_name [ , ... n ] )
    }
    [ WITH ( <index_option> [ , ... n ] ) ]
    [ ON { partition_scheme_name ( column_name )
         | filegroup_name
         | default
         }
    ]
    [ FILESTREAM_ON { filestream_filegroup_name | partition_scheme_name | "NULL" } ]
}

<index_option> ::=
{
  PAD_INDEX = { ON | OFF }
  | FILLFACTOR = fillfactor
  | IGNORE_DUP_KEY = { ON | OFF }
  | STATISTICS_NORECOMPUTE = { ON | OFF }
  | STATISTICS_INCREMENTAL = { ON | OFF }
  | ALLOW_ROW_LOCKS = { ON | OFF }
  | ALLOW_PAGE_LOCKS = { ON | OFF }
  | OPTIMIZE_FOR_SEQUENTIAL_KEY = { ON | OFF }
  | COMPRESSION_DELAY = { 0 | delay [ Minutes ] }
  | DATA_COMPRESSION = { NONE | ROW | PAGE | COLUMNSTORE | COLUMNSTORE_ARCHIVE }
       [ ON PARTITIONS ( { partition_number_expression | <range> }
       [ , ...n ] ) ]
  | XML_COMPRESSION = { ON | OFF }
      [ ON PARTITIONS ( { <partition_number_expression> | <range> }
      [ , ...n ] ) ] ]
}

下列語法適用於 Azure Synapse Analytics 和 Parallel Data Warehouse 和 Microsoft Fabric:

DECLARE
{ { @local_variable [AS] data_type } [ = value [ COLLATE <collation_name> ] ] } [ , ...n ]

Arguments

@ local_variable

變數的名稱。 變數名稱的開頭必須是 at (@) 符號。 區域變數名稱必須遵循識別碼的規則。

  • data_type

    任何系統提供的通用語言執行平台 (CLR) 使用者定義資料表類型或別名資料類型。 變數的資料類型不可以是 textntextimage

    如需系統資料類型的詳細資訊,請參閱 資料類型。 如需 CLR 使用者定義類型或別名資料類型的詳細資訊,請參閱 CREATE TYPE

  • =

    以內嵌方式指派值給變數。 此值可以是常數或運算式,但是它必須符合變數宣告類型,或是必須可隱含轉換成該類型。 如需詳細資訊,請參閱 運算式

@ cursor_variable_name

資料指標變數的名稱。 資料指標變數名稱的開頭必須是 at (@) 符號,且必須符合識別碼的規則。

  • CURSOR

    指定變數是本機資料指標變數。

  • @ table_variable_name

    table 類型的變數名稱。 變數名稱的開頭必須是 at (@) 符號,且必須符合識別碼的規則。

  • <table_type_definition>

    定義 table 資料類型。 資料表宣告包括資料行定義、名稱、資料類型和條件約束。 唯一允許的條件約束類型是 PRIMARY KEYUNIQUENULLCHECK。 如果規則或預設定義繫結至別名資料類型,就無法利用別名資料類型來當做資料行純量資料類型。

<table_type_definition>

用來定義 中 CREATE TABLE表格的資訊子集。 這裡包括元素和必要定義。 如需詳細資訊,請參閱 CREATE TABLE。

  • n

    預留位置,表示可以指定多個變數,且可以指派這些變數的值。 宣告 表格 變數時, 表格 變數必須是陳述式中 DECLARE 唯一宣告的變數。

column_name

資料表中資料行的名稱。

  • scalar_data_type

    指定資料行是一種純量資料類型。

  • computed_column_expression

    定義計算資料行值的運算式。 它是從使用相同資料表中其他資料行的運算式計算而來。 例如,計算資料行可以具有定義 cost AS price * qty。 運算式可以是非計算資料行名稱、常數、內建函式、變數,或由一或多個運算子連接的這些選項的任何組合。 運算式不能是子查詢或使用者定義函式。 運算式不能參考 CLR 使用者定義型別。

[ 整理 collation_name ]

指定資料行的定序。 collation_name可以是 Windows 定序名稱或 SQL 定序名稱,而且僅適用於 char、varchar、textncharnvarcharntext 數據類型的數據行。 若未指定,便會將使用者定義資料類型的定序指派給這個資料行 (如果資料行是使用者定義資料類型),否則,便會指派目前資料庫的定序。

如需 Windows 和 SQL 定序名稱的詳細資訊,請參閱 COLLATE

DEFAULT

指定在插入期間未明確提供值時,提供給資料行的值。 DEFAULT 定義可以套用至任何直欄,但定義為 時間戳記 或具有 屬性 IDENTITY 的直欄除外。 DEFAULT 捨棄表格時,會移除定義。 只有常數值,例如字串;系統函數,例如 SYSTEM_USER();或 NULL 可作為預設值使用。 若要維護與舊版 SQL Server 的相容性,可以將條件約束名稱指派給 DEFAULT.

  • constant_expression

    常數、 NULL或系統函數,用作資料行的預設值。

IDENTITY

指出新資料行是識別欄位。 當資料列新增到資料表時,SQL Server 會提供該資料行的唯一累加值。 身分資料行通常與條件約束搭配 PRIMARY KEY 使用,以作為資料表的唯一資料列識別碼。 此 IDENTITY 屬性可以指派給 tinyintsmallintintdecimal(p,0)numeric(p,0) 資料行。 每份資料表都只能建立一個識別欄位。 繫結的預設值和 DEFAULT 條件約束無法與身分識別資料行搭配使用。 您必須同時指定種子和遞增,或同時不指定這兩者。 如果同時不指定這兩者,預設值便是 (1,1)。

  • seed

    載入資料表的第一個資料列所用的值。

  • increment

    加入先前載入的資料列之識別值的累加值。

ROWGUIDCOL

指出新資料行是一個資料列全域唯一識別碼資料行。 每個資料表只能指定一個 uniqueidentifier 資料行作為 ROWGUIDCOL 資料行。 屬性 ROWGUIDCOL 只能指派給 uniqueidentifier 資料行。

NULL |NOT NULL

指出變數中是否允許 null。 預設值為 NULL

主鍵

利用唯一索引來強制執行一或多個指定資料行之實體完整性的限制式。 每個表格只能建立一個 PRIMARY KEY 限制。

UNIQUE

利用唯一索引來提供一或多個指定資料行之實體完整性的限制式。 表格可以有多個 UNIQUE 限制。

CLUSTERED |NONCLUSTERED

指出已針對 or PRIMARY KEY 條件約束建立UNIQUE叢集或非叢集索引。 PRIMARY KEY 條件約束使用 CLUSTERED,條件 UNIQUE 約束使用 NONCLUSTERED

CLUSTERED 只能指定一個約束。 如果為限制指定CLUSTERED了 ,且UNIQUE也指定了限制,則PRIMARY KEYPRIMARY KEY使用 NONCLUSTERED

CHECK

透過限制可能輸入一或多個資料行的值來強制執行值域完整性的限制式。

  • logical_expression

    傳回 TRUEFALSE的邏輯運算式。

<index_option>

指定一個或多個索引選項。 您無法明確建立 table 變數的索引,也無法保留 table 變數的任何統計資料。 SQL Server 2014 (12.x) 引進語法,可讓您在資料表定義內嵌建立特定索引類型。 使用此語法,您可以在表格變數上建立索引,作為表格定義的一部分。 在某些情況下,改用暫存表格可能會改善效能,以提供完整的索引支援和統計資料。

如需這些選項的完整描述,請參閱 CREATE TABLE

資料表變數和資料列估計

Table 變數沒有散發統計資料。 在許多情況下,最佳化工具會假設表格變數具有零列或一列來建置查詢計劃。 如需詳細資訊,請檢閱資料表資料類型 - 限制事項

基於這個原因,若您預期會有較多數目的資料列 (超過 100 列),就應該謹慎使用資料表變數。 考慮使用下列替代方案:

  • 當資料列計數可能更大 (大於 100) 時,暫存資料表可能是比資料表變數更好的解決方案。

  • 對於將表格變數與其他表格聯結的查詢,請使用 RECOMPILE 提示,這會導致最佳化工具對表格變數使用正確的基數。

  • 在 Azure SQL 資料庫中,從 SQL Server 2019 (15.x) 開始,資料表變數延遲編譯功能會傳播以實際資料表變數資料列計數為基礎的基數估計值,以提供更精確的資料列計數來優化執行計劃。 如需詳細資訊,請參閱 SQL 資料庫中的智慧型查詢處理

Remarks

變數通常在批次或程序中用作區塊WHILELOOP的計數器IF...ELSE

變數只能用在運算式中,不能用來取代物件名稱或關鍵字。 若要建構動態 SQL 陳述式,請使用 EXECUTE

區域變數的範圍是其宣告所在的批次。

資料表變數不一定會常駐記憶體。 在記憶體壓力下,屬於資料表變數的分頁可以推送到 tempdb

您可以在資料表變數中定義內嵌索引。

下列陳述式可以將目前指派了資料指標的資料指標變數當做一項來源來參考:

  • CLOSE 陳述
  • DEALLOCATE 陳述
  • FETCH 陳述
  • OPEN 陳述
  • 定位 DELETEUPDATE 陳述
  • SET CURSOR variable 陳述式 (右側)

在所有的這些陳述式中,如果參考的資料指標變數存在,但目前未向其配置資料指標,SQL Server 便會引發錯誤。 如果所參考的資料指標變數不存在,SQL Server 便會產生針對其他類型的未宣告變數所產生的相同錯誤。

資料指標變數:

  • 可以是資料指標類型或另一個資料指標變數的目標。 如需詳細資訊,請參閱SET @local_variable

  • 如果游標變數目前沒有指派給它的游標,則可以參照為陳述式中 EXECUTE 輸出游標參數的目標。

  • 應該視為指向資料指標的指標。

Examples

本文中的程式碼範例會使用 或AdventureWorks2025AdventureWorksDW2025範例資料庫,您可以從 Microsoft SQL Server 範例和社群專案首頁下載。

A. 使用 DECLARE

下列範例使用名為 的 @find 區域變數來擷取以 開頭 Man的所有姓氏的連絡資訊。

USE AdventureWorks2022;
GO

DECLARE @find AS VARCHAR (30);
/* Also allowed:
DECLARE @find VARCHAR(30) = 'Man%';
*/

SET @find = 'Man%';

SELECT p.LastName,
       p.FirstName,
       ph.PhoneNumber
FROM Person.Person AS p
     INNER JOIN Person.PersonPhone AS ph
         ON p.BusinessEntityID = ph.BusinessEntityID
WHERE LastName LIKE @find;

結果集如下所示。

LastName            FirstName               Phone
------------------- ----------------------- -------------------------
Manchepalli         Ajay                    1 (11) 500 555-0174
Manek               Parul                   1 (11) 500 555-0146
Manzanares          Tomas                   1 (11) 500 555-0178

B. 將 DECLARE 與兩個變數搭配使用

下列範例會擷取在位於北美洲銷售地區且年度銷售額至少為 $2,000,000 的 Adventure Works Cycles 銷售代表姓名。

USE AdventureWorks2022;
GO

SET NOCOUNT ON;
GO

DECLARE @Group AS NVARCHAR (50), @Sales AS MONEY;

SET @Group = N'North America';
SET @Sales = 2000000;
SET NOCOUNT OFF;

SELECT FirstName,
       LastName,
       SalesYTD
FROM Sales.vSalesPerson
WHERE TerritoryGroup = @Group
      AND SalesYTD >= @Sales;

C. 宣告類型為 table 的變數

下列範例會建立變數table,以儲存陳述式子OUTPUT句中UPDATE指定的值。 之後的兩個 SELECT 陳述式會傳回 @MyTableVar 中的值,以及 Employee 資料表中更新作業的結果。 INSERTED.ModifiedDate 資料行中的結果不同於 ModifiedDate 資料表中 Employee 資料行的值。 這是因為將 AFTER UPDATE 值更新成目前日期的 ModifiedDate 觸發程序是定義在 Employee 資料表上。 不過,從 OUTPUT 傳回的資料行會反映引發觸發程序之前的資料。 如需詳細資訊,請參閱 OUTPUT 子句

USE AdventureWorks2022;
GO

DECLARE @MyTableVar TABLE (
    EmpID INT NOT NULL,
    OldVacationHours INT,
    NewVacationHours INT,
    ModifiedDate DATETIME);

UPDATE TOP (10) HumanResources.Employee
SET VacationHours = VacationHours * 1.25
OUTPUT INSERTED.BusinessEntityID,
    DELETED.VacationHours,
    INSERTED.VacationHours,
    INSERTED.ModifiedDate
INTO @MyTableVar;

--Display the result set of the table variable.
SELECT EmpID,
       OldVacationHours,
       NewVacationHours,
       ModifiedDate
FROM @MyTableVar;
GO

--Display the result set of the table.
--Note that ModifiedDate reflects the value generated by an
--AFTER UPDATE trigger.
SELECT TOP (10) BusinessEntityID,
                VacationHours,
                ModifiedDate
FROM HumanResources.Employee;
GO

D. 宣告具有內嵌索引的 table 型別變數

下列範例會建立具有叢集內嵌索引和兩個非叢集內嵌索引的 table 變數。

DECLARE @MyTableVar TABLE (
    EmpID INT NOT NULL,
    PRIMARY KEY CLUSTERED (EmpID),
    UNIQUE NONCLUSTERED (EmpID),
    INDEX CustomNonClusteredIndex NONCLUSTERED (EmpID));
GO

下列查詢會傳回上一個查詢中建立之索引的相關資訊。

SELECT * FROM tempdb.sys.indexes
WHERE object_id < 0;
GO

E. 宣告使用者定義表格類型的變數

下列範例會建立資料表值參數或稱為 @LocationTVP 的資料表變數。 此步驟需要對應的使用者定義表格類型,稱為 LocationTableType

如需如何建立使用者定義資料表類型的詳細資訊,請參閱 CREATE TYPE。 如需資料表值參數的詳細資訊,請參閱使用資料表值參數 (資料庫引擎)。

DECLARE @LocationTVP AS LocationTableType;

範例:Azure Synapse Analytics 和 Analytics Platform System (PDW)

F. 使用 DECLARE

下列範例使用名為 的 @find 區域變數來擷取以 開頭 Walt的所有姓氏的連絡資訊。

-- Uses AdventureWorks
DECLARE @find AS VARCHAR (30);
/* Also allowed:
DECLARE @find VARCHAR(30) = 'Man%';
*/

SET @find = 'Walt%';

SELECT LastName,
       FirstName,
       Phone
FROM DimEmployee
WHERE LastName LIKE @find;

G. 將 DECLARE 與兩個變數搭配使用

下列範例擷取 uses 變數,以指定表格中 DimEmployee 員工的名字和姓氏。

DECLARE @lastName AS VARCHAR (30),
    @firstName AS VARCHAR (30);

SET @lastName = 'Walt%';
SET @firstName = 'Bryan';

SELECT LastName,
       FirstName,
       Phone
FROM DimEmployee
WHERE LastName LIKE @lastName
      AND FirstName LIKE @firstName;