SQL Server如何处理存储过程中与事务相关的语句?

时间:2010-04-12 12:40:10

标签: sql sql-server stored-procedures transactions

假设我有一个由几个单独的SELECT,INSERT,UPDATE和DELETE语句组成的存储过程。没有明确的BEGIN TRANS / COMMIT TRANS / ROLLBACK TRANS逻辑。

SQL Server如何以事务方式处理此存储过程?每个语句都会有隐式连接吗?或者存储过程会有一个事务吗?

另外,我怎么能使用T-SQL和/或SQL Server Management Studio自行找到它?

谢谢!

3 个答案:

答案 0 :(得分:33)

只有一个连接,无论存储过程中有多少个SQL命令,它都是用来运行该过程的。

由于存储过程中没有明确的BEGIN TRANSACTION,因此每个语句都将自行运行,如果出现任何错误,则无法回滚任何更改。

但是,如果在调用存储过程之前发出BEGIN TRANSACTION,则所有语句都在事务中分组,并且可以在存储过程执行后进行COMMITted或ROLLBACK。

在存储过程中,您可以通过检查系统变量@@TRANCOUNT (Transact-SQL)的值来确定您是否在事务中运行。零表示没有事务,其他任何事件显示您所处的嵌套事务级别。根据您的SQL Server版本,您也可以使用XACT_STATE (Transact-SQL)

如果您执行以下操作:

BEGIN TRANSACTION

EXEC my_stored_procedure_with_5_statements_inside @Parma1

COMMIT

程序中的所有内容都由事务涵盖,所有6个语句(EXEC是事务所涵盖的语句,1 + 5 = 6)。如果你这样做:

BEGIN TRANSACTION

EXEC my_stored_procedure_with_5_statements_inside @Parma1
EXEC my_stored_procedure_with_5_statements_inside @Parma1

COMMIT

两个过程调用中的所有内容都由事务覆盖,所有12个语句(2个EXEC都是事务所涵盖的语句,1 + 5 + 1 + 5 = 12)。

答案 1 :(得分:1)

您可以通过创建一个简单的小存储过程来自行查找,例如将记录插入测试表。然后开始Tran;运行sp_test;回滚;这是新记录吗?如果是,则SP忽略外部事务。如果没有,那么SP只是在事务中执行的另一个语句(我很确定是这种情况)。

答案 2 :(得分:0)

您必须了解交易是会话的状态。会话可以处于显式事务状态,因为在抛出“ BEGIN TRANSACTION”命令的任何地方(在进入例程之前或在例程代码内部),在会话中至少执行了一次BEGIN TRANSACTION。否则,会话状态处于隐式事务状态。您可以有多个BEGIN TRANSACTION,但只有第一个会更改会话的行为...其他的只会增加@@ TRANCOUNT全局sesion变量。

隐式事务状态意味着所有SQL订单(DDL,DML和DCL命令)将具有看不见的集成事务范围。