Триггер для обеспечения того, чтобы каждая новая ставка была выше предыдущей. - PullRequest
0 голосов
/ 25 мая 2020

У меня проблема с моим триггером на SQL сервере.

Этот триггер проверяет, выше ли новые ставки, чем существующие, и, если нет, вызывает ошибку:

ALTER TRIGGER [dbo].[trg_bod_validate_Bodbedrag] 
ON [dbo].[bod] 
FOR INSERT, UPDATE
AS
DECLARE @v_Voorwerp numeric(25);
DECLARE @v_Bodbedrag char(6);
DECLARE @v_Max_Bodbedrag char(6);

select @v_Voorwerp = i.voorwerp, @v_Bodbedrag = i.bodbedrag
from Inserted i;

SELECT @v_Max_Bodbedrag = max(CAST(bodbedrag AS INT))
FROM bod
WHERE voorwerp = @v_Voorwerp;

IF @v_Max_Bodbedrag <=   @v_Bodbedrag 
BEGIN
        RAISERROR ('Bod moet hoger zijn dan gegeven bod.', 16, 1)
        ROLLBACK TRANSACTION
END;
ELSE
    PRINT 'Row Inserted';

Теперь я получаю эту ошибку. Сумма ставки меньше максимальной, это неприемлемо », даже когда я вставляю заявку, когда еще нет ставок.

В чем может быть проблема?

Для вашего сведения: Voorwerp: Product, Bodbedrag: Сумма ставки

1 Ответ

0 голосов
/ 25 мая 2020

На заметку:

  1. На SQL сервере псевдотаблицы Вставленные (и удаленные) могут иметь от 0 до N строк, где N - это количество вставляемых / обновляемых / удаляемых строк. И это нужно делать в любом триггере. Однако как только вы переключаетесь на мышление, основанное на множествах (вместо процедурного), вы в любом случае обнаруживаете, что это гораздо более простая проблема. в порядке, а те, которые нет, мы в основном должны отклонить всю вставку / обновление, даже если это всего одна строка, которая нарушает правила.

  2. Таким образом, соединение находит max(bodbedrag) для всех продуктов, которые существуют в Inserted - за исключением строки, которая вставляется / обновляется - потому что, насколько нам известно, вставка / обновление уже произошло и эти данные существуют в нашей базе данных - до тех пор, пока мы откатимся назад, если захотим.

  3. Я проигнорировал ваше использование char вместо decimal. В идеале вы должны исправить свои типы данных, но вы можете продолжить преобразование / преобразование, если вы используете sh. Я оставлю это вам.

  4. Обратите внимание, что в наши дни мы используем throw, а не raiserror.

ALTER TRIGGER [dbo].[trg_bod_validate_Bodbedrag] 
ON [dbo].[bod] 
FOR INSERT, UPDATE
AS
BEGIN
    SET NOCOUNT ON;

    -- Find the max of for inserted voorwerp's excluding the currently inserted/updated
    -- Is an update of existing bid even allowed
    IF EXISTS (
        SELECT 1
        FROM Inserted I
        LEFT JOIN (
          SELECT MAX(bodbedrag) bodbedrag
          FROM dbo.dob D
          INNER JOIN Inserted I ON I.voorwerp = D.voorwerp and I.ID <> D.ID
        ) D
        WHERE I.bodbedrag < coalesce(D.bodbedrag,0)
    ) BEGIN
        -- THROW should be used now, not RAISERROR
        -- RAISERROR ('Bod moet hoger zijn dan gegeven bod.', 16, 1);
        THROW 51000, 'Bod moet hoger zijn dan gegeven bod.', 1;  
        ROLLBACK TRANSACTION;
    END; ELSE BEGIN
        PRINT 'Row Inserted';
    END;
END
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...