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

时间:2015-11-16 16:20:11

标签: sql-server tsql advanced-installer

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

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中,这是有效的,但在高级安装程序中没有,它失败并显示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中),所以我想在BEGIN ... END块中不允许GO。连接配置如下:

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

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

3 个答案:

答案 0 :(得分:6)

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

为了解决对象验证的这些时间问题,您可以将语句括在EXEC中,直到运行时才会对其进行验证:

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;

答案 1 :(得分:0)

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

答案 2 :(得分:0)

GO是一个批处理终止符 - 它特定于您使用的工具而不是SQL Server - 所以如果你把

Statement1
GO
Statemetn2

它将作为两个单独的执行(批处理)发送到SQL Server。

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