我有一个设置为滚动到生产的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今天不是很好)。
答案 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)
我似乎记得你无法在事务中创建,修改或删除数据库模式对象(包括存储过程)(因为这样的结构更改不是事务性的:你不能通过数据更改将它们回滚)。