使用方法:setvar正常吗?

时间:2013-07-10 20:34:13

标签: sql sql-server tsql sqlcmd

我使用:

调用几个sql文件
:r C:\Scripts\Script1.sql
:r C:\Scripts\Script2.sql
:r C:\Scripts\Script3.sql

我对此处的:r来电有这个想法:TransactSQL to run another TransactSQL scriptScript1.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或如何以所需的输出以不同方式解决此问题?

感谢任何帮助或意见!

2 个答案:

答案 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读取它,但这看起来过于繁琐和脆弱。你想要完成什么?