#sql #sql-server #tsql #triggers
Вопрос:
У меня есть три стола Reservation
, Reservation_Passenger
и Ticket
.
В каждом бронировании может быть несколько пассажиров. Мне нужно создать триггер для вставки билета (в зависимости от количества пассажиров) каждый раз, когда статус бронирования обновляется до «Забронировано». Как я могу этого достичь?
- Бронирование (идентификатор бронирования, статус)
- Reservation_Passenger (идентификатор бронирования, идентификатор пассажира)
- Билет (идентификатор билета, идентификатор пассажира, дата выдачи)
Что я пробовал:
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
Комментарии:
1. Вы должны использовать команду СОЗДАТЬ ТРИГГЕР. Что вы пробовали до сих пор и где вас заблокировали ?.
2. Пожалуйста, опубликуйте вашу существующую попытку и объясните, что не работает или где вы застряли. Учебник по триггерам
3. @MarcGuillot Я обновил свой пост
4. @Stu Я обновил свой пост
5. Пожалуйста, прочтите эту статью
Ответ №1:
Таким же образом, как вы сохраняете статус в переменной, вы также можете получить идентификатор резервирования
DECLARE @reservationStatus varchar(15)
DECLARE @reservationId int
SELECT @reservationId = INSERTED.reservationId,
@reservationStatus = INSERTED.Status
FROM INSERTED
Теперь в той части, где вы застряли, чтобы создать билет для каждого пассажира при бронировании, вы можете вставить ВСТАВКУ с ВЫБОРОМ соответствующих пассажиров.
INSERT INTO Ticket (passengerId, issuedDate)
SELECT passengerId, getdate()
FROM Reservation_Passenger
WHERE reservationId = @reservationId
PS Вам нужно будет быть осторожным, чтобы ваш код не изменил более одного бронирования на забронированное по одной и той же команде ОБНОВЛЕНИЯ. Потому что в этом случае триггер срабатывает только один раз, а все обновленные резервирования хранятся во ВСТАВЛЕННОМ наборе данных. Вам нужно будет использовать курсор для перебора всех этих бронирований, чтобы применить свою логику, или переключиться на этот более простой триггер, который создает билеты для всех пассажиров всех забронированных бронирований за один шаг:
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'
Вы также должны быть осторожны, потому что триггер срабатывает при обновлении любого поля в таблице резервирования. Если вы обновите другое поле, например комментарий, в уже забронированном бронировании, ваш триггер снова продублирует все его билеты.
Я рекомендую вам проверить не только то, что ВСТАВЛЕНО.Статус = «Забронировано», но также УДАЛЕНО.Статус < > «Забронировано», поэтому вы создаете билеты только тогда, когда поле статуса изменилось на Забронировано с чего-то другого.
Это было бы :
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'
Комментарии:
1. В этом есть та же ошибка, на которую я ссылался в приведенных выше комментариях, и предполагается, что только 1 строка когда-либо будет обновлена.
2. @Stu Я добавлял дополнение с некоторыми проблемами его логики и способами их решения.