我有一个情况,需要检查某一列(如版本号),然后应用一系列DDL更改。
问题在于我无法在IF BEGIN END代码块中执行它,因为DDL语句需要GO分隔符,而TSQL不允许这样做。
我想知道是否有任何方法可以解决这个问题。
我有一个情况,需要检查某一列(如版本号),然后应用一系列DDL更改。
问题在于我无法在IF BEGIN END代码块中执行它,因为DDL语句需要GO分隔符,而TSQL不允许这样做。
我想知道是否有任何方法可以解决这个问题。
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 的一个支持非常差的功能。尽管如此,上述内容应该是一个很好的开始。
客户端工具可以识别 GO,但服务器不会。您可以在存储过程或即席查询中使用 CREATE 而无需使用 GO。
多个“IF”语句?您可以测试后续DDL语句的成功
动态SQL?EXEC('ALTER TABLE foo WITH CHECK ADD CONSTRAINT ...')?
如上所述,GO是仅客户端批处理分隔符,用于将单个SQL文本块拆分为提交到SQL Server的批处理。