触发器根据多对多关系插入多行

Posted

技术标签:

【中文标题】触发器根据多对多关系插入多行【英文标题】:Trigger to insert multiple rows based on many-to-many relationship 【发布时间】:2021-10-02 06:11:16 【问题描述】:

我有三个表ReservationReservation_PassengerTicket

每个预订可以有多名乘客。每次预订状态更新为“已预订”时,我都需要创建一个触发器来插入一张票(根据乘客人数)。我怎样才能实现它?

预留(reservationId,状态) Reservation_Passenger(reservationId、passengerId) 机票(ticketId、passengerId、issuedDate)

我尝试过的:

CREATE 
    TRIGGER Generate_Ticket 
    ON Reservation
    AFTER UPDATE
AS
    DECLARE @reservationStatus varchar(15)

    SELECT @reservationStatus =  INSERTED.Status from INSERTED

    IF @reservationStatus = 'Booked'
        BEGIN
        --stuck here

        END
GO

【问题讨论】:

您必须使用 CREATE TRIGGER 命令。到目前为止,您尝试了什么?您在哪里被阻止?。 请发布您现有的尝试,并解释什么不起作用或您遇到的问题。 Trigger tutorial @MarcGuillot 我更新了我的帖子 @Stu 我更新了我的帖子 请阅读this article 【参考方案1】:

与将状态存储到变量中的方式相同,您也可以检索 reservationId

DECLARE @reservationStatus varchar(15)
DECLARE @reservationId int

SELECT @reservationId = INSERTED.reservationId, 
       @reservationStatus = INSERTED.Status 
FROM INSERTED

现在在您卡住的部分,要为预订中的每位乘客创建一张票,您可以使用相关乘客的 SELECT 提供一个 INSERT。

INSERT INTO Ticket (passengerId, issuedDate)
       SELECT passengerId, getdate()
       FROM Reservation_Passenger
       WHERE reservationId = @reservationId

PS您需要注意,您的代码不会在同一个 UPDATE 命令上将多个预订更改为预订。因为在这种情况下,触发器只会触发一次,所有更新的预留都存储在 INSERTED 数据集中。您将需要使用 CURSOR 循环遍历所有这些预订以应用您的逻辑,或者切换到这个更简单的触发器,只需一步即可为所有预订的所有乘客创建机票:

CREATE TRIGGER Generate_Ticket ON Reservation AFTER UPDATE
AS

INSERT INTO Ticket (passengerId, issuedDate)
       SELECT P.passengerId, getdate()
       FROM INSERTED as R
            INNER JOIN Reservation_Passenger as P on P.reservationId = R.reservationID
       WHERE R.Status = 'Booked'

您还应该小心,因为触发器会在 Reservation 表上的任何字段更新时触发。如果您要在已预订的预订上更新另一个字段(例如评论),您的触发器将再次复制他的所有门票。

我建议您不仅检查 INSERTED.Status = 'Booked',还检查 DELETED.Status 'Booked',因此只有在 Status 字段从其他内容更改为 Booked 时才创建工单。

那就是:

CREATE TRIGGER Generate_Ticket ON Reservation AFTER UPDATE
AS

INSERT INTO Ticket (passengerId, issuedDate)
       SELECT P.passengerId, getdate()
       FROM INSERTED as I
            INNER JOIN DELETED as D on D.reservationId = I.reservationID
            INNER JOIN Reservation_Passenger as P on P.reservationId = I.reservationID
       WHERE I.Status = 'Booked' and coalesce(D.Status, '') <> 'Booked'

【讨论】:

这与我在上述 cmets 中链接到的错误相同,并假设只有 1 行会被更新。 @Stu 我正在添加一个附录,其中包含他的一些逻辑问题以及如何解决这些问题。

以上是关于触发器根据多对多关系插入多行的主要内容,如果未能解决你的问题,请参考以下文章

JPA多对多合并所有者触发器删除连接表

在 Django 中更新多对多关系时如何不触发“m2m_changed”信号?

ejb3:用简单的主键映射多对多关系

在休眠中的多对多映射中仅插入一个表

在事件监听器中同步多对多关系(Laravel 5.7)

quartz教程