Mat*_*les 19 sql-server stored-procedures
我有一个运行一些命令的存储过程。我不希望这些命令被包装在存储过程的事务中。如果第 4 个命令失败,我希望第 1、第 2 和第 3 个命令保持不变,而不是回滚。
是否有可能以这样一种方式编写存储过程,使其不全部作为一个大事务执行?
JNK*_*JNK 18
我认为这里可能会有一些关于批处理与交易的混淆。
一个交易是声明,要么成功,要么失败,因为一个单位的语句或集。所有 DDL 语句都在事务本身中(即,如果更新 100 行但第 98 行抛出错误,则不会更新任何行)。您也可以使用BEGIN TRANSACTION,然后使用COMMIT或将一系列语句包装在事务中ROLLBACK。
一个批次是一系列被一起执行的语句。存储过程是批处理的一个示例。在存储过程中,如果一个语句失败并且存在错误捕获(通常是TRY/CATCH阻塞),那么后续语句将不会执行。
我怀疑您的问题是发生错误时批处理被取消,因为存储过程本身或外部范围(如调用此过程的应用程序或存储过程)在其中捕获错误。如果是这种情况,解决起来就比较棘手,因为您需要调整在任何范围内处理错误的方式。
Tho*_*ger 17
所有事务都不会在单个事务中执行。看看这个例子:
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;
Run Code Online (Sandbox Code Playgroud)
这是输出:

通过创建扩展事件会话来监视sql_transaction事件,以下是执行的输出dbo.ChangeValues:

正如您在上面的屏幕截图中看到的那样,四个语句中的每一个都有单独的事务。前 3 次提交,最后一次由于错误而回滚。
sql server 中的所有内容都包含在一个事务中。
当你明确指定begin transaction和end transaction则称为明确的事务。当你不这样做时,那就是隐式交易。
要切换您所处的模式,您可以使用
set implicit_transactions on
Run Code Online (Sandbox Code Playgroud)
或者
set implicit_transactions off
select @@OPTIONS & 2
Run Code Online (Sandbox Code Playgroud)
如果上面返回 2,则您处于隐式事务模式。如果它返回 0,则您处于自动提交状态。
事务是全部或什么都可以使数据库保持一致状态..记住 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'
Run Code Online (Sandbox Code Playgroud)
-- 现在创建 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
Run Code Online (Sandbox Code Playgroud)
请参阅:始终创建事务是一种不好的做法吗?
小智 -2
用 BEGIN TRAN 分隔每个部分并检查事务是否成功。如果已提交,则进行回滚,因为它们都从同一级别执行,因此您将能够单独提交每个部分,而无需在失败时回滚所有部分。
有关更多信息,您可以查看:http://msdn.microsoft.com/en-us/library/ms188929.aspx
| 归档时间: |
|
| 查看次数: |
91403 次 |
| 最近记录: |