我有一种情况,我想检查某个列(如版本号),然后应用一堆ddl更改
麻烦是我无法在IF BEGIN END块中执行此操作,因为DDL语句需要在它们之间使用GO分隔符,而TSQL不允许这样做.
我想知道是否有办法实现这一目标
您不需要使用完整的块.如果您不使用BEGIN/END(包括单个DDL语句),则条件将完整地执行下一个语句.这相当于在Pascal,C等中的if的行为.当然,这意味着你将不得不一遍又一遍地重新检查你的状况.这也意味着使用变量来控制脚本的行为几乎是不可能的.
[编辑:CREATE PROCEDURE在下面的示例中不起作用,因此我将其更改为其他内容并移动了CREATE PROCEDURE以进行下面的更广泛讨论]
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
...
Run Code Online (Sandbox Code Playgroud)
或类似的东西,取决于你的条件.
不幸的是,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
Run Code Online (Sandbox Code Playgroud)
如果你确实需要条件逻辑来决定做什么,那么我所知道的唯一方法是使用EXECUTE将DDL语句作为字符串运行.
If ((SELECT Version FROM table WHERE... ) <= 15)
EXECUTE 'CREATE PROC dbo.abc
AS
....
')
Run Code Online (Sandbox Code Playgroud)
但这非常痛苦.你必须逃避程序正文中的任何引号,这真的很难读.
根据您需要应用的更改,您可以看到所有这些变得非常难看.以上甚至不包括错误检查,这本身就是一种皇家的痛苦.这就是为什么大量的工具制造者通过找出自动创建部署脚本的方法来谋生.
抱歉; 对于一切都没有简单的"正确"方式.这只是TSQL支持很差的东西.不过,上述应该是一个良好的开端.