25

作为我的集成策略的一部分,我运行了一些 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' 必须是查询批处理中的第一条语句。

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

4

11 回答 11

25

这是我想出的:

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

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

奇迹般有效!

于 2008-09-11T00:16:51.100 回答
10

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

PS 另一种方法是 SET PARSEONLY { ON | 离开 }。

于 2016-04-15T12:00:39.647 回答
5

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

于 2008-09-11T03:40:40.767 回答
3

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

于 2008-09-11T04:26:41.700 回答
2

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

于 2008-12-08T16:15:35.400 回答
2

这是一个旧线程,但 Jobo 是不正确的: Create Procedure 必须是批处理中的第一条语句。因此,您不能使用Exists来测试存在,然后使用Createor Alter。遗憾。

于 2012-02-21T18:49:23.970 回答
2

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

因此,测试它是否不存在,如果不存在则创建一个虚拟 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]
....
于 2019-07-19T14:59:01.403 回答
1

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

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

于 2008-09-11T08:15:15.130 回答
1

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

IF EXISTS(SELECT * FROM sysobjects WHERE Name = 'PROC_NAME' AND xtype='P') 
BEGIN
    DROP PROCEDURE PROC_NAME
END
GO
CREATE PROCEDURE PROC_NAME
    @value  int
AS
BEGIN
    UPDATE  SomeTable
    SET     SomeColumn = 1
    WHERE   Value = @value
END
GO
于 2018-04-04T10:20:59.040 回答
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
于 2009-01-14T05:03:37.227 回答
0

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

于 2009-01-14T05:05:36.693 回答