Когда я запускаю подзапрос (триггер) в хранимой процедуре, я получаю ошибку.Подзапрос вернул более 1 значения.Это не т - PullRequest
0 голосов
/ 20 сентября 2019

Когда я пытался запустить свою процедуру (smažPoložky_SP) и удалить некоторые строки, я получаю

Подзапрос вернул более 1 значения. Это недопустимо, если подзапрос следует =,! =, <,<=,>,> = или когда подзапрос используется как выражение

, потому что мой триггер.(триггер вместо удаления)

CREATE TRIGGER zkontrolujMnožství ON Zboží
 INSTEAD OF DELETE
AS 
 DECLARE @p_mnozstvi INTEGER = (SELECT množstvíSklad FROM deleted) -- Getting number of goods
BEGIN 
 IF @p_mnozstvi < 0 -- Try to know if is empty 
     EXECUTE vyvolej_chybu_sp 15 -- Raise error
 ELSE 
     DELETE FROM Zboží WHERE (SELECT zbožíID FROM deleted) = zbožíID 
END;
alter PROCEDURE testSmazani (@id_jednotky INTEGER) AS 
BEGIN 
    BEGIN TRANSACTION  /* SELECT for get information if id exists */
            IF EXISTS(SELECT měrnáJednotkaID FROM MěrnéJednotky WHERE měrnáJednotkaID = @id_jednotky)
                BEGIN 
                    /* This delete is error because my = in trigger */
                    DELETE FROM Zboží WHERE měrnáJednotka = @id_jednotky  
                    DELETE FROM MěrnéJednotky WHERE měrnáJednotkaID = @id_jednotky
                    COMMIT;
                end
                else
                rollback
END;

Ответы [ 2 ]

2 голосов
/ 20 сентября 2019

В вашем триггере эта строка:

DELETE FROM Zboží WHERE (SELECT zbožíID FROM deleted) = zbožíID 

Произойдет ошибка, если deleted содержит более одной строки.

Просто напишите это вместо этого:

DELETE FROM Zboží WHERE zbožíID IN (SELECT zbožíID FROM deleted)

Кроме того, способ объявления и заполнения @p_mnozstvi также приведет к ошибке, если deleted содержит более одной строки.

Не будет ошибки, если вы сделаете это таким образом, но вы можете получитьнеожиданные результаты:

DECLARE @p_mnozstvi INTEGER;
SELECT @p_mnozstvi = množstvíSklad FROM deleted;

Вероятно, было бы лучше переосмыслить, как вы хотите обрабатывать эту часть логики, когда deleted содержит несколько строк.Возможно, используйте EXISTS(), чтобы проверить, содержит ли какая-либо строка значение ноль (или не ноль, в зависимости от того, как вы хотите его обработать).

0 голосов
/ 20 сентября 2019

Ваш триггер не учитывает, что deleted может иметь более одной строки.Непонятно, что именно вы хотите сделать, но похоже, что вам нужен цикл:

CREATE TRIGGER zkontrolujMnožství ON Zboží INSTEAD OF DELETE
AS BEGIN 
    DECLARE @p_mnozstvi INTEGER;
    DECLARE d_cursor CURSOR FOR
        SELECT množstvíSklad FROM deleted;

    OPEN d_cursor;
    FETCH NEXT FROM d_cursor INTO @p_mnozstvi;

    WHILE @@FETCH_STATUS = 0  
    BEGIN  
        IF @p_mnozstvi < 0 -- Try to know if is empty 
            EXECUTE vyvolej_chybu_sp 15; -- Raise error
        ELSE 
            DELETE FROM Zboží WHERE zbožíID IN (SELECT zbožíID FROM deleted);
    END;
    CLOSE db_cursor; 
    DEALLOCATE db_cursor;
END;

Столько, сколько мне не нравятся курсоры, если вы хотите вызывать хранимую процедуру для каждого значения, то естьвероятно, лучший подход.

РЕДАКТИРОВАТЬ:

Если вы хотите вызвать ошибку, если любое значений отрицательные, то вам не нужен курсор:

CREATE TRIGGER zkontrolujMnožství ON Zboží INSTEAD OF DELETE
AS BEGIN     
    IF (EXISTS (SELECT 1 FROM deleted WHERE množstvíSklad < 0)
        EXECUTE vyvolej_chybu_sp 15; -- Raise error
    ELSE 
        DELETE FROM Zboží
            WHERE zbožíID IN (SELECT zbožíID FROM deleted);
END;
...