【问题标题】:Cannot rollback in if block transaction sql如果阻塞事务sql不能回滚
【发布时间】:2017-11-10 22:20:16
【问题描述】:

当我执行这个存储过程时,即使IF 语句是正确的,我也无法在IF 块中回滚。如果IF 语句是正确的,脚本最终仍然在运行并且根本没有回滚。

消息:账号id已经使用成功注册

消息 3902,级别 16,状态 1,过程 PROC_DANGKY,第 23 行
COMMIT TRANSACTION 请求没有对应的 BEGIN TRANSACTION。

代码:

CREATE PROCEDURE PROC_REGISTER
    @name nvarchar(30),
    @birth datetime,
    @passport nvarchar(9),
    @address nvarchar(50),
    @phone nvarchar(11),
    @email nvarchar(20),
    @account nvarchar(30),
    @password nvarchar(20)
AS
BEGIN TRAN  
    BEGIN TRY
        IF (EXISTS(SELECT * FROM CUSTOMER WHERE ACCOUNT = @account))    
        BEGIN               
            PRINT N'The account id has already been used'
            ROLLBACK TRAN               
        END     

        INSERT INTO KHACHHANG 
        VALUES (@name, @birth, @passport, @address, @phone, @email, @account, @password)
        PRINT N'Successfully registered'
    END TRY
    BEGIN CATCH
        DECLARE @ErrorMsg VARCHAR(2000)
        SELECT @ErrorMsg = N'Error: ' + ERROR_MESSAGE()
        RAISERROR(@ErrorMsg, 16,1)

        ROLLBACK TRAN

        RETURN
    END CATCH   
COMMIT TRAN

【问题讨论】:

  • 当你检查 EXISTS 时你什么都不做,所以你不必回滚,插入后你提交而不是从外部提交

标签: sql sql-server stored-procedures transactions


【解决方案1】:

重新格式化您的查询


存在后删除回滚

CREATE PROC PROC_REGISTER
    @name nvarchar(30),
    @birth datetime,
    @passport nvarchar(9),
    @address nvarchar(50),
    @phone nvarchar(11),
    @email nvarchar(20),
    @account nvarchar(30),
    @password nvarchar(20)

AS
 BEGIN TRAN      
    BEGIN TRY
        IF (EXISTS(SELECT * FROM CUSTOMER WHERE ACCOUNT = @account))    
             PRINT N'The account id has already used'
        ELSE   
         BEGIN

             INSERT INTO KHACHHANG VALUES (@name, @birth, @passport,           @address, @phone, @email, @account, @password)
           PRINT N'Successul register'
         END
    END TRY
    BEGIN CATCH
        DECLARE @ErrorMsg VARCHAR(2000)


          SELECT @ErrorMsg = N'Error: ' + ERROR_MESSAGE()
            RAISERROR(@ErrorMsg, 16,1)
             IF @@TRANCOUNT > 0  
                  ROLLBACK TRAN
        END CATCH   

IF @@TRANCOUNT > 0  
    COMMIT TRAN
GO  

RETURN

【讨论】:

  • 呃...如果IF 条件为真,这将出错(由于缺少提交)。如果 BEGIN TRAN 也不在该块中,则没有理由将提交放入 IF/ELSE 块中。
【解决方案2】:

你可以在回滚前检查@@TRANCOUNT是否存在事务:

CREATE PROC PROC_REGISTER
    @name nvarchar(30),
    @birth datetime,
    @passport nvarchar(9),
    @address nvarchar(50),
    @phone nvarchar(11),
    @email nvarchar(20),
    @account nvarchar(30),
    @password nvarchar(20)

AS
BEGIN TRAN  
    BEGIN TRY
        IF (EXISTS(SELECT * FROM CUSTOMER WHERE ACCOUNT = @account))    
            BEGIN               
                PRINT N'The account id has already used'
                IF (@@TRANCOUNT > 0)
                BEGIN
                    ROLLBACK TRAN
                END
            END     
        INSERT INTO KHACHHANG VALUES (@name, @birth, @passport, @address, @phone, @email, @account, @password)
        PRINT N'Successul register'
    END TRY
    BEGIN CATCH
        DECLARE @ErrorMsg VARCHAR(2000)
        SELECT @ErrorMsg = N'Error: ' + ERROR_MESSAGE()
        RAISERROR(@ErrorMsg, 16,1)
        IF (@@TRANCOUNT > 0)
        BEGIN
            ROLLBACK TRAN
        END
        RETURN
    END CATCH   
COMMIT TRAN

【讨论】:

    猜你喜欢
    • 2017-12-28
    • 2013-08-02
    • 2012-07-13
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多