SQL Server: у запроса ROLLBACK TRANSACTION нет соответствующей BEGIN TRANSACTION
У меня есть триггер, который работает (он срабатывает, когда это необходимо), но я все еще получаю сообщение об ошибке. Я понимаю ошибку, но не знаю, как ее устранить.
Я пытался установить НЕКОТОРЫЕ СДЕЛКИ со всем кодом, который идет с ним, но я думаю, что моя грамматика неверна, потому что у меня всегда тайм-аут!
Итак, мой вопрос, где именно я должен поставить свой BEGIN TRANSACTION
заявления в моем коде?
Кроме того, мне нужно 3 BEGIN TRANSACTION
заявления, так как у меня есть 3 ROLLBACK
?
Заранее спасибо!
Мой код:
ALTER TRIGGER [dbo].[Tr_CheckOverlap]
ON [dbo].[Tranche]
FOR INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE @IdVol INT, @IdTranche INT,
@AgeMinInserted DATE, @AgeMaxInserted DATE
SELECT @AgeMinInserted = t.TRA_Age_Min
FROM Tranche t
JOIN inserted AS i ON t.TRA_Id = i.TRA_Id
SELECT @AgeMaxInserted = t.TRA_Age_Max
FROM Tranche t
JOIN inserted AS i ON t.TRA_Id = i.TRA_Id
DECLARE CR_TrancheVol CURSOR FOR
SELECT t.TRA_Vol_Id,t.TRA_Id
FROM Tranche t
JOIN inserted AS i ON t.TRA_Vol_Id = i.TRA_Vol_Id;
OPEN CR_TrancheVol
FETCH CR_TrancheVol INTO @IdVol, @IdTranche
WHILE( @@FETCH_STATUS = 0)
BEGIN
DECLARE @AgeMin DATE, @AgeMax DATE
SELECT @AgeMin = t.TRA_Age_Min
FROM Tranche t
WHERE t.TRA_Id = @IdTranche
SELECT @AgeMax = t.TRA_Age_Max
FROM Tranche t
WHERE t.TRA_Id = @IdTranche
IF @AgeMinInserted > @AgeMin AND @AgeMinInserted < @AgeMax
BEGIN
PRINT 'Trans1'
RAISERROR('Overlap: Date de naissance minimum déjà couverte', 1, 420)
ROLLBACK TRANSACTION
END
IF @AgeMaxInserted > @AgeMin AND @AgeMaxInserted < @AgeMax
BEGIN
PRINT 'Trans2'
RAISERROR('Overlap: Date de naissance maximum déjà couverte', 1, 421)
ROLLBACK TRANSACTION
END
IF @AgeMinInserted < @AgeMin AND @AgeMaxInserted > @AgeMax
BEGIN
PRINT 'Trans3'
RAISERROR('Overlap: Tranche déjà couverte complètement', 1, 422)
ROLLBACK TRANSACTION
END
FETCH CR_TrancheVol INTO @IdVol, @IdTranche
END
CLOSE CR_TrancheVol
DEALLOCATE CR_TrancheVol
END
РЕДАКТИРОВАТЬ:
Итак, я попробовал ваш ответ без курсора (я понимаю, что мой путь был явно не лучшим!), Но пока он не работает.
Моя цель: у меня есть БД, чтобы забронировать рейс. В этой базе данных у меня есть таблица "Транш", в которой указаны некоторые даты и цены (в зависимости от времени полета).
Мне нужно предотвратить и избежать любого совпадения даты рождения, например:
1y-17y: 80€
18y-64y: 120€
Так что мой триггер должен срабатывать, когда я пытаюсь вставить 17y-63y: xx € (потому что у меня уже есть цена для этих возрастов).
Извините, если мой английский не идеален, кстати!
Вот мой стол "Транш":
TRA_Vol_ID - это внешний ключ другой таблицы "Vol", которая содержит рейсы
Вот код, который у меня есть:
ALTER TRIGGER [dbo].[Tr_CheckOverlap]
ON [dbo].[Tranche]
FOR INSERT
AS
BEGIN
/*
Some SQL goes here to get the value of Minimum age.
I assuming that it doesn't vary by entry, however,
I don't really have enough information to go on to tell
*/
SET NOCOUNT ON;
DECLARE @MinAge DATE, @MaxAge DATE
SELECT @MinAge = t.TRA_Age_Min
FROM Tranche t
JOIN Vol AS v ON v.VOL_Id = t.TRA_Vol_Id
JOIN inserted AS i ON t.TRA_Id = i.TRA_Id
WHERE t.TRA_Id = i.TRA_Id
SELECT @MaxAge = t.TRA_Age_Max
FROM Tranche t
JOIN inserted AS i ON t.TRA_Id = i.TRA_Id
JOIN Vol AS v ON v.VOL_Id = t.TRA_Vol_Id
WHERE t.TRA_Id = i.TRA_Id
IF (SELECT COUNT(CASE WHEN i.TRA_Age_Min > @MinAge AND i.TRA_Age_Min < @MaxAge THEN 1 END) FROM inserted i) > 0
BEGIN
RAISERROR('Overlap: Birthday min reached',1,430);
ROLLBACK
END
ELSE IF (SELECT COUNT(CASE WHEN i.TRA_Age_Max > @MinAge AND i.TRA_Age_Max < @MaxAge THEN 1 END) FROM inserted i) > 0
BEGIN
RAISERROR('Overlap: Birthday max reached',1,430);
ROLLBACK
END
END
1 ответ
Я действительно не знаю, каковы цели ОП здесь. Тем не менее, я хотел опубликовать небольшой пример, как сделать подход к набору данных и как проверить все строки за один раз.
В настоящий момент триггер, который имеет OP, будет "работать" только в том случае, если пользователь вставляет 1 строку. Больше, и вещи не будут работать должным образом. Тогда у нас также есть проблема CURSOR
, Я отмечаю, что объявление курсоров не ссылается inserted
вообще, так что я на самом деле не знаю, каковы их цели. Похоже, что ОП проверяет данные, уже находящиеся в таблице, когда INSERT
происходит, а не данные, которые вставляются. Это кажется очень странным.
Во всяком случае, это не решение для ОП, однако, мне не хватает места в комментарии, чтобы поместить все это. Может быть, это подтолкнет ОП в правильном направлении.
ALTER TRIGGER [dbo].[Tr_CheckOverlap]
ON [dbo].[Tranche]
FOR INSERT
AS
BEGIN
/*
Some SQL goes here to get the value of Minimum age.
I assuming that it doesn't vary by entry, however,
I don't really have enough information to go on to tell
*/
IF (SELECT COUNT(CASE WHEN i.Age < @MinAge THEN 1 END) FROM inserted i) > 0 BEGIN
RAISERROR('Age too low',1,430);
ROLLBACK
END
ELSE
IF (SELECT COUNT(CASE WHEN i.Age > @MaxAge THEN 1 END) FROM inserted i) > 0 BEGIN
RAISERROR('Age too high',1,430);
ROLLBACK
END
END
Вопрос под рукой, кажется, очень много xy вопрос; проблема не в CURSOR
или ROLLBACK
проблемы с этим триггером гораздо более фундаментальные. Я бы предложил пересмотреть ваш вопрос и на самом деле объяснить вашу цель того, что вы хотите сделать со своим триггером. Предоставить DDL для CREATE
ваш стол и INSERT
заявления для любых образцов данных. Вы можете также предоставить некоторые INSERT
операторы, которые будут иметь разные результаты для вашего триггера (не забудьте включить те, которые имеют более одной строки для вставки за один раз).
Я понимаю, что это больше комментирует, однако, опять же, мне явно не хватает места, чтобы написать все это.:)