1

我正在尝试编写一个 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 放入事务块中?什么可以进入交易块有什么限制?或者,有什么比我想要实现的更好的选择?

谢谢

4

2 回答 2

3

正如 Thomas Haratyk 在他的回答中所说,你的问题是“去”。但是,您可以在事务中拥有任意数量的批次。不喜欢这样的是 try/catch。这是一个简单的概念验证:

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
于 2013-02-22T20:33:27.413 回答
2

删除 GO 并使用动态 sql 创建您的过程,否则它将失败。

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

GO 不是 SQL 关键字,它是一个批处理分隔符。因此它不能包含在事务中。

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

sql 错误:'CREATE/ALTER PROCEDURE' 必须是查询批处理中的第一条语句?

在事务中使用“GO”

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

于 2013-02-22T15:27:39.520 回答