我使用:
调用几个sql文件:r C:\Scripts\Script1.sql
:r C:\Scripts\Script2.sql
:r C:\Scripts\Script3.sql
我对此处的:r
来电有这个想法:TransactSQL to run another TransactSQL script。 Script1.sql
脚本也可能在其代码中有其他sql脚本调用等。
但现在我想为每个脚本定义设置。例如:我定义LastInsertedID
并在调用SCOPE_IDENTITY()
之前将其设置为Script1.sql
的值。此脚本现在使用此变量并使用它。
为此,我使用了sqlcmd脚本变量(http://msdn.microsoft.com/de-de/library/ms188714.aspx)并使用以下方法设置它们:
:setvar LastInsertedID SCOPE_IDENTITY()
然后我可以在SELECT $(LastInsertedID
中写下Script1.sql
,它会给我正确的价值。
后来我发现这根本不正确,因为如果你在选择INSERT
之前处理其他$(LastInsertedID)
语句,它会给你新插入行的ID。这可能是这种情况,因为:setvar
不会保存当前SCOPE_IDENTITY()
的值,而是保存对它的引用,并在请求后再次调用它。
所以我尝试了一些不同的东西并声明了一个变量,为它分配了SCOPE_IDENTITY()
的当前值,然后用:setvar
保存了它。它看起来像这样:
DECLARE @LastInsertedID int
SELECT @LastInsertedID = SCOPE_IDENTITY()
:setvar LastInsertedID @LastInsertedID
PRINT $(LastInsertedID)
这暂时有效,并提供了正确的结果。但后来我将我的代码分成多个GO
部分,并意识到:setvar
再次提供的不是所需的输出。
在之前的示例中GO
之后插入:setvar
时:
DECLARE @LastInsertedID int
SELECT @LastInsertedID = SCOPE_IDENTITY()
:setvar LastInsertedID @LastInsertedID
GO
PRINT $(LastInsertedID)
现在它会显示一条错误消息:Must declare the scalar variable @LastInsertedID
。
再次:setvar
不保存变量@LastInsertedID
的实际值,而是保存变量本身的引用,当然在该给定的上下文中不存在。
我现在的问题是,如何正确使用:setvar
或如何以所需的输出以不同方式解决此问题?
感谢任何帮助或意见!
答案 0 :(得分:6)
"再次:setvar不保存变量@LastInsertedID的实际值,而是保存变量本身的引用,当然在该给定的上下文中不存在。"
Setvar并没有真正保存对该变量的引用。 Setvar(和变量替换)是预处理器,因此它与运行文本编辑器搜索&在运行之前替换你的文件。
这可能会使事情变得更加清晰。 SETVAR&替换发生在其他事情之前。所以这个:
DECLARE @LastInsertedID int
SELECT @LastInsertedID = SCOPE_IDENTITY()
:setvar LastInsertedID @LastInsertedID
GO
PRINT $(LastInsertedID)
变成这样:
DECLARE @LastInsertedID int
SELECT @LastInsertedID = SCOPE_IDENTITY()
GO
PRINT @LastInsertedID
然后它由SQL服务器运行。这不起作用,因为在GO语句之后不再定义@LastInsertedID。
Setvar不能用于保存GO块之间的值。每个区块都有自己的范围和范围。自己的一组SQL变量。您需要在同一个GO块中运行所有代码,或者找到另一种方法在两个不同的块之间传递数据(临时表?全局临时表?proc调用?)。
答案 1 :(得分:1)
sqlcmd指令(例如:setvar
)根本不与您的服务器通信。将它们视为原始宏。他们更倾向于改变您在运行时知道的事情。我想你可以想出一些花哨的方法让sqlcmd输出一个:setvar
语句的文件,然后用另一个调用sqlcmd读取它,但这看起来过于繁琐和脆弱。你想要完成什么?