Sql error 54001 ошибка превышен предел глубины стека

Ваш триггер срабатывает на событие BEFORE UPDATE, а внутри него происходит еще один update, который снова вызывает этот триггер, что приводит к бесконечной рекурсии.

Также немного странным выглядит само обновление:

UPDATE trips set all_sum_column = summ;

Вы действительно хотите обновить all_sum_column всех записей таблицы на одно и тоже значение при обновлении одной из них?

Я полагаю, что это просто ошибка в коде (потому что при подсчете суммы вы учитываеете только текущую запись trips.id_route = routes.id_route), и вы хотите обновить только текущую запись из tips. В таком случае необходимо обновлять не через update, а используя специальное ключевое слово, доступное внутри триггера — NEW (оно представляет собой новую версию обновляемой строки, также есть OLD — предыдущая версия соответственно):

NEW.all_sum_column = summ;

Это не вызовет последующего выполнения триггера еще раз.

Триггер будет выглядеть так:

create or replace function month_sum_update1() returns trigger as
$BODY$
DECLARE
    summ int;
BEGIN
    select sum(quantity*price) into summ from trips, routes
    WHERE routes.id_route = NEW.id_route
      AND (date_travel<=now() AND date_travel>=now()-interval '1 month');
    NEW.all_sum_column = summ;
    return NEW;
END;
$BODY$
    language plpgsql;

Больше о триггерах в официальной документации.

Давайте поясню. Триггер в вашем случае вызывается перед вставкой данных. Ему автоматически передаётся переменная NEW, в которой содержатся значения, которые должны вставиться: NEW.id, NEW.guid, NEW.name.
Так вот этот триггер может просто поменять вставляемые значения. Например, в триггерной функции вы подменяете значение uuid на то, что вам нужно:

NEW.uuid = md5(random()::text || clock_timestamp()::text)::uuid;

после этого триггер должен вернуть изменённые значения NEW:
return NEW;
Для вставки в таблицу будет испрользовано то, что вернул триггер, т.е. NEW, в том числе и NEW.guid, который вы указали в триггерной функции.

Возможно, устроит более простое решение: объявить в таблице значение поля uuid по умолчанию:

CREATE TABLE public."USERS"
(
  id integer,
  guid uuid default md5(random()::text || clock_timestamp()::text)::uuid,
  name text
)

в таком случае можно обойтись без триггеров.

A function may not see the same state of the database depending on whether it’s VOLATILE or not, when this state is changing during the execution of the SQL statement it’s called from, either because of the statement itself or because of another transaction if the isolation level is
Read Committed.

This is documented in https://www.postgresql.org/docs/current/xfunc-volatility.html

For functions written in SQL or in any of the standard procedural
languages, there is a second important property determined by the
volatility category, namely the visibility of any data changes that
have been made by the SQL command that is calling the function. A
VOLATILE function will see such changes, a STABLE or IMMUTABLE
function will not. This behavior is implemented using the snapshotting
behavior of MVCC (see Chapter 13): STABLE and IMMUTABLE functions use
a snapshot established as of the start of the calling query, whereas
VOLATILE functions obtain a fresh snapshot at the start of each query
they execute.

If your function reads the database and follows different paths depending on what it reads, it’s quite possible that it goes into infinite recursion only when it’s not VOLATILE. Looking at the code might be revealing.

I Create trigger to store the Salary Amount but When I Fire The Query For Insert

INSERT INTO employees(
            employee_id, first_name, last_name, email, phone_number,  hire_date, 
            job_id, salary, commission_pct, manager_id, department_id)
    VALUES (2002,'poiuy','patel','bhargavgor@dfghj',9898562123,'2012-07-31 00:00:00','IT_PROG',4500.00,0.00,100,60);

Then It Will Show Me The Following Error To set the limit of the max_stack_depth So Can Any One Give Me The Idea TO Solve This Error..

I Try Also To Change The Value Of max_stack_depth in Configuration File But It IS Not Working

Error Like Following

ERROR:  stack depth limit exceeded
HINT:  Increase the configuration parameter "max_stack_depth" (currently 2048kB), after ensuring the platform's stack depth limit is adequate.

Ваш триггер срабатывает на событие BEFORE UPDATE, а внутри него происходит еще один update, который снова вызывает этот триггер, что приводит к бесконечной рекурсии.

Также немного странным выглядит само обновление:

UPDATE trips set all_sum_column = summ;

Вы действительно хотите обновить all_sum_column всех записей таблицы на одно и тоже значение при обновлении одной из них?

Я полагаю, что это просто ошибка в коде (потому что при подсчете суммы вы учитываеете только текущую запись trips.id_route = routes.id_route), и вы хотите обновить только текущую запись из tips. В таком случае необходимо обновлять не через update, а используя специальное ключевое слово, доступное внутри триггера — NEW (оно представляет собой новую версию обновляемой строки, также есть OLD — предыдущая версия соответственно):

NEW.all_sum_column = summ;

Это не вызовет последующего выполнения триггера еще раз.

Триггер будет выглядеть так:

create or replace function month_sum_update1() returns trigger as
$BODY$
DECLARE
    summ int;
BEGIN
    select sum(quantity*price) into summ from trips, routes
    WHERE routes.id_route = NEW.id_route
      AND (date_travel<=now() AND date_travel>=now()-interval '1 month');
    NEW.all_sum_column = summ;
    return NEW;
END;
$BODY$
    language plpgsql;

Больше о триггерах в официальной документации.

Я пытаюсь создать триггер, когда после вставки рисунка я хочу вставить его в таблицу In_Gallery или On_Loan, но не в обе. Когда я пытался создать функцию триггера, я продолжал получать сообщение об ошибке:

ERROR: stack depth limit exceeded
HINT:  Increase the configuration parameter "max_stack_depth" (currently 2048kB), after ensuring the platform's stack depth limit is adequate.

Я не уверен, что с этим не так:

    CREATE OR REPLACE FUNCTION checkOnLoan()    
    RETURNS trigger AS
$$
    DECLARE    
       countGal numeric;
    BEGIN
            SELECT COUNT(*) INTO countGal FROM IN_GALLERY WHERE P_id = new.P_id;
            IF countGal = 0 THEN    
                INSERT INTO ON_LOAN VALUES (new.Certid, new.P_id, new.Insurer);
            ELSE
                RAISE EXCEPTION 'ALREADY IN GALLERY';
            END IF;
    RETURN new;
    END;
$$

LANGUAGE 'plpgsql';

CREATE TRIGGER OnLoan
    AFTER INSERT ON ON_LOAN
    FOR EACH ROW
    EXECUTE PROCEDURE checkOnLoan();

2 ответа

Непосредственной причиной вашей ошибки является бесконечный цикл, подобный объясненному в настоящее время принятому ответу. Но вы должны, вероятно, исправить больше, чем просто это. Триггер BEFORE улучшит ситуацию …

Функция запуска:

CREATE OR REPLACE FUNCTION check_onloan()
  RETURNS trigger AS
$$
BEGIN
   IF EXISTS (SELECT FROM in_gallery WHERE p_id = NEW.p_id) THEN
      RAISE EXCEPTION 'p_id % already in gallery!', NEW.p_id;
   END IF;
   RETURN NEW;  -- for BEFORE trigger
END
$$  LANGUAGE plpgsql;

Курок:

CREATE TRIGGER insert_after_on_loan
BEFORE INSERT ON on_loan             -- !!!
FOR EACH ROW EXECUTE PROCEDURE check_onloan();

RETURN NEW не имеет никакого смысла вообще для триггера AFTER. Руководство:

Возвращаемое значение игнорируется для триггеров уровня строки, запускаемых после операции, и поэтому они могут возвращать NULL.

Мое обоснованное предположение: вам нужен триггер BEFORE. Осталось только сделать исключение. Дешевле проверить перед выполнением работы, чем откатить ее позже. Для этой цели обычно эффективнее проверять существование с помощью IF EXISTS ..., а не подсчитывать. Тогда вам не нужно определять какие-либо переменные и нет DECLARE раздела.

Связанный:

  • PL / pgSQL проверяет, существует ли строка

  • Откат транзакции при ошибке запуска

Очевидно, вам нужен еще один зеркальный триггер для таблицы in_gallery в этом дизайне — который, вероятно, не идеален для начала.

Как бы вы это ни делали, будет оставшееся состояние гонки . При одновременной загрузке записи несколько транзакций могут попытаться ввести один и тот же p_id в обе таблицы практически в одно и то же время, но пока не увидеть p_id в таблице other , и введите его в обе таблицы. Это помогает держать транзакции короткими, чтобы минимизировать временные рамки, но проблема остается в принципе.

Одним чистым решением будет одна таблица painting с флагом boolean, указывающей ее статус. Это может иметь только одно состояние за раз. Детали зависят от вашей полной ситуации …

В стороне: пересмотреть регистр написания идентификаторов в CaMeL в Postgres.

  • Имена столбцов PostgreSQL чувствительны к регистру?


1

Erwin Brandstetter
2 Дек 2019 в 02:04

Вы снова INSERT в триггере AFTER INSERT, вызывая повторный запуск триггера в течение этой секунды INSERT, который снова INSERT запускает и запускает триггер заново, и так далее, и так далее , В какой-то момент стек исчерпан всеми вызовами этой функции, и вы получите ошибку.

Удалите INSERT из функций триггера и просто RETURN new. Возвращение new приведет к завершению оригинала INSERT. Для триггеров AFTER INSERT нет необходимости вручную INSERT в функции триггера.

Как:

CREATE OR REPLACE FUNCTION checkOnLoan()    
RETURNS trigger AS
$$
DECLARE    
    countGal numeric;
BEGIN
    SELECT COUNT(*) INTO countGal FROM IN_GALLERY WHERE P_id = new.P_id;
    IF countGal = 0 THEN    
        RETURN new;
    ELSE
        RAISE EXCEPTION 'ALREADY IN GALLERY';
    END IF;
END;
$$
LANGUAGE plpgsql;

И аналог для другой триггерной функции.


3

sticky bit
30 Ноя 2019 в 00:49

Хорошо, если вы действительно хотите, чтобы триггер обновлялся, что вы могли бы сделать, чтобы установить этот триггер как специфичный для столбца, чтобы он не запускался при обновлении до all_books, что вызывает вашу рекурсию. Что-то вроде этого —

create trigger total2
after update of copy_id
on totalbooks
for each row
execute procedure total1();

Конечно, вы можете изменить, какие столбцы запускают функцию, я просто выбрал copy_id потому что это то, что вы считаете.

ОДНАКО

Если вы обновляете с помощью count() результат, вы можете просто включить триггер INSERT и DELETE действия. Таким образом, триггер будет срабатывать при изменении счетчика, но сам не будет срабатывать при обновлении. // РЕДАКТИРОВАТЬ: так как ваш sum это всего лишь подсчет всех записей в copies, он изменится только при вставке или обновлении записи, поэтому запуск этого триггера при обновлении в любом случае не имеет смысла.

РЕДАКТИРОВАТЬ: я подумал, что было бы полезно добавить ссылку на СОЗДАТЬ ТРИГГЕР Документация. См. раздел с пометкой «событие», потому что в нем подробно описано, как указывать столбцы в событии.

РЕДАКТИРОВАТЬ ДЛЯ НОВОЙ ИНФОРМАЦИИ:

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

Иметь books таблица, где каждая строка содержит информацию об одной книге (название, автор и т. д.), а затем copies таблица, в которой каждая строка содержит информацию об одной копии книги (серийный номер, дата последнего извлечения и т. д.).

Таким образом, получить количество копий так же просто, как SELECT COUNT(*) FROM copies WHERE book_id=[some book id].

Если вы действительно хотите где-то кэшировать счетчик, сделайте это на books таблице.

Создать INSERT OR UPDATE запускать copies это делает UPDATE books SET copy_count=(SELECT COUNT(*) FROM copies WHERE book_id=NEW.book_id) WHERE id=NEW.book_id.

Затем создайте DELETE триггер на копиях, которые делают UPDATE books SET copy_count=(SELECT COUNT(*) FROM copies WHERE book_id=OLD.book_id) WHERE id=OLD.book_id

Причина двух триггеров заключается в том, что NEW переменная доступна только в INSERT or UPDATE триггеры и OLD доступно только в DELETE триггеры. Вы могли бы сделать все это как один триггер, но для этого потребуется больше кода, чем я хотел бы разместить здесь.

Убедитесь, что все ваши триггеры AFTER триггеры, иначе новая вставленная/удаленная строка не будет учитываться при подсчете.

Я stack depth limit exceeded при попытке сохранить строку из R в PostgreSQL. Чтобы решить проблему с массовыми upserts, я использовал такой запрос:

sql_query_data <- sprintf("BEGIN;
CREATE TEMPORARY TABLE
ts_updates(ts_key varchar, ts_data hstore, ts_frequency integer) ON COMMIT DROP;
INSERT INTO ts_updates(ts_key, ts_data) VALUES %s;
LOCK TABLE %s.timeseries_main IN EXCLUSIVE MODE;

UPDATE %s.timeseries_main
SET ts_data = ts_updates.ts_data,
ts_frequency = ts_updates.ts_frequency
FROM ts_updates
WHERE ts_updates.ts_key = %s.timeseries_main.ts_key;

INSERT INTO %s.timeseries_main
SELECT ts_updates.ts_key, ts_updates.ts_data, ts_updates.ts_frequency
FROM ts_updates
LEFT OUTER JOIN %s.timeseries_main ON (%s.timeseries_main.ts_key = ts_updates.ts_key)
WHERE %s.timeseries_main.ts_key IS NULL;
COMMIT;",
values, schema, schema, schema, schema, schema, schema, schema)

}

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

Однако сейчас эта стратегия сталкивается с некоторыми проблемами. У меня больше нет записей, но несколько, в которых hstore немного больше. Но это действительно не «большой». Я читаю предложения @Craig Ringer, который советует не приближаться к пределу 1 ГБ. Поэтому я предполагаю, что размер самого hstore не является проблемой, но я получаю это сообщение:

Error in postgresqlExecStatement(conn, statement,...): RS-DBI driver: (could not Retrieve the result: ERROR: stack depth limit exceeded HINT: Increase the configuration parameter "max_stack_depth" (currently 2048kB), after ensuring the platform stack depth limit is adequate. )

EDIT: я увеличил лимит до 7 МБ и столкнулся с той же ошибкой, что и 7 МБ. Это действительно странно для меня, потому что я сам запрос составляет всего 1,7 МБ (проверял его, вставляя его в текстовый файл). Может ли кто-нибудь пролить свет на это?

38 / 33 / 12

Регистрация: 31.05.2012

Сообщений: 586

1

02.08.2017, 16:09. Показов 4110. Ответов 5


всем привет! Создал тригер для инсерта и в результате вставки выдает ошибку

[54001] ERROR: stack depth limit exceeded Подсказка: Increase the configuration parameter «max_stack_depth» (currently 2048kB), after ensuring the platform’s stack depth limit is adequate. Где: SQL statement «SELECT 1 FROM ONLY «public».»posts» x WHERE «id» OPERATOR(pg_catalog.=) $1 FOR KEY SHARE OF x» SQL statement «INSERT INTO public.post_content (htmlcode, type, post_id) VALUES (NEW.htmlcode, NEW.type, 37)» PL/pgSQL function increment_type_of_post_content() line 4 at SQL statem …
Details

Может кто подсказать чего он хочет?

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь

0

4719 / 3927 / 994

Регистрация: 29.08.2013

Сообщений: 25,181

Записей в блоге: 3

02.08.2017, 16:55

2

СУБД нужно угадать?

0

38 / 33 / 12

Регистрация: 31.05.2012

Сообщений: 586

02.08.2017, 18:24

 [ТС]

3

Цитата
Сообщение от qwertehok
Посмотреть сообщение

СУБД нужно угадать?

postgres

0

4719 / 3927 / 994

Регистрация: 29.08.2013

Сообщений: 25,181

Записей в блоге: 3

02.08.2017, 18:48

4

Цитата
Сообщение от Левиафам
Посмотреть сообщение

Подсказка: Increase the configuration parameter «max_stack_depth» (currently 2048kB), after ensuring the platform’s stack depth limit is adequate

читали?

0

38 / 33 / 12

Регистрация: 31.05.2012

Сообщений: 586

02.08.2017, 23:49

 [ТС]

5

Цитата
Сообщение от qwertehok
Посмотреть сообщение

читали?

ну это как-то странно что превышает 2 метра, может я что-то не так делаю….

0

1184 / 914 / 367

Регистрация: 02.09.2012

Сообщений: 2,785

03.08.2017, 04:54

6

Цитата
Сообщение от Левиафам
Посмотреть сообщение

может я что-то не так делаю…

Покажите тогда хотя бы код триггера, триггерной функции, ну и самого SQL-выражения, которое приводит к срабатыванию триггера.

0

IT_Exp

Эксперт

87844 / 49110 / 22898

Регистрация: 17.06.2006

Сообщений: 92,604

03.08.2017, 04:54

6

Понравилась статья? Поделить с друзьями:
  • Spore ошибка 1001
  • Spore исправление ошибок
  • Sql error 42p01 ошибка отношение не существует
  • Spore steam ошибка подключения к серверу spore
  • Sql error 42501 ошибка нет доступа к схеме