我需要在SQL Server事务中创建两个过程。如果失败,则需要回退此事务中的create和其他执行的查询。我知道create语句必须是查询批处理中的第一条语句,但是我需要知道如何处理多个批处理的事务。
BEGIN TRANSACTION
CREATE PROCEDURE [dbo].[SP_SP-1]
@id BIGINT
AS
BEGIN
SET NOCOUNT ON;
-- SQL statements
END
GO
CREATE PROCEDURE [dbo].[SP_SP-2]
@id BIGINT
AS
BEGIN
SET NOCOUNT ON;
-- SP-2 statements
END
GO
UPDATE Table
SET Value = '1.0.0.5'
COMMIT TRANSACTION / ROLLBACK TRANSACTION
答案 0 :(得分:2)
我建议您在Handling Transactions in Nested SQL Server Stored Procedures中进一步研究此主题。
从一开始,您的语法是错误的。您无法开始事务然后创建过程,您需要做相反的事情:
CREATE PROCEDURE [dbo].[SP_SP-1]
@id bigint
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION
SET NOCOUNT ON;
-- SP-2 Statments
Update Table set Value='1.0.0.5'
END TRY
BEGIN CATCH
--handle error and perform rollback
ROLLBACK
SELECT ERROR_NUMBER() AS ErrorNumber
SELECT ERROR_MESSAGE() AS ErrorMessage
END CATCH
END
当尝试在事务范围内执行更新时,最好使用TRY
和CATCH
。
请阅读更多内容,并使用我提供的链接进行调查以获得更大的图像。
答案 1 :(得分:2)
以下是一种在事务中执行多个批处理的方法。这使用临时表来指示是否有任何批处理出错,并相应地执行最终的COMMIT
或ROLLLBACK
。
另一种方法是封装必须成单语句批处理的语句(CREATE PROCEDURE
,CREATE VIEW
等),但是当必须对文字文本中的引号进行转义时,这会变得很丑陋。 / p>
CREATE TABLE #errors (error varchar(5));
GO
BEGIN TRANSACTION
GO
CREATE PROCEDURE [dbo].[USP_SP-1]
@id bigint
AS
BEGIN
SET NOCOUNT ON;
-- SP Statments
END;
GO
IF @@ERROR <> 0 INSERT INTO #errors VALUES('error');
GO
CREATE PROCEDURE [dbo].[USP_SP-2]
@id BIGINT
AS
BEGIN
SET NOCOUNT ON;
-- SP-2 Statments
END;
GO
IF @@ERROR <> 0 INSERT INTO #errors VALUES('error');
GO
UPDATE Table SET Value='1.0.0.5'
GO
IF @@ERROR <> 0 INSERT INTO #errors VALUES('error');
GO
IF EXISTS(SELECT 1 FROM #errors)
BEGIN
IF @@TRANCOUNT > 0 ROLLBACK;
END
ELSE
BEGIN
IF @@TRANCOUNT > 0 COMMIT;
END;
GO
IF OBJECT_ID(N'tempdb..#errors', 'U') IS NOT NULL
DROP TABLE #errors;
GO
答案 2 :(得分:1)
要使用事务,您需要知道事务的含义。这是“工作单元处于提交状态或回滚状态”的意思。
因此,在使用事务时,必须知道声明的位置和关闭的位置。因此,您必须仅在父过程中开始和结束事务,否则它将作为一个工作单元工作,即,无论查询DML语句执行什么,它都使用相同的事务。
我也不明白为什么您的更新语句也超出了过程和事务部分。
应该是(请参阅我的评论,您可以使用与c Sharp相同的TRY Catch):
Create PROCEDURE [dbo].[SP_SP-1]
@id bigint
AS
BEGIN
Begin Transaction
SET NOCOUNT ON;
-- SP Statments
Exec SP_SP-2 @id --here you can pass the parameter to another procedure, but do not use transaction in another procedure, other wise it will create another transaction
If @@Error > 0 than
Rollback
Else
Commit
End
END
GO
--Do not use transaction in another procedure, otherwise, it will create another transaction which has own rollback and commit and do not participate in the parent transaction
Create PROCEDURE [dbo].[SP_SP-2]
@id BIGINT
AS
BEGIN
SET NOCOUNT ON;
-- SP-2 Statments
END
GO
答案 3 :(得分:0)
我找到了将该解决方案作为字符串执行程序来执行的解决方案,这是一种执行我想要的方法的解决方法
Begin Try
Begin Transaction
EXEC ('
Create PROCEDURE [dbo].[SP_1]
@id bigint
AS
BEGIN
SET NOCOUNT ON;
SP-1
END
GO
Create PROCEDURE [dbo].[SP_Inc_Discovery_RunDoc]
@id bigint
AS
BEGIN
SET NOCOUNT ON;
Sp-2
END')
Update Table set Value='1.0.0.5'
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