2008-09-10 54 views
20

作爲我的集成策略的一部分,我有幾個SQL腳本運行以更新數據庫。這些腳本所做的第一件事是檢查他們是否需要運行,例如:如何在SQL Server中有條件地創建存儲過程?

if @version <> @expects 
    begin 
     declare @error varchar(100); 
     set @error = 'Invalid version. Your version is ' + convert(varchar, @version) + '. This script expects version ' + convert(varchar, @expects) + '.'; 
     raiserror(@error, 10, 1); 
    end 
else 
    begin 
     ...sql statements here... 
    end 

很好用!除非我需要添加存儲過程。 「create proc」命令必須是一批sql命令中唯一的命令。在我的IF語句中添加「創建過程」會導致此錯誤:

 
'CREATE/ALTER PROCEDURE' must be the first statement in a query batch. 

哎唷!如何將CREATE PROC命令放入我的腳本中,並只在需要時才執行?

回答

20

這就是我想出了:

把它包在EXEC(),像這樣:

if @version <> @expects 
    begin 
     ...snip... 
    end 
else 
    begin 
     exec('CREATE PROC MyProc AS SELECT ''Victory!'''); 
    end 

就像一個魅力!

+2

每次重新創建過程(有條件地下降)是一個更好的解決方案。如果使用exec,你什麼也得不到,並且有缺點;您的proc必須轉義字符串,並且錯誤中的任何行號都將引用與exec命令相關的行號。 – Peter 2008-09-12 07:20:29

+0

+1能夠處理除存在以外的條件(在我的情況下@@版本驅動是否創建某些特效) – cmsjr 2009-06-24 17:16:28

+1

+1 - 我用它來配置我的CRUD生成器以創建一個存根過程,如果它尚未存在,然後_改變它。這使我可以修改我存儲的特效,構建CRUD,但是_保留爲現有的procs_分配的任何權限。 – 2010-07-09 19:49:31

5

但要小心你的存儲過程中的單引號 - 他們需要通過添加第二個「逃脫」。第一個答案已經做到了,但萬一你錯過了。年輕球員的陷阱。

+0

這個答案應該是一個評論。你爲什麼不移動它? – Luiso 2015-12-16 15:32:14

3

對數據庫進行版本控制是一種方式,但是......爲什麼有條件地創建存儲過程。對於視圖,存儲過程和函數,只需有條件地刪除它們並每次重新創建它們。如果你有條件地創建,那麼你將不會清理那些有問題或在2年前被另一個開發者(你或我永遠不會這樣做)破解的數據庫,他確信他會記得刪除一次緊急更新。

1

我必須承認,我通常會同意@Peter - 我有條件地放棄,然後無條件地重新創建每一次。在過去,當我試圖對數據庫之間的模式差異進行二次猜測時,我有過很多次被發現,有或沒有任何形式的版本控制。

話雖如此,你自己的建議@Josh很酷。當然有趣。 :-)

0

丟棄和創建的問題是,您將失去之前應用於要刪除的對象的任何安全授權。

0
IF NOT EXISTS(SELECT * FROM sys.procedures WHERE name = 'pr_MyStoredProc') 
BEGIN 

    CREATE PROCEDURE pr_MyStoredProc AS ..... 
    SET NOCOUNT ON 
END 

ALTER PROC pr_MyStoredProc 
AS 
SELECT * FROM tb_MyTable 
0

在T-SQL中使用'Exists'命令來查看存儲過程是否存在。如果是,請使用'更改',否則使用'創建'

0

這是一箇舊線程,但Jobo不正確:Create Procedure必須是批處理中的第一條語句。因此,您不能使用Exists來測試是否存在,然後使用CreateAlter。可憐。

4

SET NOEXEC ON是關掉一些代碼部分好辦法

IF NOT EXISTS (SELECT * FROM sys.assemblies WHERE name = 'SQL_CLR_Functions') 
    SET NOEXEC ON 
GO 
CREATE FUNCTION dbo.CLR_CharList_Split(@list nvarchar(MAX), @delim nchar(1) = N',') 
RETURNS TABLE (str nvarchar(4000)) AS EXTERNAL NAME SQL_CLR_Functions.[Granite.SQL.CLR.Functions].CLR_CharList_Split 
GO 
SET NOEXEC OFF 

這裏找到: https://codereview.stackexchange.com/questions/10490/conditional-create-must-be-the-only-statement-in-the-batch

附:另一種方法是SET PARSEONLY {ON | OFF}。

相關問題