70-761 练习题关于@@Trancount 最终值

Jes*_*uez 5 sql-server

练习 70-761 考试中有这个问题,执行以下脚本后指出,@@Trancount 的值是多少?

考试脚本:

CREATE PROCEDURE dbo.up_CreateSalesInvoice
(
    @Date DATE,
    @CustomerID INT,
    @StockitemId INT,
    @Quantity INT,
    @UnitPrice DECIMAL(8, 2),
    @InvoiceID INT OUT
)
AS
BEGIN
    DECLARE @RETVAL INT;
    BEGIN TRANSACTION;
    BEGIN TRY

        BEGIN TRANSACTION;
        INSERT INTO dbo.SalesInvoice(InvoiceDate, CustomerID)
            VALUES (@Date, @CustomerID);
        SET @InvoiceID = SCOPE_IDENTITY();
        COMMIT TRANSACTION;

        BEGIN TRANSACTION;
        INSERT INTO dbo.SalesInvoiceLine(InvoiceID, StockItemID, Quantity, UnitPrice)
            VALUES (@InvoiceID, @StockItemID, @Quantity, @UnitPrice);
        COMMIT TRANSACTION;

        COMMIT TRANSACTION;
        SET @RETVAL = 0;
    END TRY

    BEGIN CATCH
        ROLLBACK TRANSACTION;
        SET @RETVAL = 1;
    END CATCH

    RETURN @RETVAL;
END;
Run Code Online (Sandbox Code Playgroud)

我得出的结论是0,但预期的答案是1,所以我开始使用以下脚本复制脚本行为,并且从@@Trancount 返回的结果是0,除非我的脚本对嵌套事务执行不同的操作(如果有人)可以解释是否预期的答案是错误的,或者如果我的逻辑模拟了脚本的嵌套事务,我得到了一些错误的结果女巫给了我不同的结果

模拟行为的脚本:

CREATE TABLE #TBL(
    ID INT,
    TANK VARCHAR(12)
)

INSERT INTO #TBL VALUES (1, 'T-55-MA')

PRINT 'TRANCOUNT INICIAL :: ' +  CAST(@@TRANCOUNT AS VARCHAR)

BEGIN TRANSACTION  -- +1
PRINT 'BEGIN TRANSACTION 1 _ TRANCOUNT :: ' + CAST(@@TRANCOUNT AS VARCHAR)
BEGIN TRY
    BEGIN TRANSACTION  -- +1
    PRINT 'NESTED BEGIN TRANSACTION 1 _ TRANCOUNT :: ' + CAST(@@TRANCOUNT AS VARCHAR)
    INSERT INTO #TBL VALUES (2, 'M4A3-W(76)')
    COMMIT TRANSACTION  -- -1
    PRINT 'NESTED COMMIT 1 TRANSACTION _ TRANCOUNT :: ' + CAST(@@TRANCOUNT AS VARCHAR)

    BEGIN TRANSACTION -- +1
    PRINT 'NESTED BEGIN TRANSACTION 2 _ TRANCOUNT :: ' + CAST(@@TRANCOUNT AS VARCHAR)
    INSERT INTO #TBL VALUES (3, 'LEOPARD-A1')
    COMMIT TRANSACTION -- -1
    PRINT 'NESTED COMMIT 2 TRANSACTION _ TRANCOUNT :: ' + CAST(@@TRANCOUNT AS VARCHAR)

    COMMIT TRANSACTION -- -1
    PRINT 'NESTED COMMIT 3 TRANSACTION _ TRANCOUNT :: ' + CAST(@@TRANCOUNT AS VARCHAR)
END TRY

BEGIN CATCH
    ROLLBACK TRANSACTION
    PRINT 'ROLLBACK EN CATCH _ TRANCOUNT :: ' + CAST(@@TRANCOUNT AS VARCHAR)
END CATCH

PRINT 'FINAL TRANCOUNT _ TRANCOUNT :: ' + CAST(@@TRANCOUNT AS VARCHAR) --This returns 0
SELECT * FROM #TBL

DROP TABLE #TBL
Run Code Online (Sandbox Code Playgroud)

编辑张贴考试提供的答案的推理:

考试提供的答案为 1 的原因如下:

@@TRANCOUNT 设置为1,当存储过程运行时,只执行一个事务,将@@TRANCOUNT 增加到1。虽然外层事务中有嵌套事务,但SQL Server 并没有真正创建嵌套事务。

但是运行整个脚本并在每次提交时打印 @@TRANCOUNT 并开始 tran 一旦到达脚本末尾它总是打印 0,嵌套事务提交正在减少 @@TRANCOUNT 值,而嵌套的 BEGIN TRAN 正在增加值,尽管 SQL Server 将嵌套事务指向顶部事务是正确的。

提前致谢

Han*_*dyD 5

模拟考试中提供的预期答案不正确。Microsoft 自己的文档清楚地说明了您发现的相同内容 - 每个 BEGIN TRANSACTION 将 @@TRANCOUNT 增加 1,每个 COMMIT TRANSACTION 将其减少 1,ROLLBACK TRANSACTION 将 @@TRANCOUNT 重置为 0。

嵌套事务计数并将@@TRANCOUNT 值也增加 1,因此 SQL Server 并未实际创建嵌套事务的声明也是错误的。

请参阅此处了解更多信息。代码是否在存储过程中也没有区别。