【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,且第一个存储过程执行没有问题。
-- 但是因为第二个存储过程因为主键冲突执行失败,所以最外层事务会进行回滚,因此测试表中没有插入任何数据。
-----打完收工-----