Blu*_*eft 89 sql t-sql sql-server sql-server-2008
我正在生成一个脚本,用于自动将更改从多个开发数据库迁移到暂存/生产.基本上,它需要一堆更改脚本,并将它们合并到一个脚本中,将每个脚本包装在一个IF whatever BEGIN ... END语句中.
但是,某些脚本需要一个GO语句,以便例如SQL解析器在创建新列后知道它.
ALTER TABLE dbo.EMPLOYEE
ADD COLUMN EMP_IS_ADMIN BIT NOT NULL
GO -- Necessary, or next line will generate "Unknown column: EMP_IS_ADMIN"
UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever
Run Code Online (Sandbox Code Playgroud)
但是,一旦我将其包装在一个IF块中:
IF whatever
BEGIN
ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL
GO
UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever
END
Run Code Online (Sandbox Code Playgroud)
它失败了,因为我发送了一个BEGIN没有匹配的END.但是,如果我删除GO它,它会再次抱怨一个未知的列.
有没有办法在单个IF块中创建和更新同一列?
Ode*_*ded 41
GO 不是SQL - 它只是一些MS SQL工具中使用的批处理分隔符.
如果不使用它,则需要确保语句单独执行 - 不同批次或使用动态SQL进行填充(感谢@gbn):
IF whatever
BEGIN
ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL;
EXEC ('UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever')
END
Run Code Online (Sandbox Code Playgroud)
Min*_*cob 36
我有同样的问题,最后设法使用SET NOEXEC解决它.
IF not whatever
BEGIN
SET NOEXEC ON;
END
ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL
GO
UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever
SET NOEXEC OFF;
Run Code Online (Sandbox Code Playgroud)
mel*_*okb 16
您可以尝试sp_executesql将每个GO语句之间的内容拆分为要执行的单独字符串,如下例所示.此外,还有一个@statementNo变量来跟踪正在执行哪个语句,以便在出现异常时进行简单调试.行号将相对于导致错误的相关语句编号的开头.
BEGIN TRAN
DECLARE @statementNo INT
BEGIN TRY
IF 1=1
BEGIN
SET @statementNo = 1
EXEC sp_executesql
N' ALTER TABLE dbo.EMPLOYEE
ADD COLUMN EMP_IS_ADMIN BIT NOT NULL'
SET @statementNo = 2
EXEC sp_executesql
N' UPDATE dbo.EMPLOYEE
SET EMP_IS_ADMIN = 1'
SET @statementNo = 3
EXEC sp_executesql
N' UPDATE dbo.EMPLOYEE
SET EMP_IS_ADMIN = 1x'
END
END TRY
BEGIN CATCH
PRINT 'Error occurred on line ' + cast(ERROR_LINE() as varchar(10))
+ ' of ' + 'statement # ' + cast(@statementNo as varchar(10))
+ ': ' + ERROR_MESSAGE()
-- error occurred, so rollback the transaction
ROLLBACK
END CATCH
-- if we were successful, we should still have a transaction, so commit it
IF @@TRANCOUNT > 0
COMMIT
Run Code Online (Sandbox Code Playgroud)
您也可以通过简单地将它们包装在单引号(')中来轻松执行多行语句,如上例所示.''在生成脚本时,不要忘记使用双引号()来转义字符串中包含的任何单引号.
我最终通过替换GO自己的每个实例来实现它
END
GO
---Automatic replacement of GO keyword, need to recheck IF conditional:
IF whatever
BEGIN
Run Code Online (Sandbox Code Playgroud)
这非常适合将每组语句包装在一个字符串中,但仍远非理想.如果有人找到更好的解决方案,发布它,我会接受它.
您可以将语句括在BEGIN和END中,而不是GO中
IF COL_LENGTH('Employees','EMP_IS_ADMIN') IS NULL --Column does not exist
BEGIN
BEGIN
ALTER TABLE dbo.Employees ADD EMP_IS_ADMIN BIT
END
BEGIN
UPDATE EMPLOYEES SET EMP_IS_ADMIN = 0
END
END
Run Code Online (Sandbox Code Playgroud)
(在Northwind数据库上测试)
编辑:(可能在SQL2012上测试过)
| 归档时间: |
|
| 查看次数: |
52043 次 |
| 最近记录: |