1

实际上,我对在存储过程中使用嵌套事务有点困惑。我需要在一个主程序中调用两个/三个程序。

例如:

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

我是否以正确的方式做这件事?

4

4 回答 4

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
于 2016-05-31T11:52:32.833 回答
0

没有嵌套事务之类的东西。如果您只想回滚事务的一部分,那么我应该使用savepoints。关于保存点,如果 afterCOMMIT 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

如果我要使用保存点,那么我将使用此处的以下模板(请参阅第 1 节Example)。

于 2016-05-31T11:46:05.613 回答
0

SQL Server 数据库引擎会忽略提交内部事务。基于在最外层事务结束时采取的操作,事务要么被提交,要么被回滚。如果提交了外部事务,则也提交了内部嵌套事务。如果外部事务被回滚,那么所有内部事务也会被回滚,而不管内部事务是否被单独提交。

请参考链接 https://technet.microsoft.com/en-us/library/ms189336%28v=sql.105%29.aspx

于 2016-05-31T09:28:47.790 回答
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
  1. 创建 3 个存储过程(ProductID 不是身份,我不使用它来生成测试错误):
--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
  1. 输入虚假数据
EXEC    [dbo].[usp_addmix]
        @itemid = N'1',
        @color = N'red',
        @name = N'ali',
        @new = N'test'

它运作良好。

当第一个过程正确而后一个过程错误时,或者反之亦然,回滚操作对两者都适用。

于 2020-03-24T07:10:39.817 回答