TSQL SET 命令在 EXEC 语句中不起作用
TSQL SET command not working inside EXEC statement
我正在尝试 运行 SQL Server Management Studio 中的以下脚本:
DECLARE @counter INT = 1
EXEC('SET '+@counter+' = '+@counter+' + 1')
但是,我得到这个错误:
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '1'-
我已经排除故障好几天了,但一无所获 - 我猜 TSQL 很可能根本不接受 EXEC 命令中的这个,但我可以用什么来代替它?
这是一个更大的脚本的一部分,上面的内容必须在 EXEC 语句中才能使其余部分正常工作..
由于多种原因,这不会起作用。
让我们从你拥有的开始:
DECLARE @counter INT = 1
EXEC('SET '+@counter+' = '+@counter+' + 1')
EXEC
期望括号内有一个字符串,但您有一个 int
(变量 @counter
),所以这是您的第一个问题。但是,奇怪的是,您在这里没有遇到转换错误;似乎 @counter
是 被解释为其值 (1
),而不是首先应用 Data Type Precedence。 (如果您尝试 SELECT 'SET '+@counter+' = '+@counter+' + 1'
,您将收到错误 “将 varchar 值 'SET ' 转换为数据类型 int 时转换失败。”)。
即使 如果 查询成功越过了这个障碍,那也会导致另一个错误,因为查询变为:
SET 1 = 1 + 1
显然这行不通,1
是 1
,没有其他数字。
其次,在“动态”语句范围之外声明的变量不能在其中引用。让我们采取以下措施:
DECLARE @Varible int = 1;
EXEC (N'SELECT @Variable;');
这个returns错误:
Must declare the scalar variable "@Variable".
如果您使用的是“动态”语句(您的语句根本不是动态的),那么您需要对变量进行参数化。这就是为什么你不应该使用 EXEC ({SQL Statement})
而应该使用 sys.sp_executesql
.
因此,对于上述内容,您得到:
DECLARE @counter INT = 1;
DECLARE @SQL nvarchar(MAX);
SET @SQL = N'SET @Variable = @Variable + 1;';
EXEC sys.sp_executesql @SQL, N'@Variable int OUTPUT',@Variable = @counter OUTPUT;
SELECT @Counter;
正如我所提到的,这毫无意义,因为上面没有任何动态内容,您的查询应该只是:
DECLARE @counter INT = 1;
SET @counter = @counter + 1;
当然,none 甚至会继续解决诸如如何 安全地 将对象注入动态语句之类的问题,但那不是'这个问题是关于什么的。正如我所提到的,这里的动态语句是多余的,因为它不是动态的,并且不需要延迟解析(例如当您 ALTER
a table 添加一列,然后尝试在同一批次中引用该列)。
如果你运行下面的脚本,它会抛出类似
的错误
Msg 137, Level 15, State 1, Line 1
Must declare the scalar variable "@counter".
BEGIN
DECLARE @counter INT = 1
EXEC('SET @counter = '+ @counter+' + 1')
END
为什么?
因为dynamic SQL
是不同范围到外部
所以可以试试这个方法(使用输出)
DECLARE @counter INT = 1
DECLARE @SQL nvarchar(50) = 'SELECT @counter2 =' + CAST(@counter + 1 AS VARCHAR(100))
exec sp_executesql @SQL, N'@counter2 int out', @counter out
SELECT @counter
我正在尝试 运行 SQL Server Management Studio 中的以下脚本:
DECLARE @counter INT = 1
EXEC('SET '+@counter+' = '+@counter+' + 1')
但是,我得到这个错误:
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '1'-
我已经排除故障好几天了,但一无所获 - 我猜 TSQL 很可能根本不接受 EXEC 命令中的这个,但我可以用什么来代替它?
这是一个更大的脚本的一部分,上面的内容必须在 EXEC 语句中才能使其余部分正常工作..
由于多种原因,这不会起作用。
让我们从你拥有的开始:
DECLARE @counter INT = 1
EXEC('SET '+@counter+' = '+@counter+' + 1')
EXEC
期望括号内有一个字符串,但您有一个 int
(变量 @counter
),所以这是您的第一个问题。但是,奇怪的是,您在这里没有遇到转换错误;似乎 @counter
是 被解释为其值 (1
),而不是首先应用 Data Type Precedence。 (如果您尝试 SELECT 'SET '+@counter+' = '+@counter+' + 1'
,您将收到错误 “将 varchar 值 'SET ' 转换为数据类型 int 时转换失败。”)。
即使 如果 查询成功越过了这个障碍,那也会导致另一个错误,因为查询变为:
SET 1 = 1 + 1
显然这行不通,1
是 1
,没有其他数字。
其次,在“动态”语句范围之外声明的变量不能在其中引用。让我们采取以下措施:
DECLARE @Varible int = 1;
EXEC (N'SELECT @Variable;');
这个returns错误:
Must declare the scalar variable "@Variable".
如果您使用的是“动态”语句(您的语句根本不是动态的),那么您需要对变量进行参数化。这就是为什么你不应该使用 EXEC ({SQL Statement})
而应该使用 sys.sp_executesql
.
因此,对于上述内容,您得到:
DECLARE @counter INT = 1;
DECLARE @SQL nvarchar(MAX);
SET @SQL = N'SET @Variable = @Variable + 1;';
EXEC sys.sp_executesql @SQL, N'@Variable int OUTPUT',@Variable = @counter OUTPUT;
SELECT @Counter;
正如我所提到的,这毫无意义,因为上面没有任何动态内容,您的查询应该只是:
DECLARE @counter INT = 1;
SET @counter = @counter + 1;
当然,none 甚至会继续解决诸如如何 安全地 将对象注入动态语句之类的问题,但那不是'这个问题是关于什么的。正如我所提到的,这里的动态语句是多余的,因为它不是动态的,并且不需要延迟解析(例如当您 ALTER
a table 添加一列,然后尝试在同一批次中引用该列)。
如果你运行下面的脚本,它会抛出类似
的错误Msg 137, Level 15, State 1, Line 1
Must declare the scalar variable "@counter".
BEGIN
DECLARE @counter INT = 1
EXEC('SET @counter = '+ @counter+' + 1')
END
为什么?
因为dynamic SQL
是不同范围到外部
所以可以试试这个方法(使用输出)
DECLARE @counter INT = 1
DECLARE @SQL nvarchar(50) = 'SELECT @counter2 =' + CAST(@counter + 1 AS VARCHAR(100))
exec sp_executesql @SQL, N'@counter2 int out', @counter out
SELECT @counter