我有一个运行一些命令的存储过程。我不希望这些命令被包装在存储过程的事务中。如果第4条命令失败,我希望保留第1条,第2条和第3条而不回滚。
是否可以编写存储过程,使其不能全部作为一个大事务来执行?
我有一个运行一些命令的存储过程。我不希望这些命令被包装在存储过程的事务中。如果第4条命令失败,我希望保留第1条,第2条和第3条而不回滚。
是否可以编写存储过程,使其不能全部作为一个大事务来执行?
Answers:
所有交易都不会在单个交易中执行。看一下这个例子:
use TestDB;
go
if exists (select 1 from sys.tables where object_id = object_id('dbo.TestTranTable1'))
drop table dbo.TestTranTable1;
create table dbo.TestTranTable1
(
id int identity(1, 1) not null,
some_int int not null
default 1
);
go
insert into dbo.TestTranTable1
default values;
go 4
select *
from dbo.TestTranTable1;
if exists (select 1 from sys.sql_modules where object_id = object_id('dbo.ChangeValues'))
begin
drop proc dbo.ChangeValues;
end
go
create proc dbo.ChangeValues
as
update dbo.TestTranTable1
set some_int = 11
where id = 1;
update dbo.TestTranTable1
set some_int = 12
where id = 2;
update dbo.TestTranTable1
set some_int = 13
where id = 3;
-- this will error out (arithmetic overflow)
update dbo.TestTranTable1
set some_int = 2147483648
where id = 4;
go
exec dbo.ChangeValues;
select *
from dbo.TestTranTable1;
这是输出:
通过创建扩展事件会话来监视sql_transaction
事件,以下是执行的输出dbo.ChangeValues
:
如您在上面的屏幕截图中所见,四个语句中的每一个都有单独的事务。前3次提交,最后一次由于错误而回滚。
我认为这可能是关于批处理还是事务的混淆。
一个交易是声明,要么成功,要么失败,因为一个单位的语句或集。所有DDL语句本身都在事务中(即,如果您更新100行,但第98行抛出错误,则不会更新任何行)。您也可以使用BEGIN TRANSACTION
,然后使用COMMIT
或将一系列语句包装在事务中ROLLBACK
。
一个批次是一系列被一起执行的语句。存储过程是批处理的一个示例。在存储过程中,如果一个语句失败并且存在错误陷阱(通常为TRY/CATCH
块),则后续语句将不执行。
我怀疑您的问题是发生错误时批处理将被取消,因为存储的proc本身或外部作用域(例如调用此过程的应用程序或存储的proc)都存在错误陷阱。如果是这种情况,则解决起来就比较棘手,因为您需要在捕获错误的任何范围内调整错误的处理方式。
sql server中的所有内容都包含在一个事务中。
当您显式指定时begin transaction
,end transaction
它称为Explicit Transaction。当您不这样做时,它就是隐式事务。
要切换您所处的模式,请使用
set implicit_transactions on
要么
set implicit_transactions off
select @@OPTIONS & 2
如果以上返回2,则您处于隐式事务模式。如果返回0,则表示您处于自动提交状态。
事务是ALL还是什么都不会使数据库保持一致状态..记住ACID属性。
CREATE TABLE [dbo].[Products](
[ProductID] [int] NOT NULL,
[ProductName] [varchar](25) NULL,
[DatabaseName] [sysname] NOT NULL,
CONSTRAINT [pk_Product_ID_ServerName] PRIMARY KEY CLUSTERED
(
[ProductID] ASC,
[DatabaseName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
-- insert some data
INSERT INTO [dbo].[Products]([ProductID], [ProductName], [DatabaseName])
SELECT 1, N'repl1_product1', N'repl1' UNION ALL
SELECT 1, N'repl2_product1_02', N'repl2' UNION ALL
SELECT 1, N'repl3_product1_03', N'repl3' UNION ALL
SELECT 2, N'repl1_product1_01', N'repl1' UNION ALL
SELECT 2, N'repl2_product1', N'repl2' UNION ALL
SELECT 2, N'repl3_product1_03', N'repl3' UNION ALL
SELECT 3, N'repl1_product1_01', N'repl1' UNION ALL
SELECT 3, N'repl2_product1_02', N'repl2' UNION ALL
SELECT 3, N'repl3_product1', N'repl3' UNION ALL
SELECT 4, N'repl1_product1_01', N'repl1' UNION ALL
SELECT 4, N'repl2_product1_02', N'repl2' UNION ALL
SELECT 5, N'repl1_product1_01', N'repl1' UNION ALL
SELECT 5, N'repl2_product1_02', N'repl2'
-立即创建SP-注意前3个将成功,第4个将由于字符串截断而失败...
IF OBJECT_ID ('usp_UpdateProducts', 'P') IS NOT NULL
DROP PROCEDURE usp_UpdateProducts;
GO
create procedure usp_UpdateProducts
as
begin try
update Products
set ProductName = 'repl1_product1'
where DatabaseName = 'repl1'and ProductID = 1;
update Products
set ProductName = 'repl2_product1'
where DatabaseName = 'repl2' and ProductID = 2;
update Products
set ProductName = 'repl3_product1'
where DatabaseName = 'repl3' and ProductID = 3;
update Products
set ProductName = 'repl3_product1_03&&&&&&&&&&39399338492w9924389234923482' -- this will fail ...
where DatabaseName = 'repl3' and ProductID = 4;
SELECT 1/0;
end try
begin catch
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() as ErrorState,
ERROR_PROCEDURE() as ErrorProcedure,
ERROR_LINE() as ErrorLine,
ERROR_MESSAGE() as ErrorMessage;
end catch
go
请参阅:总是创建交易是否有坏习惯?
每个命令将需要单独的事务。您还可以通过保存的事务来完成此任务:
请参阅SAVE TRANSACTION (Transact-SQL)
产品文档。
我想将单个事务限定为存储过程的默认行为,因为所有语句都包装在隐式事务中。但是,没有人应该依靠隐式事务来控制其代码的命运。显式控制生产代码中处理事务的方式是一种更好的做法。
使用BEGIN TRAN分开每个部分,并检查交易是否成功。如果是提交,则进行回滚,因为它们都是从同一级别执行的,因此您可以分别提交每个节,而不必在失败的情况下回滚所有节。
有关更多信息,请参见:http : //msdn.microsoft.com/zh-cn/library/ms188929.aspx