Dan*_*ert 3 sql sql-server sql-server-2005
我正在研究需要删除列的数据库升级脚本(该部分很容易).在我删除列之前,我想获取值并将其移动到已存在的另一列中.
我试图用我的剧本来实现幂等,这是我似乎失败的地方.我有这样的代码......
IF EXISTS (SELECT *
FROM sys.all_columns
WHERE sys.all_columns.object_id = OBJECT_ID(N'[dbo].[MyTable]')
AND sys.all_columns.name = 'Column1')
BEGIN
UPDATE [dbo].[MyTable]
SET [Column2] = [Column1]
ALTER TABLE [dbo].[MyTable]
DROP COLUMN [Column1]
END
Run Code Online (Sandbox Code Playgroud)
无论我做什么,UPDATE
总是执行查询,即使条件为false,也会导致错误.如果我的初始条件为false,我需要做什么来阻止运行此查询?ALTER TABLE
如果条件为真,则仅在下面的语句中运行.
Ste*_*erg 12
我猜你说"UPDATE查询总是被执行,导致错误",你的意思是你得到错误:
Msg 207, Level 16, State 1 Line 6
Invalid column name 'Column1'.
这不是因为查询正在执行 - 这是一个解析错误.SQL Server在执行之前会对整个IF语句进行解析,并且在UPDATE语句中失败,因为Column1不再存在.它在ALTER TABLE语句中也失败了,但SQL Server只显示第一个错误.
顺便说一句,这就是为什么Shannon的例子有效 - 因为她的两个IF块都被一次解析,第二个类似于你的解析就好了,因为在解析脚本时,列仍然存在.我怀疑如果Shannon再次运行她的脚本(减去创建表部分),将出现相同的错误.
要解决这个问题,您只需要使用动态SQL - 在实际运行该行之前不会对其进行解析.您使用EXEC命令运行动态SQL,并将它传递给您要执行的字符串,如下所示:
IF EXISTS (SELECT *
FROM sys.all_columns
WHERE sys.all_columns.object_id = OBJECT_ID(N'[dbo].[MyTable]')
AND sys.all_columns.name = 'Column1')
BEGIN
EXEC('UPDATE [dbo].[MyTable] SET [Column2] = [Column1]')
EXEC('ALTER TABLE [dbo].[MyTable] DROP COLUMN [Column1]')
END
Run Code Online (Sandbox Code Playgroud)