Как обновить ту же строку, что и вставка/обновление в plpgsql, не достигая max_stack_depth

Моя проблема в том, что я достиг предела стека. И сообщение об ошибке говорит: «Вы должны увеличить 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;

Я хочу извлечь из этого урок, поэтому, если возможно, объясните мне, что я здесь делаю неправильно, или в моем подходе не хватает понимания.

Почему вы храните числа как значения varchar?

a_horse_with_no_name 09.04.2019 11:57

@a_horse_with_no_name Я не делал БД, я просто помогаю кому-то с триггерами. Но вы правы, целое число или число с плавающей запятой должны быть здесь правильным типом.

LyessD 09.04.2019 12:00
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
38
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы получаете эту проблему, потому что обновление в триггере снова запускает триггер, вызывая бесконечный цикл. Никакое значение 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. Виноват ! Имеет смысл, что если триггер использует запрос на обновление, это вызывает бесконечный цикл. Спасибо за ваше время и ответ!

LyessD 09.04.2019 14:04

Если вы хотите изменить столбцы в обновляемой (или вставленной) строке, не используйте 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();

Другие вопросы по теме