TSQL - 在事务语句中创建存储过程

时间:2010-04-26 16:42:39

标签: sql-server sql-server-2008 stored-procedures

我有一个设置为滚动到生产的sql脚本。我把各种项目包装成单独的交易。在我们创建存储过程的每个事务中。我收到错误消息

第15行,第1行,第4行 关键字'procedure'附近的语法不正确。

我创建了这个示例脚本来说明

Begin Try
Begin Transaction 
    -- do a bunch of add/alter tables here
    -- do a bunch of data manipulation/population here

    -- create a stored proc
  create procedure dbo.test
  as
  begin
    select * from some_table
  end
Commit  
End Try
Begin Catch
    Rollback  
    Declare @Msg nvarchar(max)
    Select @Msg=Error_Message();
    RaisError('Error Occured: %s', 20, 101,@Msg) With Log;
End Catch

这个错误似乎意味着我无法在事务中创建存储过程,但我找不到任何其他说明的文档(也许google今天不是很好)。

4 个答案:

答案 0 :(得分:12)

尝试在create procedure中执行EXEC('...'),如下所示:

Begin Try
Begin Transaction 
    -- do a bunch of add/alter tables here
    -- do a bunch of data manipulation/population here

    -- create a stored proc
  EXEC ('create procedure dbo.test
  as
  begin
    select * from some_table
  end')
Commit  
End Try
Begin Catch
    Rollback  
    Declare @Msg nvarchar(max)
    Select @Msg=Error_Message();
    RaisError('Error Occured: %s', 20, 101,@Msg) With Log;
End Catch

GO

答案 1 :(得分:10)

您无法以这种方式编写脚本,因为必须在自己的批处理中运行许多语句。相反,我建议做一些类似于Red-Gate的SQL Compare如何构建其脚本的东西:

Set Xact_Abort On
GO
Begin Transaction 
GO
If object_id('tempdb..#tmpErrors') is not null
    Drop Table #tmpErrors
GO
Create Table #tmpErrors( [Error] int not null )
GO
Create Procedure dbo.Test
As
Begin
    --....
End
GO
If @@Error <> 0 AND @@TranCount >0 Rollback Transaction
GO
IF @@TranCount = 0 Begin Insert #tmpErrors (Error) Select 1 Begin Transaction End
GO

-- more statements

GO
If @@Error <> 0 AND @@TranCount >0 Rollback Transaction
GO
IF @@TranCount = 0 Begin Insert #tmpErrors (Error) Select 1 Begin Transaction End
GO

--.....

IF NOT EXISTS(SELECT * FROM #tmpErrors)
    BEGIN
        PRINT 'The database update succeeded'
        IF @@TRANCOUNT > 0 COMMIT TRANSACTION
    END
ELSE 
    BEGIN
        PRINT 'The database update failed'
        IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION
    END
GO

DROP TABLE #tmpErrors
GO

答案 2 :(得分:2)

KM提出的解决方案存在各种问题:

  • 如果您在EXEC()调用中放入的内容在语义上不正确(例如,您在存储过程中的FROM中放置了一个不存在的表),则该错误不会冒出来并且事务处理没有回滚。

  • 如果你在EXEC()调用中放入的内容在语法上是不正确的(例如你在存储过程中放入SELECTT而不是SELECT),那么事务似乎会被回滚但是一个完全神秘的错误气泡起来:

    A transport-level error has occurred when receiving results from the server. (provider: TCP Provider, error: 0 - The specified network name is no longer available.)
    

所以我仍然不知道如何在事务中创建一个过程,但仍然有事务和try-catch是有用的。

答案 3 :(得分:0)

我似乎记得你无法在事务中创建,修改或删除数据库模式对象(包括存储过程)(因为这样的结构更改不是事务性的:你不能通过数据更改将它们回滚)。