2013-07-10 28 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調用?)之間傳遞數據的方法。