一个 BEGIN ... END 块中的多个语句

Multiple statements inside one BEGIN ... END block

在我的安装程序中,我必须对模式进行微小的更改:

IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'[dbo].[UserProfiles]') AND name = 'AllCheckboxesChecked')
BEGIN
  ALTER TABLE [dbo].[UserProfiles] ADD [AllCheckboxesChecked] [bit] CONSTRAINT [DF_UserProfiles_AllCheckboxesChecked] DEFAULT 0 NOT NULL
  UPDATE [dbo].[UserProfiles] SET [AllCheckboxesChecked]=1 WHERE [CheckedBoxes] LIKE '%#ALL#%'
END
GO

这在 SSMS 中有效,但在 Advanced Installer 中无效,它失败并显示错误消息,指出列 AllCheckboxesChecked 不存在。所以我尝试了:

IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'[dbo].[UserProfiles]') AND name = 'AllCheckboxesChecked')
BEGIN
  ALTER TABLE [dbo].[UserProfiles] ADD [AllCheckboxesChecked] [bit] CONSTRAINT [DF_UserProfiles_AllCheckboxesChecked] DEFAULT 0 NOT NULL
  GO
  UPDATE [dbo].[UserProfiles] SET [AllCheckboxesChecked]=1 WHERE [CheckedBoxes] LIKE '%#ALL#%'
END
GO

但这也会引发语法错误(不在 SSMS 中,只在 AdvInst 中),所以我猜 GO 在 BEGIN...END 块内是不允许的。连接配置如下:

Connection type: Microsoft SQL Server / MSDE
Connection mode: ODBC Driver
ODBC Driver: SQL Server
Use 64-bit ODBC resource: No

如果安装程序在列尚不存在的数据库上运行,我可以采取哪些步骤来创建列并填充正确的值?

GO 语句是批处理终止符,批处理中的项目仅在批处理结束时提交,在下一个 GO 语句或到达脚本末尾时.在您的情况下,包含 ALTER COLUMN 语句的批处理尚未提交,因此您会收到该列不存在的错误。您必须将脚本分成两部分。

column doesn't exist 错误是由于对 现有 对象进行验证造成的。由于 table 已经存在,解析器/编译器将验证 table 是否包含所有引用的列。

为了解决对象验证的此类时间问题,您可以将语句包含在 EXEC 中,直到 运行-time:

才会进行验证
BEGIN
  ALTER TABLE [dbo].[UserProfiles]
    ADD [AllCheckboxesChecked] [bit]
    CONSTRAINT [DF_UserProfiles_AllCheckboxesChecked] DEFAULT 0
    NOT NULL;

  EXEC(N'UPDATE [dbo].[UserProfiles]
         SET [AllCheckboxesChecked]=1
         WHERE [CheckedBoxes] LIKE ''%#ALL#%''');
END;

GO 是一个批处理终结器 - 它特定于您正在使用的工具而不是 SQL 服务器 - 所以如果您将

Statement1
GO
Statemetn2

这将作为两个单独的执行(批次)发送到 SQL 服务器。

基本上您将查询分成两批,第一批您没有关闭 BEGIN 块,第二批您没有开始 END 块!