在SQL Server上运行有条件的DDL语句

9

我有一个情况,需要检查某一列(如版本号),然后应用一系列DDL更改。

问题在于我无法在IF BEGIN END代码块中执行它,因为DDL语句需要GO分隔符,而TSQL不允许这样做。

我想知道是否有任何方法可以解决这个问题。

3个回答

7
您不需要使用完整的代码块。如果您没有使用BEGIN / END,则条件语句将执行其余的下一个语句,包括单个DDL语句。这等同于Pascal、C等语言中的if语句的行为。当然,这意味着您将不断地检查您的条件。这也意味着使用变量来控制脚本的行为基本上是不可行的。
If ((SELECT Version FROM table WHERE... ) <= 15)
CREATE TABLE dbo.MNP (
....
)
GO

If ((SELECT Version FROM table WHERE... ) <= 15)
ALTER TABLE dbo.T1
ALTER COLUMN Field1 AS CHAR(15)
GO

...

根据您的条件,可能会是类似于这样的东西。

不幸的是,CREATE/ALTER PROCEDURE和CREATE/ALTER VIEW有特殊的要求,使得它们更难处理。它们基本上需要成为语句中唯一的内容,因此您无法将它们与IF结合使用。

对于许多情况,当您想要“升级”对象时,可以将其视为有条件的删除,然后再创建:

IF(EXISTS(SELECT * FROM sys.objects WHERE type='p' AND object_id = OBJECT_ID('dbo.abc')))
DROP PROCEDURE dbo.abc
GO

CREATE PROCEDURE dbo.abc
AS
    ...
GO

如果您确实需要条件逻辑来决定要做什么,那么我知道的唯一方法是使用EXECUTE将DDL语句作为字符串运行。

If ((SELECT Version FROM table WHERE... ) <= 15)
EXECUTE 'CREATE PROC dbo.abc 
AS
    ....
')

但这样做很痛苦。你必须转义任何存储过程主体中的引号,而且很难阅读。

根据您需要应用的更改,您会发现所有这些都会变得非常丑陋。上面的内容甚至不包括错误检查,这本身就是一个巨大的烦恼。这就是为什么大量工具制造商通过找到自动创建部署脚本的方法来谋生。

对不起,没有一种适用于所有情况的简单“正确”方式。这只是 TSQL 的一个支持非常差的功能。尽管如此,上述内容应该是一个很好的开始。


1
如果 ((SELECT Version FROM table WHERE... ) <= 15) 创建存储过程 dbo.abc AS 这个语法不起作用.... 它说关键字 'PROCEDURE' 附近有语法错误。 - np-hard
1
你说得对!抱歉。看到了吗?我告诉你这很混乱(教训我凌晨回答问题)。T-SQL要求CREATE PROC必须是“批处理”中的唯一语句(GO之间)。我修复了上面的示例,并向您提供了更多有关该问题的详细信息。祝好运。 - Euro Micelli

1

客户端工具可以识别 GO,但服务器不会。您可以在存储过程或即席查询中使用 CREATE 而无需使用 GO。


1

多个“IF”语句?您可以测试后续DDL语句的成功

动态SQL?EXEC('ALTER TABLE foo WITH CHECK ADD CONSTRAINT ...')?

如上所述,GO是仅客户端批处理分隔符,用于将单个SQL文本块拆分为提交到SQL Server的批处理。


动态SQL很快就会变得混乱,因为我在存储过程内部使用了动态SQL。 - np-hard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接