为什么即使应该完成Alter Table命令,此更新也会抛出错误?

时间:2011-01-24 01:00:36

标签: sql-server

这对我来说一直是一个令人讨厌的问题,我很想知道这些SQL Batch命令无法正常工作的原因。

我有一张表用于保存系统的配置设置。添加新设置后,我们会向表中添加一个新字段。在更新期间,我需要使用相同的脚本更改服务器上的大量数据库。通常,它们都处于相同的状态,我可以执行以下操作:

Alter Table Configuration Add ShowClassesInCheckin bit;
GO

Update Configuration Set ShowClassesInCheckin=ShowFacilitiesInCheckin;
GO

这很好用。但是,有时一个或两个数据库会更新,所以我想编写条件逻辑,只有在该字段尚不存在时才进行这些更改:

if Not Exists(select * from sys.columns where Name = N'ShowClassesInCheckin' AND Object_ID = Object_ID(N'Configuration'))
BEGIN
    Alter Table Configuration Add ShowClassesInCheckin bit;
    Update Configuration Set ShowClassesInCheckin=ShowFacilitiesInCheckin;
END;
GO

在这种情况下,我收到一个错误:“无效的列名'ShowClassesInCheckin'”现在,这是有道理的,因为在调用Update之前批处理表没有在批处理中进行调用(如果没有Alter和Update之间的“GO”。但这没有帮助......我仍然不知道如何实现我的目标......

2 个答案:

答案 0 :(得分:5)

整个SQL脚本在执行之前进行解析。在解析阶段,该列将不存在,因此解析器会生成错误。在执行脚本的第一行之前引发错误。

解决方案是动态SQL:

exec (N'Update Configuration Set ShowClassesInCheckin=ShowFacilitiesInCheckin;')

在达到exec之前不会对此进行解析,到那时,该列将存在。

答案 1 :(得分:0)

应该有效的替代方案是重新引入go。这意味着您需要使用其他内容作为更新的条件,可能基于数据库名称。

if Not Exists(select * from sys.columns where Name = N'ShowClassesInCheckin' AND Object_ID = Object_ID(N'Configuration'))
BEGIN
    Alter Table Configuration Add ShowClassesInCheckin bit;
END;
GO

if *new condition here*
BEGIN
    Update Configuration Set ShowClassesInCheckin=ShowFacilitiesInCheckin;
END;
GO