触发器根据多对多关系插入多行
Posted
技术标签:
【中文标题】触发器根据多对多关系插入多行【英文标题】:Trigger to insert multiple rows based on many-to-many relationship 【发布时间】:2021-10-02 06:11:16 【问题描述】:我有三个表Reservation
、Reservation_Passenger
和Ticket
。
每个预订可以有多名乘客。每次预订状态更新为“已预订”时,我都需要创建一个触发器来插入一张票(根据乘客人数)。我怎样才能实现它?
预留(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 我正在添加一个附录,其中包含他的一些逻辑问题以及如何解决这些问题。以上是关于触发器根据多对多关系插入多行的主要内容,如果未能解决你的问题,请参考以下文章