审计触发器将多行插入审计表

时间:2021-06-21 19:34:18

标签: sql sql-server tsql triggers

我编写了一个触发器,当我更新基表中的值时,我在审计表中得到了多个记录。我只期待一个。这是我的触发器:

CREATE TRIGGER dbo.SOP10100_TRDISAMT
ON dbo.SOP10100
AFTER INSERT, UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    IF (select TRDISAMT from inserted) = 0
        BEGIN
            RETURN
        END
    ELSE
        BEGIN
            DECLARE @SOPTYPE smallint = (select soptype from inserted)
            DECLARE @SOPNUMBE char(21) = (select sopnumbe from inserted)
            DECLARE @MSTRNUMB int = (select mstrnumb from inserted)
            DECLARE @DOCID char(15) = (select docid from inserted)
            DECLARE @SUBTOTAL numeric(19,5) = (select subtotal from inserted)
            DECLARE @MISCAMT numeric(19,5) = (select MISCAMNT from inserted)
            DECLARE @TRDISAMT numeric(19,5) = (select TRDISAMT from inserted)
            DECLARE @TRDISAMT_B4 numeric(19,5) = (select TRDISAMT from deleted)
            DECLARE @FRTAMNT numeric(19,5) = (select FRTAMNT from inserted)
            DECLARE @TAXAMNT numeric(19,5) = (select TAXAMNT from inserted)
            DECLARE @DOCAMNT numeric(19,5) = (select DOCAMNT from inserted)
            DECLARE @USERNAME nvarchar(128) = (select SUSER_SNAME())
            DECLARE @TheTime datetime = (select GETDATE())

            INSERT INTO SOP10100_TRDISAMT_AUDIT (soptype,sopnumbe,MSTRNUMB,DOCID,SUBTOTAL,MISCAMT,TRDISAMT,TRDISAMT_B4,FRTAMNT,TAXAMNT,DOCAMNT,USERNAME,TheTime)
            VALUES (@SOPTYPE,@SOPNUMBE,@MSTRNUMB,@DOCID,@SUBTOTAL,@MISCAMT,@TRDISAMT,@TRDISAMT_B4,@FRTAMNT,@TAXAMNT,@DOCAMNT,@USERNAME,@TheTime)
        END
    END

这是我运行的更新值:

update SOP10100 set TRDISAMT = 35 where SOPTYPE = 1 and SOPNUMBE = '126535'

这导致两条记录被插入到我的审计表中。想法?

1 个答案:

答案 0 :(得分:1)

您的查询存在致命缺陷,因为它没有考虑插入或更新的多行(或零行)。

您的触发器应该看起来像这样:

CREATE TRIGGER dbo.SOP10100_TRDISAMT
ON dbo.SOP10100
AFTER INSERT, UPDATE
AS 

INSERT INTO SOP10100_TRDISAMT_AUDIT
    (soptype, sopnumbe, MSTRNUMB, DOCID, SUBTOTAL, MISCAMT, TRDISAMT,
    TRDISAMT_B4, FRTAMNT, TAXAMNT, DOCAMNT, USERNAME, TheTime)
SELECT i.soptype, i.sopnumbe, i.mstrnumb, i.docid, i.subtotal, i.MISCAMNT, i.TRDISAMT,
    i.TRDISAMT, i.FRTAMNT, i.TAXAMNT, i.DOCAMNT, SUSER_SNAME(), GETDATE()
FROM inserted i
WHERE i.TRDISAMT <> 0;

GO
  • 如果要排除UPDATE语句根本没有更改值的行,则需要添加
EXCEPT
SELECT d.soptype, d.sopnumbe.....
FROM deleted d
  • 我注意到 char 是一种不常见的数据类型,只能在值固定为该长度的情况下使用,否则会出现尾随空格。
相关问题