【SQL】关于存储过程调用过程中事务的点点滴滴

1、调用两个存储过程

----------------------------------------------------------------
-- 表[dbo].[aaa_test]中[id]为主键
----------------------------------------------------------------

-- 存储过程1
ALTER PROCEDURE [dbo].[aaa_test_proc1]
    @p_id    int,
    @p_name    varchar(50)
AS
BEGIN
    INSERT INTO [dbo].[aaa_test]
               ([id]
               ,[name])
         VALUES
               (@p_id
               ,@p_name)
END

----------------------------------------------------------------

-- 存储过程2
ALTER PROCEDURE [dbo].[aaa_test_proc2]
    @p_id    int,
    @p_name    varchar(50)
AS
BEGIN
    INSERT INTO [dbo].[aaa_test]
               ([id]
               ,[name])
         VALUES
               (@p_id
               ,@p_name)
END

----------------------------------------------------------------

-- 调用两个存储过程
exec dbo.aaa_test_proc1 '1','事务测试1'
exec dbo.aaa_test_proc2 '1','事务测试2'

----------------------------------------------------------------

-- 结果
--(1 行受影响)
--消息 2627,级别 14,状态 1,过程 aaa_test_proc2,第 11 行
--违反了 PRIMARY KEY 约束 'PK_aaa_test'。不能在对象 'dbo.aaa_test' 中插入重复键。
--语句已终止。

-- 表[dbo].[aaa_test]:
id
name
1
事务测试1






-- 【结论】:不明确指定事务时,两次存储过程调用是分开的两个事务

2、在同一个事务中调用两个存储过程,没有事务的嵌套

----------------------------------------------------------------
-- 表[dbo].[aaa_test]中[id]为主键
----------------------------------------------------------------

-- 存储过程1
ALTER PROCEDURE [dbo].[aaa_test_proc1]
    @p_id    int,
    @p_name    varchar(50)
AS
BEGIN
    INSERT INTO [dbo].[aaa_test]
               ([id]
               ,[name])
         VALUES
               (@p_id
               ,@p_name)
END

----------------------------------------------------------------

-- 存储过程2
ALTER PROCEDURE [dbo].[aaa_test_proc2]
    @p_id    int,
    @p_name    varchar(50)
AS
BEGIN
    INSERT INTO [dbo].[aaa_test]
               ([id]
               ,[name])
         VALUES
               (@p_id
               ,@p_name)
END

----------------------------------------------------------------

-- 调用两个存储过程
BEGIN TRY 
    BEGIN TRAN 
        exec dbo.aaa_test_proc1 '1','事务测试1'
        exec dbo.aaa_test_proc2 '1','事务测试2'
    COMMIT TRAN 
END TRY 
BEGIN CATCH 
    ROLLBACK TRAN 
END CATCH

----------------------------------------------------------------

-- 结果
--(1 行受影响)

-- 表[dbo].[aaa_test]:
id
name
-- 【结论】:在同一个事务中调用多个存储过程,其中一个出错后,全部回滚。

3、事务嵌套

----------------------------------------------------------------
-- 表[dbo].[aaa_test]中[id]为主键
----------------------------------------------------------------

-- 存储过程1
ALTER PROCEDURE [dbo].[aaa_test_proc1]
    @p_id    int,
    @p_name    varchar(50)
AS
BEGIN
    BEGIN TRY 
        BEGIN TRAN 
            INSERT INTO [dbo].[aaa_test]
                       ([id]
                       ,[name])
                 VALUES
                       (@p_id
                       ,@p_name)
            COMMIT TRAN 
    END TRY 
    BEGIN CATCH 
        ROLLBACK TRAN 
    END CATCH
END

----------------------------------------------------------------

-- 存储过程2
ALTER PROCEDURE [dbo].[aaa_test_proc2]
    @p_id    int,
    @p_name    varchar(50)
AS
BEGIN
    INSERT INTO [dbo].[aaa_test]
               ([id]
               ,[name])
         VALUES
               (@p_id
               ,@p_name)
END

----------------------------------------------------------------

-- 调用两个存储过程
BEGIN TRY 
    BEGIN TRAN 
        exec dbo.aaa_test_proc1 '1','事务测试1'
        exec dbo.aaa_test_proc2 '1','事务测试2'
    COMMIT TRAN 
END TRY 
BEGIN CATCH 
    ROLLBACK TRAN 
END CATCH

----------------------------------------------------------------

-- 结果
--(1 行受影响)

-- 表[dbo].[aaa_test]:
id
name
-- 【结论】:事务嵌套时,以最外层事务的执行情况为准。
-- 例子中,虽然在第一个存储过程的子事务中有commit tran,且第一个存储过程执行没有问题。
-- 但是因为第二个存储过程因为主键冲突执行失败,所以最外层事务会进行回滚,因此测试表中没有插入任何数据。

-----打完收工-----

原文地址:https://www.cnblogs.com/WillYang/p/3238541.html