T-SQL ALTER TABLE未被执行

时间:2014-03-06 15:33:59

标签: sql-server-2008 tsql alter-table

我遇到了一个奇怪的问题。代码:

if not exists(select * from sys.columns where Name = N'columnName' and Object_ID = Object_ID(N'[xxx].[yyy]'))
BEGIN
    ALTER TABLE [xxx].[yyy] ADD [columnName] [bit] NOT NULL Default 0
    update [xxx].[yyy] set [columnName] = 1
END

此SQL文件片段失败,并显示错误,指出列[columnName]不存在于update语句中。在SSMS中执行ALTER TABLE行时,它会正确执行,然后程序正常工作。可能是这个问题的根源?

1 个答案:

答案 0 :(得分:2)

最简单的方法是将其拆分为单独的批次。另外,让ALTEREXEC内运行,否则当 列存在时,您可能会遇到问题:

if not exists(select * from sys.columns where Name = N'columnName' and
              Object_ID = Object_ID(N'[xxx].[yyy]'))
BEGIN
    exec('ALTER TABLE [xxx].[yyy] ADD [columnName] [bit] NOT NULL Default 0')
END

GO

update [xxx].[yyy] set [columnName] = 1

问题是(简单化)T-SQL编译器尝试一次编译整个批次(批次由GO 1 s分隔)。所以它甚至在它开始执行任何逻辑之前都试图编译UPDATE


使其成为条件:

if not exists(select * from sys.columns where Name = N'columnName' and
              Object_ID = Object_ID(N'[xxx].[yyy]'))
BEGIN
    exec('ALTER TABLE [xxx].[yyy] ADD [columnName] [bit] NOT NULL Default 0')
    exec('update [xxx].[yyy] set [columnName] = 1')
END

我们有效地使用exec再次延迟编译,直到我们知道我们希望它发生。

顺便提一下,在这种情况下,我可能会采取第三种方式:

if not exists(select * from sys.columns where Name = N'columnName' and
              Object_ID = Object_ID(N'[xxx].[yyy]'))
BEGIN
    exec('ALTER TABLE [xxx].[yyy] ADD [columnName] [bit] NOT NULL constraint DF_XXX Default 1')
    exec('ALTER TABLE xxx.yyy DROP CONSTRAINT DF_XXX')
    exec('ALTER TABLE xxx.yyy ADD CONSTRAINT DF_XXX DEFAULT (0) FOR columnName')
END

因为前两个方法将首先更新整个表以使该列中包含0,然后然后再次更新表以将值设置为1 - 而这个最终方法应该只需要更新一次现有的行。


1 批次由客户端工具(例如SSMS)而不是SQL Server拆分。 GO 是SQL Server语句/命令,而且令人担忧的是,这些工具只使用默认批处理分隔符。它可能会从默认值更改为其他内容,但我确实建议不要使用它。