如何在SQL Server中有条件地创建存储过程?

时间:2008-09-10 23:45:28

标签: sql-server stored-procedures

作为我的集成策略的一部分,我有一些SQL脚本可以运行以更新数据库。所有这些脚本所做的第一件事就是检查它们是否需要运行,例如:

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 proc”会导致此错误:

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

哎哟!如何将CREATE PROC命令放在我的脚本中,只有在需要时才执行?

11 个答案:

答案 0 :(得分:21)

以下是我提出的建议:

将它包装在EXEC()中,如下所示:

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

像魅力一样!

答案 1 :(得分:7)

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

P.S。另一种方法是SET PARSEONLY {ON |关闭}。

答案 2 :(得分:5)

但请注意您的存储过程中的单引号 - 它们需要通过添加第二个来“转义”。第一个答案是这样做的,但万一你错过了。年轻球员的陷阱。

答案 3 :(得分:3)

对数据库进行版本控制是可行的方法,但是......为什么有条件地创建存储过程。对于视图,存储过程,函数,只需有条件地删除它们并每次都重新创建它们。如果你有条件地创建,那么你就不会清理那些有问题的数据库或者是2年前由另一个开发人员(你或我永远不会这样做)放入的黑客,他确信他会记得删除一次紧急更新。

答案 4 :(得分:2)

删除和创建的问题是您丢失了先前已应用于被删除对象的任何安全授权。

答案 5 :(得分:1)

我必须承认,我通常会同意@Peter - 我有条件地放弃,然后每次无条件地重新创建。在过去尝试猜测数据库之间的架构差异时,无论是否有任何形式的版本控制,我都被抓了太多次。

话虽如此,你自己的建议@Josh很酷。当然很有趣。 : - )

答案 6 :(得分:1)

这是一个旧线程,但Jobo不正确:Create Procedure必须是批处理中的第一个语句。因此,您无法使用Exists来测试是否存在,然后使用CreateAlter。可惜。

答案 7 :(得分:1)

我的解决方案是检查proc是否存在,如果是,则删除它,然后创建proc(与@robsoft相同的答案,但有一个例子......)

dependencies {
    implementation 'com.google.dagger:dagger:2.+'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.+'
    implementation 'com.google.dagger:dagger-android:2.+' // If you're using classes in dagger.android
    implementation 'com.google.dagger:dagger-android-support:2.+' // if you use the support libraries
    annotationProcessor 'com.google.dagger:dagger-android-processor:2.+'
}

答案 8 :(得分:1)

最好更改现有的存储过程,因为可能会添加属性和权限,并且如果删除存储的过程,这些属性和权限也会丢失。

因此,测试一下它是否不存在,如果不存在,则创建一个虚拟proc。然后在那之后使用alter语句。

IF NOT EXISTS(SELECT * FROM sysobjects WHERE Name = 'YOUR_STORED_PROC_NAME' AND xtype='P')
EXECUTE('CREATE PROC [dbo].[YOUR_STORED_PROC_NAME] as BEGIN select 0 END')
GO
ALTER  PROC [dbo].[YOUR_STORED_PROC_NAME]
....

答案 9 :(得分:-1)

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

答案 10 :(得分:-1)

使用T-SQL中的'Exists'命令查看存储的proc是否存在。如果是,请使用'Alter',否则使用'Create'