实际上,我对在存储过程中使用嵌套事务感到有些困惑。 我需要在一个主要程序中调用两个/三个程序。
例如:
Begin try
Begin Tran -- 1st level transcation
Procedure 1 --will be executed
Procedure 2 --will be executed
End tran -- 1st level transcation
End try
Begin Catch
Rollback tran
End Catch
PROCEDURE 1:
BEGIN TRAN TRAN1
///scripts
COMMIT TRAN TRAN1
PROCEDURE 2:
BEGIN TRAN TRAN2
///scripts
COMMIT TRAN TRAN2
我是以正确的方式做到的吗?
答案 0 :(得分:0)
SQL Server数据库引擎会忽略提交内部事务。根据最外层事务结束时采取的操作,提交或回滚事务。如果提交了外部事务,则还会提交内部嵌套事务。如果外部事务被回滚,那么所有内部事务也会回滚,无论内部事务是否单独提交。
请参阅链接 https://technet.microsoft.com/en-us/library/ms189336%28v=sql.105%29.aspx
答案 1 :(得分:0)
没有nested transactions之类的东西。如果您只想回滚事务的一部分,那么我应该使用savepoints。关于保存点,如果执行COMMIT TRANSACTION SavepointName
ROLLBACK
后,此最后ROLLBACK
语句将回滚包含保存点定义的部分的每个提示:
BEGIN TRANSACTION -- A
SAVE TRANSACTION SavePoint1 -- B
-- do something
COMMIT TRANSACTION SavePoint1 -- C
-- ...
-- This ROLLBACK will rollback everything including data committed for SavePoint1 - it will rollback also actions for [B,C] range
ROLLBACK -- D
如果我使用保存点,那么我将使用here中的以下模板(参见Example
部分)。
答案 2 :(得分:0)
BEGIN TRANSACTION => @@ TRANCOUNT = @@ TRANCOUNT + 1
COMMIT TRANSACTION => @@ TRANCOUNT = @@ TRANCOUNT - 1(如果0保存更改)
ROLLBACK TRANSACTION => @@ TRANCOUNT = 0(并放弃更改)
在你的外部程序中,只需做
BEGIN TRY
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION
..
END TRY
答案 3 :(得分:0)
我用两个假设的过程来完成整个过程。进行全面测试和使用。我希望这个时间以后能解决,因为问题是三年前的。
1。拳头步骤创建两个表:
CREATE TABLE [dbo].[Products](
[ProductId] [nvarchar](70) NOT NULL,
[ItemId] [nvarchar](50) NOT NULL,
[Color] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_table_4] PRIMARY KEY CLUSTERED
(
[ProductId] 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
CREATE TABLE [dbo].[Users](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](20) NULL,
[NewColumn] [nchar](10) NULL,
CONSTRAINT [P_Users_Id] PRIMARY KEY CLUSTERED
(
[Id] 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
--SP1
Create PROCEDURE [dbo].[usp_adduser]
@name nvarchar(20),
@new nchar(10)
AS
BEGIN
SET NOCOUNT ON;
insert into users
values (@name,@new)
END
GO
--SP2
Create PROCEDURE [dbo].[usp_addproduct]
@itemid nvarchar(50),
@color nvarchar(50)
--,@Productid int = null --for test commnted
AS
BEGIN
SET NOCOUNT ON;
insert into products ([ItemId], [Color]) --dont use producid for test
values (@itemid,@color)
END
GO
--SP3
Create PROCEDURE [dbo].[usp_addmix]
@itemid nvarchar(50),
@color nvarchar(50),
@name nvarchar(20),
@new nchar(10)
AS
SET NOCOUNT ON;
Set Implicit_transactions ON;
Begin transaction
Execute usp_adduser @name,@new
Execute usp_addproduct @itemid,@color
Commit transaction
Catch
if @@TRANCOUNT > 0
rollback
EXEC [dbo].[usp_addmix]
@itemid = N'1',
@color = N'red',
@name = N'ali',
@new = N'test'
效果很好。
当第一个步骤正确而后一个错误时,反之亦然,回滚操作对这两个操作都很好。