6

我使用以下方法调用几个 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再次提供的不是所需的输出。

当您在之前的示例中插入 aGO之后::setvar

DECLARE @LastInsertedID int
SELECT @LastInsertedID = SCOPE_IDENTITY()
:setvar LastInsertedID @LastInsertedID

GO

PRINT $(LastInsertedID)

它现在给你一个错误信息说:Must declare the scalar variable @LastInsertedID

再次:setvar不保存变量的实际值,@LastInsertedID而是对变量本身的引用,这当然不再存在于给定的上下文中。

我现在的问题是,我该:setvar如何正确使用,或者如何以不同的方式解决这个问题?

我感谢任何帮助或输入!

4

2 回答 2

8

“同样 :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 调用?)。

于 2014-07-03T20:28:47.103 回答
2

sqlcmd 指令(例如:setvar)根本不与您的服务器通信。将它们视为原始宏。它们更多地用于更改您在运行时会知道的事情。我想你可以想出一些奇特的方法让 sqlcmd 输出一个:setvar语句文件,然后通过另一个对 sqlcmd 的调用将其读入,但这似乎过于繁琐和脆弱。你想达到什么目的?

于 2013-07-11T01:45:53.540 回答