2008-09-10 56 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}。

相关问题