Ошибка триггера pl/sql: точная выборка возвращает больше запрошенного количества строк
Мне трудно понять, что не так с моим триггером pl/sql. Ошибка: Отчет об ошибке - Ошибка SQL: ORA-01422: точная выборка возвращает больше запрошенного числа строк ORA-06512: в "SYSTEM.TRG_LATE_RETURN", строка 6 ORA-04088: ошибка во время выполнения триггера "SYSTEM.TRG_LATE_RETURN' 01422. 00000 - "Точная выборка возвращает больше запрошенного количества строк" * Причина: число, указанное в точной выборке, меньше возвращаемых строк. * Действие: переписать запрос или изменить количество запрошенных строк
Мой триггер выглядит следующим образом:
create or replace trigger trg_late_return
before update of DETAIL_RETURNDATE, DETAIL_DUEDATE on TY_DETAILRENTAL
declare
temp_date DATE:= SYSDATE;
temp_due_date DATE:= SYSDATE;
BEGIN
select DETAIL_RETURNDATE
into temp_date
from TY_DETAILRENTAL;
select DETAIL_DUEDATE
into temp_due_date
from TY_DETAILRENTAL;
IF temp_date is null
THEN
update TY_DETAILRENTAL
set DETAIL_DAYSLATE=null;
END IF;
if temp_date <> null
THEN
if temp_date = trunc(temp_due_date) + 1
then
update TY_DETAILRENTAL
set DETAIL_DAYSLATE=0;
end if;
if temp_date > trunc(temp_due_date) + 1
then
update TY_DETAILRENTAL
set DETAIL_DAYSLATE = DETAIL_RETURNDATE - DETAIL_DUEDATE;
end if;
end if;
END;
/
Новичок в SQL и PL/SQL, поэтому я был бы признателен за любую помощь.
1 ответ
Ни один из ваших запросов или обновлений не имеет фильтров (где предложения), поэтому вы работаете со всей таблицей - это не может быть тем, что вы хотели. Вы пытаетесь получить все значения этих столбцов в скалярных переменных, которые могут содержать только одно значение.
Триггер также работает с той же таблицей, которую вы запрашиваете и обновляете, что говорит о том, что вы на самом деле подразумевали, что это (или нужно, чтобы это было) триггер уровня строки, а не триггер уровня оператора.
Это означает, что вам нужно добавить for each row
к определению, и вместо того, чтобы запрашивать и обновлять таблицу, вы можете работать с new
псевдозапись, доступная для триггеров уровня строки.
Вы также не можете использовать <>
сравнить с нулем; вы уже используете is null
и противоположность этому is not null
, Хотя вы могли бы просто использовать else
Вот.
Так что это может быть то, что вы хотели:
create or replace trigger trg_late_return
before update of detail_returndate, detail_duedate
on ty_detailrental
for each row
begin
if :new.detail_returndate is null
then
:new.detail_dayslate := null;
else
if :new.detail_returndate = trunc(:new.detail_duedate) + 1
then
:new.detail_dayslate := 0;
elsif :new.detail_returndate > trunc(:new.detail_duedate) + 1
then
:new.detail_dayslate := :new.detail_returndate - :new.detail_duedate;
end if;
end if;
end;
/
Вы можете обратиться к обновленному значению столбцов с помощью :new
при их сравнении, так что вам не нужны копии локальных переменных этих значений. (Вы можете посмотреть на значения перед обновлением с :old
тоже, но в этом нет необходимости).
Изменения, которые вы вносите в new
псевдозапись используется, когда фактическая совпадающая строка в базе данных наконец обновляется.
Узнайте больше о новых / старых псевдозаписях и о триггерах в целом.