变量 (Transact-SQL)
适用于: SQL Server Azure SQL 数据库 Azure SQL 托管实例 Azure Synapse Analytics 分析平台系统 (PDW) Microsoft Fabric 中的 SQL 分析端点 Microsoft Fabric 中的仓库
Transact-SQL 局部变量是可以保存单个特定类型数据值的对象。 批处理和脚本中的变量通常用于:
- 作为计数器,可以计算执行循环的次数,或控制循环的执行次数。
- 保存数据值以供控制流语句测试。
- 保存存储过程返回代码要返回的数据值或函数返回值。
注解
一些 Transact-SQL 系统函数的名称以两个 at 符号 (@@
) 开头。 尽管在早期版本的 SQL Server 中,函数 @@
称为全局变量, @@
但函数不是变量,它们的行为与变量不同。 这些 @@
函数是系统函数,其语法用法遵循函数的规则。
不能在视图中使用变量。
事务回滚不影响对变量所做的更改。
声明 Transact-SQL 变量
该 DECLARE
语句通过以下方式初始化 Transact-SQL 变量:
指定一个名称。 名称的首字符必须为一个
@
。指定系统提供的或用户定义的数据类型和长度。 对于数值变量还指定精度和小数位数。 对于 XML 类型的变量,可以分配可选的架构集合。
将值设置为
NULL
.
例如,以下DECLARE
语句创建一个名为 int 数据类型的局部变量@mycounter
。 默认情况下,此变量的值为 NULL
.
DECLARE @MyCounter INT;
若要声明多个局部变量,请在定义的第一个局部变量后使用一个逗号,然后指定下一个局部变量名称和数据类型。
例如,以下 DECLARE
语句将创建三个名为 @LastName
@StateProvince
/> 的局部变量,并将每个变量初始化为 NULL
:
DECLARE @LastName NVARCHAR(30), @FirstName NVARCHAR(20), @StateProvince NCHAR(2);
在另一个示例中,以下DECLARE
语句将创建一个名为布尔变量的布尔变量,该变量@IsActive
声明为位,0
其值为 (false
):
DECLARE @IsActive BIT = 0;
变量范围
变量的作用域就是可以引用该变量的 Transact-SQL 语句的范围。 变量的范围从声明的点持续到声明它的批处理或存储过程的末尾。 例如,以下脚本生成语法错误,因为变量在一个批处理中声明(由 GO
关键字分隔)并在另一个批中引用:
USE AdventureWorks2022;
GO
DECLARE @MyVariable INT;
SET @MyVariable = 1;
GO
SELECT BusinessEntityID,
NationalIDNumber,
JobTitle
FROM HumanResources.Employee
WHERE BusinessEntityID = @MyVariable;
变量具有局部范围,并且仅在定义变量的批处理或过程中可见。 在下面的示例中,为执行 sp_executesql
而创建的嵌套作用域无权访问在较高作用域中声明的变量,并返回和错误。
DECLARE @MyVariable INT;
SET @MyVariable = 1;
EXECUTE sp_executesql N'SELECT @MyVariable'; -- this produces an error
在 Transact-SQL 变量中设置值
首次声明变量时,其值设置为 NULL
。 若要向变量赋值,请使用 SET
语句。 这是为变量赋值的首选方法。 变量还可以通过在语句的选择 SELECT
列表中被引用来分配值。
若要通过使用 SET 语句为变量赋值,请包含变量名和需要赋给变量的值。 这是为变量赋值的首选方法。 例如,下面的批处理声明两个变量、为它们赋值并在 WHERE
语句的 SELECT
子句中予以使用:
USE AdventureWorks2022;
GO
-- Declare two variables.
DECLARE @FirstNameVariable NVARCHAR(50),
@PostalCodeVariable NVARCHAR(15);
-- Set their values.
SET @FirstNameVariable = N'Amy';
SET @PostalCodeVariable = N'BA5 3HX';
-- Use them in the WHERE clause of a SELECT statement.
SELECT LastName,
FirstName,
JobTitle,
City,
StateProvinceName,
CountryRegionName
FROM HumanResources.vEmployee
WHERE FirstName = @FirstNameVariable
OR PostalCode = @PostalCodeVariable;
GO
变量也可以通过选择列表中当前所引用的值赋值。 如果在选择列表中引用变量,则应为其分配标量值,否则 SELECT
语句应仅返回一行。 例如:
USE AdventureWorks2022;
GO
DECLARE @EmpIDVariable INT;
SELECT @EmpIDVariable = MAX(EmployeeID)
FROM HumanResources.Employee;
GO
警告
如果单个 SELECT
语句中有多个赋值子句,SQL Server 不保证表达式的计算顺序。 仅当赋值之间有引用时,效果才可见。
SELECT
如果语句返回多个行,并且变量引用非标表达式,则变量将设置为结果集中最后一行中为表达式返回的值。 例如,在以下批处理 @EmpIDVariable
中,设置为 BusinessEntityID
返回的最后一行的值,即 1
:
USE AdventureWorks2022;
GO
DECLARE @EmpIDVariable INT;
SELECT @EmpIDVariable = BusinessEntityID
FROM HumanResources.Employee
ORDER BY BusinessEntityID DESC;
SELECT @EmpIDVariable;
GO
示例
以下脚本创建一个小的测试表并向其填充 26 行。 脚本使用变量来执行下列三个操作:
- 通过控制循环执行的次数来控制插入的行数。
- 提供插入整数列的值。
- 作为表达式一部分生成插入字符列的字母的函数。
-- Create the table.
CREATE TABLE TestTable (cola INT, colb CHAR(3));
GO
SET NOCOUNT ON;
GO
-- Declare the variable to be used.
DECLARE @MyCounter INT;
-- Initialize the variable.
SET @MyCounter = 0;
-- Test the variable to see if the loop is finished.
WHILE (@MyCounter < 26)
BEGIN;
-- Insert a row into the table.
INSERT INTO TestTable
VALUES
-- Use the variable to provide the integer value
-- for cola. Also use it to generate a unique letter
-- for each row. Use the ASCII function to get the
-- integer value of 'a'. Add @MyCounter. Use CHAR to
-- convert the sum back to the character @MyCounter
-- characters after 'a'.
(
@MyCounter,
CHAR((@MyCounter + ASCII('a')))
);
-- Increment the variable to count this iteration
-- of the loop.
SET @MyCounter = @MyCounter + 1;
END;
GO
SET NOCOUNT OFF;
GO
-- View the data.
SELECT cola, colb FROM TestTable;
GO
DROP TABLE TestTable;
GO