【问题标题】: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

标签: sql sql-server tsql triggers


【解决方案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 我正在添加一个附录,其中包含他的一些逻辑问题以及如何解决这些问题。
猜你喜欢
  • 1970-01-01
  • 2018-12-29
  • 1970-01-01
  • 2021-10-01
  • 2011-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多