【问题标题】:SQL Server: Post Insert Pre Commit TriggerSQL Server:后插入预提交触发器
【发布时间】:2013-08-07 08:58:22
【问题描述】:

我已经查找了一段时间,但在插入发生后但在提交发生之前,我找不到任何触发触发器的方法。我需要这样做,以便在插入的信息有问题时能够恢复角色,但还需要检查插入的信息,因此需要在插入完成后进行。

是否有执行此操作的触发器或可以重现此相同功能的任何方法?

【问题讨论】:

    标签: sql-server database triggers


    【解决方案1】:

    触发器在提交发生之前被激活。如果某些检查失败,您可以在触发器中使用ROLLBACK

    CREATE TABLE dbo.Product(
        Id INT NOT NULL PRIMARY KEY,
        Name NVARCHAR(100) NOT NULL,
        UnitPrice NUMERIC(9,2) NOT NULL -- CHECK (UnitPrice > 0)
    );
    GO
    CREATE TRIGGER trgIU_Product_VerifyUnitPrice
    ON dbo.Product
    AFTER INSERT, UPDATE
    AS
    BEGIN
        IF UPDATE(UnitPrice)
        BEGIN
            -- For simple checks you could use CHECK constraints
            -- inserted and deleted are virtual tables store the new and the old rows (values)
            IF EXISTS(SELECT * FROM inserted WHERE UnitPrice <= 0)
            BEGIN
                ROLLBACK; -- It "cancels" current transaction
                RAISERROR('Wrong UnitPrice.',16,1); -- It notifies the caller that there is an error
            END
        END
    END;
    GO
    
    SET NOCOUNT ON;
    PRINT 'Test #1';
    INSERT INTO dbo.Product (Id,Name,UnitPrice)
    SELECT  1 , 'PCs      ', 1200;
    
    PRINT 'Test #2';
    INSERT INTO dbo.Product (Id,Name,UnitPrice)
    SELECT  2 , 'MACs     ', 2200;
    
    PRINT 'Test #3';
    INSERT INTO dbo.Product (Id,Name,UnitPrice)
    SELECT  3 , 'Keyboard ', 0;
    
    PRINT 'Test #4';
    INSERT INTO dbo.Product (Id,Name,UnitPrice)
    SELECT  4 , 'AAA', 111
    UNION ALL
    SELECT  5 , 'BBB', 0;
    GO
    
    PRINT 'Test #5';
    BEGIN TRANSACTION;
    INSERT INTO dbo.Product (Id,Name,UnitPrice)
    SELECT  6 , 'CCC', 222
    UNION ALL
    SELECT  7 , 'DDD', 0;
    COMMIT TRANSACTION;
    GO
    SELECT @@TRANCOUNT AS [Active transactions count];
    GO
    
    PRINT 'Test #6';
    SELECT * FROM dbo.Product;
    

    结果:

    /*
    Test #1
    
    Test #2
    
    Test #3
    Msg 50000, Level 16, State 1, Procedure trgIU_Product_VerifyUnitPrice, Line 11
    Wrong UnitPrice.
    Msg 3609, Level 16, State 1, Line 11
    The transaction ended in the trigger. The batch has been aborted.
    
    Test #4
    Msg 50000, Level 16, State 1, Procedure trgIU_Product_VerifyUnitPrice, Line 11
    Wrong UnitPrice.
    Msg 3609, Level 16, State 1, Line 2
    The transaction ended in the trigger. The batch has been aborted.
    
    Test #5
    Msg 50000, Level 16, State 1, Procedure trgIU_Product_VerifyUnitPrice, Line 11
    Wrong UnitPrice.
    Msg 3609, Level 16, State 1, Line 3
    The transaction ended in the trigger. The batch has been aborted.
    Active transactions count
    -------------------------
    0
    
    Test #6
    Id Name UnitPrice
    -- ---- ---------
    1  PCs  1200.00
    2  MACs 2200.00
    */
    

    参考:http://technet.microsoft.com/en-us/library/ms189799.aspx

    【讨论】:

      【解决方案2】:

      看看documentation 对 AFTER TRIGGER 的评价。

      AFTER 指定 DML 触发器仅在所有操作时触发 触发 SQL 语句中指定的已成功执行。

      您可以轻松编写 AFTER 触发器,但不能使用它来控制在事务提交之前发生的情况。可能有一个显式事务保持打开状态,直到例如“手动”回滚或提交。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-29
        • 2013-11-09
        • 2018-05-26
        • 1970-01-01
        • 2016-12-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多