Tho*_*del 5 sql t-sql sql-server sqlcmd
我使用以下命令调用几个sql文件:
:r C:\Scripts\Script1.sql
:r C:\Scripts\Script2.sql
:r C:\Scripts\Script3.sql
Run Code Online (Sandbox Code Playgroud)
我对这里的:r调用有这个想法:TransactSQL运行另一个TransactSQL脚本.该Script1.sql脚本也可能在其代码中有其他sql脚本调用等.
但现在我想为每个脚本定义设置.例如:我在调用之前定义LastInsertedID并将其设置为SCOPE_IDENTITY()right 的值Script1.sql.此脚本现在使用此变量并使用它.
为此,我使用了sqlcmd脚本变量(http://msdn.microsoft.com/de-de/library/ms188714.aspx)并使用以下方法设置它们:
:setvar LastInsertedID SCOPE_IDENTITY()
Run Code Online (Sandbox Code Playgroud)
然后我可以写入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)
Run Code Online (Sandbox Code Playgroud)
这再次起作用,并提供了正确的结果.但后来我将我的代码分成多个GO部分,并意识到:setvar再次提供的不是所需的输出.
当您在之前的示例中插入GO之后:setvar:
DECLARE @LastInsertedID int
SELECT @LastInsertedID = SCOPE_IDENTITY()
:setvar LastInsertedID @LastInsertedID
GO
PRINT $(LastInsertedID)
Run Code Online (Sandbox Code Playgroud)
它现在给你一个错误信息说:Must declare the scalar variable @LastInsertedID.
同样:setvar不保存变量的实际值,@LastInsertedID而是保存变量本身的引用,当然在该给定的上下文中不存在.
我现在的问题是,我如何:setvar正确使用或如何以所需的输出不同地解决这个问题?
我感谢任何帮助或输入!
"再说一遍:setvar不保存变量@LastInsertedID的实际值,而是保存变量本身的引用,当然在该给定的上下文中不存在."
Setvar并没有真正保存对变量的引用.Setvar(和变量替换)是预处理器,因此它与在运行文件编辑器之前运行文本编辑器搜索和替换文件相同.
这可能会使事情变得更加清晰.SETVAR和替换发生在其他任何事情之前.所以这:
DECLARE @LastInsertedID int
SELECT @LastInsertedID = SCOPE_IDENTITY()
:setvar LastInsertedID @LastInsertedID
GO
PRINT $(LastInsertedID)
Run Code Online (Sandbox Code Playgroud)
变成这样:
DECLARE @LastInsertedID int
SELECT @LastInsertedID = SCOPE_IDENTITY()
GO
PRINT @LastInsertedID
Run Code Online (Sandbox Code Playgroud)
然后它由SQL服务器运行.这不起作用,因为在GO语句之后不再定义@LastInsertedID.
Setvar不能用于保存GO块之间的值.每个块都有自己的范围和自己的SQL变量集.您需要在同一个GO块中运行所有代码,或者找到另一种方法在两个不同的块之间传递数据(临时表?全局临时表?proc调用?).
sqlcmd 指令(例如:setvar)根本不与您的服务器通信。将它们视为原始宏。它们更多地用于改变您在运行时知道的事情。我想您可以想出一些奇特的方法来让 sqlcmd 输出一个:setvar语句文件,然后通过另一个对 sqlcmd 的调用将其读入,但这似乎过于麻烦和脆弱。你想达到什么目的?