2013-07-10 30 views
2

我打电话用几个SQL文件:如何正确使用setvar?

: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,并在Script1.sql的呼叫之前将其设置为值SCOPE_IDENTITY()。这个脚本现在使用这个变量并且与它一起工作。

要做到这一点我用的sqlcmd脚本变量(http://msdn.microsoft.com/de-de/library/ms188714.aspx),并通过设置它们:

:setvar LastInsertedID SCOPE_IDENTITY() 

然后我可以写在Script1.sqlSELECT $(LastInsertedID和它会给我正确的值。

后来我发现这是不正确的,因为如果您在选择$(LastInsertedID)之前先处理其他INSERT声明,它会为您提供新插入行的ID。这可能是这种情况,因为:setvar不保存当前的SCOPE_IDENTITY()的值,而是对其进行引用,并在请求后再次调用它。

所以我尝试了一些不同的东西,并声明了一个变量,将其赋值为当前值SCOPE_IDENTITY(),然后用:setvar保存。它看起来像这样:

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

这再次工作,并提供了正确的结果。但后来我把我的代码分成了多个GO部分,并意识到:setvar再次提供不了所需的输出。

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

GO 

PRINT $(LastInsertedID) 

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

当你插入之前的例子中的:setvarGO

再次:setvar不保存变量@LastInsertedID的实际值,但此外还引用了变量本身,当然在该给定的上下文中不再存在。

我现在的问题是,我该如何恰当地使用:setvar或者我如何以期望的输出方式解决这个问题?

我感谢任何帮助或输入!

回答

1

sqlcmd指令(例如:setvar)根本不与您的服务器进行通信。把它们想象成一个原始宏观。它们更适合于改变在运行时会知道的事情。我想你可以想出一些奇特的方式让sqlcmd输出一个:setvar语句的文件,然后用另一个调用sqlcmd读入它,但看起来过于繁琐和脆弱。你想达到什么目的?“

+0

我想设置一些值,然后使用这些值运行脚本。例如:将id设置为1,运行脚本,该脚本为ID为1的条目插入一些附加数据。稍后重新使用它,并将id设置为2.所以基本上是一个简单的函数调用,但带有脚本文件。 –

+0

这样做。你可以像':setvar ID 1'那样做,然后在脚本的SQL部分执行'insert into dbo.tbl($(ID))'或者将它分配给一个SQL变量(例如@id)。对于所有意图和目的,在运行时将$(ID)视为由sqlcmd替换为变量值的静态文本。 –

+0

啊...我以为你想要帮助。成为一个屁股不是一个很好的方法来实现这一目标。也就是说,SQL变量填充您尝试使用sqlcmd变量填充的角色。为什么,特别是,你觉得你需要分配一个sqlcmd变量?你想用sqlcmd变量来完成什么,你不能使用SQL变量? –

4

”再说一遍:s​​etvar不会保存变量@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调用?)之间传递数据的方法。