使用触发器收集表中的更新值

时间:2019-06-30 05:54:49

标签: sql-server triggers

我遇到一种情况,创建了一个包含约30多个列的表,该表创建了一个审计表,其中列数相同,而其他列的描述较少,列的日期已更新。需要一个触发器来收集更新的列并将其作为描述收集,并且需要像这样构成一个句子,以便将字段更新到审计表中。样品触发的帮助将不胜感激。在此先感谢。

ALTER TRIGGER [dbo].[trg_reservationdetail_audit]
ON [dbo].[tblReservationDetails]
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
    SET NOCOUNT ON;
    INSERT reservationDetails_audits(
        reservationDetailId,
        reservationId,
        rdCreationDate,
        rdItemTypeId,
        rdDeparture,
        rdArrival,
        rdPax,
        PaxChildren,
        PaxBabies,
        rdStatusId,
        rdIsCancelled,
        rdPackageId,
        rdRateId,
        rdPrice,
        rdTaxId,
        rdRoomId,
        rdTaxAmount,
        rdDays,
        siteId,
        CreatorID,
        CreatorName,
        Updated,
        UpdatedBy,
        Amount,
        Segment_ID,
        Source_ID,
        Remarks,
        SessionId,
        Contact_ID,
        CreatorContactProfileID,
        HotelReservationUniqueID,
        HotelReservationResID_Value,
        RoomStayId,
        ChnMgrContent_ID,
        InvoiceTo,
        SourceContext,
        BlockRoomChange,
        BlockRoomChangeReasonId,
        rdinvoiceid,
        isOnHoldResDet,
        updated_at,
        Operation,
        Description)
     SELECT
       i.reservationDetailId,
        reservationId,
        rdCreationDate,
        rdItemTypeId,
        rdDeparture,
        rdArrival,
        rdPax,
        PaxChildren,
        PaxBabies,
        rdStatusId,
        rdIsCancelled,
        rdPackageId,
        rdRateId,
        rdPrice,
        rdTaxId,
        rdRoomId,
        rdTaxAmount,
        rdDays,
        siteId,
        CreatorID,
        CreatorName,
        Updated,
        UpdatedBy,
        Amount,
        Segment_ID,
        Source_ID,
        Remarks,
        SessionId,
        Contact_ID,
        CreatorContactProfileID,
        HotelReservationUniqueID,
        HotelReservationResID_Value,
        RoomStayId,
        ChnMgrContent_ID,
        InvoiceTo,
        SourceContext,
        BlockRoomChange,
        BlockRoomChangeReasonId,
        rdinvoiceid,
        i.isOnHoldResDet,           
        GETDATE(),
   CASE WHEN EXISTS (SELECT * FROM Deleted) THEN 'UPD' ELSE 'INS' END
FROM
   Inserted I
UNION ALL
SELECT
       d.reservationDetailId,
        reservationId,
        rdCreationDate,
        rdItemTypeId,
        rdDeparture,
        rdArrival,
        rdPax,
        PaxChildren,
        PaxBabies,
        rdStatusId,
        rdIsCancelled,
        rdPackageId,
        rdRateId,
        rdPrice,
        rdTaxId,
        rdRoomId,
        rdTaxAmount,
        rdDays,
        siteId,
        CreatorID,
        CreatorName,
        Updated,
        UpdatedBy,
        Amount,
        Segment_ID,
        Source_ID,
        Remarks,
        SessionId,
        Contact_ID,
        CreatorContactProfileID,
        HotelReservationUniqueID,
        HotelReservationResID_Value,
        RoomStayId,
        ChnMgrContent_ID,
        InvoiceTo,
        SourceContext,
        BlockRoomChange,
        BlockRoomChangeReasonId,
        rdinvoiceid,
        d.isOnHoldResDet,           
        GETDATE(),
        'DEL'
     FROM Deleted d
    WHERE NOT EXISTS (
   SELECT * FROM Inserted
);
END

期望样本触发器在审计表中带有新列作为描述,这将形成一个简单的句子向用户显示。

1 个答案:

答案 0 :(得分:1)

次要问题是比较可为空的列。可以用一个表达式来完成 ISNULL(NULLIF(i.Col, d.Col), NULLIF(d.Col, i.Col)) IS NOT NULL,如果inserteddeletedCol行不同,则为true。

INSERT reservationDetails_audits(
        reservationDetailId,
        reservationId,
        rdCreationDate,
        -- ..
        updated_at,
        Operation,
        Description)
SELECT
        i.reservationDetailId,
        i.reservationId,
        i.rdCreationDate,
        -- ..
        i.isOnHoldResDet,           
        GETDATE(),
        CASE WHEN d.reservationDetailId IS NOT NULL THEN 'UPD' ELSE 'INS' END,
        CASE WHEN d.reservationDetailId IS NOT NULL THEN
          ' updated cols: '
          -- assumming reservationId is not nullable
          + CASE i.reservationId <> d.reservationId THEN 'reservationId ' ELSE '' END 
          -- assumming rdCreationDate is nullable
          + CASE ISNULL(NULLIF(i.rdCreationDate, d.rdCreationDate), NULLIF(d.rdCreationDate, i.rdCreationDate)) IS NOT NULL THEN 'rdCreationDate ' ELSE '' END
          -- + ..
        ELSE '' END
FROM Inserted I
LEFT JOIN deleted d on d.reservationDetailId = i.reservationDetailId
UNION ALL
--  delete oper query

;