Прежде всего, даже если у вашего триггера не было тайм-аута, он почти наверняка не делал то, что вы хотите. Большая часть этого сводится к вопиющему игнорированию возможно нескольких возвращаемых значений в некоторых операторах.
Я также немного обеспокоен тем, к каким условиям, похоже, приближаются, потому что похоже, что я не мог сделать что-то вроде планирования рейса на выходные, если бы у меня была короткая командировка на следующей неделе! Возможно, вы захотите проверить следующий рейс, но я не знаю достаточно, чтобы гарантировать это.
Тем не менее, я думаю (основываясь на некоторых предположениях о ваших данных и намерениях, но вам нужно будет проверить мою работу), вы можете сделать свой триггер похожим на:
ALTER TRIGGER [dbo].[Tr_Check60j]
ON [dbo].[Reservation]
FOR INSERT -- You could probably do INSTEAD OF and perform the insert here
AS
BEGIN
SELECT 'Existing Flight'
FROM Inserted
JOIN Planning Inserted_planning
ON Inserted_planning.pla_id = Inserted.res_pla_id
JOIN Vol Inserted_vol
ON Inserted_vol.vol_id = Inserted_planning.pla_vol_id
WHERE EXISTS (
SELECT 'Existing Flight'
FROM Vol Return_vol
JOIN Planning Return_planning
ON Return_planning.pla_vol_Id = return_vol.vol_id
AND Return_planning.pla_date >= DATEADD(day, -60, CAST(Inserted_planning.pla_date AS DATE))
AND Return_planning.pla_id != Inserted_planning.pla_id
JOIN Return_reservation
ON Return_reservation.res_pla_id = Return_planning.pla_Id
AND Return_reservation.res_client_id = Inserted.res_client_id
AND Return_reservation.res_id != Inserted.res_id
JOIN Planning Planning_Other
ON Planning_Other.pla_date >= Return_planning.pla_date
AND Planning_Other.pla_date < Inserted_planning.pla_date
AND Planning_other.pla_id != Inserted_planning.pla_id
AND Planning_other.pla_id != Return_planning.pla_id
JOIN Reservation Reservation_Other
ON Reservation_Other.res_pla_id = Planning_Other.pla_id
AND Reservation_Other.res_client_id = Inserted.res_client_id
AND Reservation_other.res_id != Inserted.res_id
AND Reservation_other.res_id != Return_reservation.res_id
WHERE Return_vol.vol_vil_depart_id = Inserted_vol.vol_vil_arrivee_id
AND Return_vol.vil_arrivee_id = Inserted_vol.vol_vil_depart_id)
IF (@@ROWCOUNT > 0)
BEGIN
RAISERROR('Réservation impossible', 1, 601)
ROLLBACK TRANSACTION
STOP
END
END
<ч />
Хорошо, вот анализ / изменение рассуждений. Давайте разберем это по частям.
Прежде всего, ваши запросы перед курсором могут быть объединены и упрощены:
-- For clarity, put DECLAREs on their own lines
DECLARE @IdVolInsere INT;
DECLARE @IdClient INT;
DECLARE @DateVolInsere DATETIME;
DECLARE @IdVilleDepartInseree INT;
DECLARE @IdVilleArriveeInseree INT;
-- ....I'm against prefixing columns with table names, especially _shortened_ table names.
-- Except maybe for id columns.
SELECT @IdVolInsere = Vol.vol_id,
@IdClient = Inserted.res_client_Id,
@IdVilleDepartInseree = Vol.vol_vil_depart_id,
@IdVilleArriveeInseree = Vol.vol_vil_arrivee_id,
@DateVolInsere = Planning.pla_Date
FROM Vol -- Single-character aliases make it hard to track tables.
JOIN Planning
ON Planning.pla_vol_Id = vol.vol_Id
JOIN Inserted
ON Inserted.res_pla_id = Planning.pla_id
... теперь, когда все прояснено, давайте (очистим и) взглянем на курсор и другие утверждения:
DECLARE CR_Check_Vols_Par_Id_Client CURSOR FOR
SELECT Vol.vol_Id
FROM Vol
JOIN Planning
ON Planning.pla_vol_Id = Vol.vol_id
JOIN Reservation
ON Reservation.res_pla_id = Planning.pla_Id
AND Reservation.res_client_id = @IdClient
... Хорошо, проверяем любой Vol.vol_id
, который соответствует нашему идентификатору клиента. За исключением того, что это прямой AFTER
триггер, мы собираемся получить строку, которую мы только что вставили! Мы, вероятно, не очень этого хотим!
Ну, мы пока проигнорируем это и предположим, что нашему конечному состоянию не нужно беспокоиться об этом. Давайте просто удалим объявление курсора, которое превращает это в набор:
SELECT -- dunno what we need yet
FROM Vol
JOIN Planning
ON Planning.pla_vol_Id = Vol.vol_id
JOIN Reservation
ON Reservation.res_pla_id = Planning.pla_Id
AND Reservation.res_client_id = @IdClient
... следующие следующие строки:
-- Sélectionne l'id des villes aller (mêmes villes) du dernier vol existant à moins de 60j
SELECT @IdVilleDepartExistant = v.VOL_Vil_Depart_Id FROM Vol v WHERE v.VOL_Id = @IdVolExistant
SELECT @IdVilleArriveeExistant = v.VOL_Vil_Arrivee_Id FROM Vol v WHERE v.VOL_Id = @IdVolExistant
-- Vérifie s'il existe un vol aller pour le vol inséré
IF (@IdVilleDepartInseree = @IdVilleArriveeExistant) AND (@IdVilleArriveeInseree = @IdVilleDepartExistant)
... скажите мне, что мы хотим ограничить наш набор на основе данных из исходного запроса. Это обрезает набор только до этих совпадающих строк. Давайте сделаем это:
SELECT -- dunno what we need yet
FROM Vol
JOIN Planning
ON Planning.pla_vol_Id = Vol.vol_id
JOIN Reservation
ON Reservation.res_pla_id = Planning.pla_Id
AND Reservation.res_client_id = @IdClient
WHERE Vol.vol_vil_depart_id = @IdVilleArriveeInseree
AND Vol.vil_arrivee_id = @IdVilleDepartInseree
... следующий запрос получает данные для простого условия:
IF ( (DATEDIFF(DAY, @DateVolExistant , @DateVolInsere)) < 60 )
... но опять же, у нас уже есть эти данные, и мы можем добавить их к нашему запросу:
SELECT -- dunno what we need yet
FROM Vol
JOIN Planning
ON Planning.pla_vol_Id = Vol.vol_id
AND Planning.pla_date < DATEADD(day, 60, CAST(@DateVolInsere AS DATE))
JOIN Reservation
ON Reservation.res_pla_id = Planning.pla_Id
AND Reservation.res_client_id = @IdClient
WHERE Vol.vol_vil_depart_id = @IdVilleArriveeInseree
AND Vol.vil_arrivee_id = @IdVilleDepartInseree
... К сожалению, основное условие следующего раздела, скорее всего, бессмыслица:
v.VOL_Id BETWEEN @IdVolExistant AND @IdVolInsere
... это потому, что он предполагает неключевые отношения о ключе. Если это автоматически генерируемые суррогатные ключи, это определенно не соответствует действительности. Наиболее вероятные схемы ключей для естественного ключа вряд ли будут полезны во всех случаях. Гораздо лучше использовать атрибутивные данные, которые для этого типа запроса обычно являются датой. Я думаю, мы можем использовать Planning.pla_date
для этого:
SELECT -- dunno what we need yet
FROM Vol
JOIN Planning
ON Planning.pla_vol_Id = Vol.vol_id
AND Planning.pla_date >= DATEADD(day, -60, CAST(@DateVolInsere AS DATE))
JOIN Reservation
ON Reservation.res_pla_id = Planning.pla_Id
AND Reservation.res_client_id = @IdClient
JOIN Planning Planning_Other
ON Planning_Other.pla_date >= Planning.pla_date
AND Planning_Other.pla_date < @DateVolInsere
AND Planning_Other.pla_id != Planning.pla_id
JOIN Reservation Reservation_Other
ON Reservation_Other.res_pla_id = Planning_Other.pla_id
AND Reservation_Other.res.client_id = @IdClient
AND Reservation_Other.res_id != Reservation.res_id
WHERE Vol.vol_vil_depart_id = @IdVilleArriveeInseree
AND Vol.vil_arrivee_id = @IdVilleDepartInseree
... и в этот момент мы наблюдаем, что на самом деле нам нет дела до каких-либо данных, а только от того, существует ли такая строка. К счастью, мы можем превратить это в обычное предложение EXISTS
.