SQL Server: у запроса ROLLBACK TRANSACTION нет соответствующей BEGIN TRANSACTION - PullRequest
0 голосов
/ 10 мая 2018

У меня есть триггер, который работает (он срабатывает, когда должен), но я все равно получаю сообщение об ошибке. Я понимаю ошибку, но не знаю, как ее устранить.

Я пытался установить НЕКОТОРЫЕ СДЕЛКИ со всем кодом, который идет с ним, но я думаю, что моя грамматика неверна, потому что я всегда получаю тайм-аут!

Итак, мой вопрос: где именно я должен поместить свои 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

EDIT

Хорошо, поэтому я попробовал ваш ответ без курсора (я понимаю, что мой путь был явно не лучшим!), Но пока он не работает.

Моя цель: у меня есть БД для бронирования рейса. В этой базе данных у меня есть таблица «Транш», в которой указаны некоторые даты и цены (в зависимости от времени полета).

Мне нужно предотвратить и избежать любого совпадения даты рождения, например:

1y-17y: 80€
18y-64y: 120€

Так что мой триггер должен срабатывать, когда я пытаюсь вставить 17y-63y: xx € (потому что у меня уже есть цена для этих возрастов).

Извините, если мой английский не идеален, кстати!

Вот мой стол "Транш":

https://i.stack.imgur.com/KuQH8.png

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 Ответ

0 голосов
/ 10 мая 2018

Я действительно не знаю, каковы цели ОП здесь.Тем не менее, я хотел опубликовать небольшой пример того, как сделать подход к набору данных и как проверить все строки за один раз.

В настоящий момент триггер, который имеет OP, будет «работать» только в том случае, если пользовательвставляет 1 ряд.Больше, и вещи не будут работать должным образом.Тогда у нас также есть проблема CURSOR.Я отмечаю, что объявление курсоров вообще не ссылается на inserted, поэтому я на самом деле не знаю, каковы их цели.Похоже, что OP выполняет аудит данных, уже находящихся в таблице, когда происходит 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

Данный вопрос, кажется, в значительной степени является вопросом ху;проблема не в CURSOR или ROLLBACK, проблемы с этим триггером гораздо более фундаментальные.Я бы предложил пересмотреть ваш вопрос и на самом деле объяснить вашу цель того, что вы хотите сделать со своим триггером.Предоставьте DDL для CREATE вашей таблицы и INSERT операторов для любых данных выборки.Возможно, вы захотите также предоставить некоторые операторы INSERT, которые будут иметь разные результаты для вашего триггера (обязательно включите те, которые содержат более одной строки за раз).

Я понимаю, что это большекомментируя, однако, опять же, в комментарии определенно недостаточно места, чтобы написать все это.:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...