Моя проблема в том, что я достиг предела стека. И сообщение об ошибке говорит: «Вы должны увеличить max_stack_depth
» и показывает мне строку, которую я использую для обновления другого столбца.
Я сталкиваюсь с этой ошибкой после запроса на обновление (код ниже).
Я знаю, что моя проблема может выглядеть как другие вопросы, но ни один из них не объясняет, почему я получаю эту ошибку.
То, что я хочу сделать, простое, и я делал это много раз, но здесь мне чего-то не хватает.
Я хочу: если есть обновление на столе support_fh
нажать на курок. Я ожидаю, что этот триггер сделает:
если новые значения запроса на обновление section
= 'DISTRIBUTION'
и modulo
= '6'
и fabricant
= 'NEXANS'
и capacite
= 12
, то установите diametre
= '12.5'
(код ниже).
Конечно, это строка diametre
из той же строки, что и запрос на обновление.
Кроме того, я знаю, что должен использовать тип character varying
вместо типа integer
, но меня попросили сделать так.
Моя триггерная функция:
create or replace function maj_diam() returns trigger
as
$$
Declare fab_loc character varying;
Declare section_loc character varying;
Declare capa_loc character varying;
Declare modulo_loc character varying;
BEGIN
Select fabricant into fab_loc from support_fh where id = new.id;
Select section into section_loc from support_fh where id = new.id;
Select capcite into capa_loc from support_fh where id = new.id;
Select modulo into modulo_loc from support_fh where id = new.id;
if fab_loc = 'NEXANS' and section_loc = 'DISTRIBUTION'
and capa_loc = '12' and modulo_loc = '6' then
update support_fh set diametre = '12.2' where id = new.id;
endif;
return new;
end;
$$;
Мой триггер:
create trigger maj_diam
After update on support_fh
for each row
execute procedure maj_diam();
Мой запрос на обновление для проверки моего триггера:
update support_fh set fabricant = 'NEXANS', section = 'DISTRIBUTION', capacite = '12', modulo = '6'
where id = 11827;
Я хочу извлечь из этого урок, поэтому, если возможно, объясните мне, что я здесь делаю неправильно, или в моем подходе не хватает понимания.
@a_horse_with_no_name Я не делал БД, я просто помогаю кому-то с триггерами. Но вы правы, целое число или число с плавающей запятой должны быть здесь правильным типом.
Вы получаете эту проблему, потому что обновление в триггере снова запускает триггер, вызывая бесконечный цикл. Никакое значение max_stack_depth
не является достаточно большим для этого (и слишком большое увеличение этого значения в любом случае опасно).
Вместо того, что вы делаете, вы должны создать триггер BEFORE
и изменить значение NEW
, которое должно быть вставлено:
IF NEW.fab_loc = 'NEXANS' AND NEW.section_loc = 'DISTRIBUTION'
AND NEW.capa_loc = '12' AND NEW.modulo_loc = '6'
THEN
NEW.diametre := '12.2';
END IF;
Я подумал, что если я хочу изменить значение из той же строки, необходим триггер AFTER
. Виноват ! Имеет смысл, что если триггер использует запрос на обновление, это вызывает бесконечный цикл. Спасибо за ваше время и ответ!
Если вы хотите изменить столбцы в обновляемой (или вставленной) строке, не используйте UPDATE
в функции триггера. Объявите триггер как BEFORE UPDATE
, затем просто назначьте новые значения.
Вам также не нужны четыре оператора select для чтения четырех столбцов из одной и той же таблицы.
Но поскольку вы получаете доступ только к столбцам из той же строки, которая была обновлена, вам вообще не нужен SELECT.
Таким образом, ваша триггерная функция может быть упрощена до:
create or replace function maj_diam() returns trigger
as
$$
BEGIN
if new.fabricant = 'NEXANS'
and new.section = 'DISTRIBUTION'
and new.capcite = '12'
and new.modulo = '6'
then
new.diametre := '12.2';
end if;
return new;
end;
$$;
Предполагая, что капцит, модуль и диаметр на самом деле являются числами, вы не должны сравнивать их со значениями varchar. Таким образом, приведенный выше код, вероятно, должен быть: new.diametre := 12.2;
или new.capcite = 12
.
И определение триггера необходимо изменить на:
create trigger maj_diam
BEFORE update on support_fh
for each row
execute procedure maj_diam();
Почему вы храните числа как значения varchar?