T-SQL安装/升级脚本作为事务

时间:2013-02-22 15:17:48

标签: sql sql-server tsql transactions

我正在尝试编写一个T-SQL脚本,该脚本将升级当前正在部署的系统。该脚本将包含以下内容的混合:

  • 新表
  • 现有表格的新列
  • 新功能
  • 新存储过程
  • 对存储过程的更改
  • 新观点
  • 等。

由于这是一个相当大的升级,我希望脚本在其单个部分失败时回滚。我在下面概述了我的尝试代码:

DECLARE @upgrade NVARCHAR(32);
SELECT @upgrade = 'my upgrade';

BEGIN TRANSACTION @upgrade
BEGIN
    PRINT 'Starting';
    BEGIN TRY
        CREATE TABLE x ( --blah...
        );

        ALTER TABLE y --blah...
        );

        CREATE PROCEDURE z AS BEGIN ( --blah...
        END
        GO  --> this is causing trouble!

        CREATE FUNCTION a (  --blah...

    END TRY
    BEGIN CATCH    
        PRINT 'Error with transaction. Code: ' + @@ERROR + '; Message: ' + ERROR_MESSAGE();
        ROLLBACK TRANSACTION @upgrade;
        PRINT 'Rollback complete';
        RETURN;
    END TRY
END
PRINT 'Upgrade successful';
COMMIT TRANSACTION @upgrade;
GO

注意 - 我知道一些语法并不完美 - 我不得不重新键入代码

似乎我无法将存储过程放入事务块中。是否有一个原因?是因为使用了GO这个词吗?如果是这样,我如何将SP放入事务块?什么可以进入事务块有什么限制?或者,什么是我想要实现的更好的替代方案?

由于

2 个答案:

答案 0 :(得分:3)

正如Thomas Haratyk在回答中所说,你的问题是“走了”。但是,您可以根据需要在事务中拥有尽可能多的批次。这是尝试/捕获不喜欢这个。这是一个简单的概念验证:

begin tran
go
select 1
go
select 2
go
rollback

begin try
    select 1
    go
    select 2
    go
end try
begin catch
    select 1
end catch

答案 1 :(得分:2)

删除GO并使用动态sql创建程序,否则将失败。

EXEC ('create procedure z 
  as
  begin
    print "hello world"
  end')

GO不是SQL关键字,它是批处理分隔符。所以它不能包含在交易中。

请参阅这些主题以获取更多信息:

sql error:'CREATE/ALTER PROCEDURE' must be the first statement in a query batch?

Using "GO" within a transaction

http://msdn.microsoft.com/en-us/library/ms188037.aspx