Измените OLD, чтобы он возвращался DELETE в триггерной функции postgresql

У меня есть триггерная функция в postgresql, которая будет вставлять строки в таблицу аудита при операциях INSERT, UPDATE и DELETE. В моих таблицах есть столбец с именем Audit_id, и мне нужно записать в это поле идентификатор вставленной строки аудит. это моя функция

CREATE OR REPLACE FUNCTION my_audit_trigger()
 RETURNS trigger LANGUAGE plpgsql
AS $function$
declare
  audit_pk bigint;
begin
IF TG_OP = 'INSERT'
THEN
INSERT INTO audit.table_audit (rel_id, table_name, operation, after)
VALUES (TG_RELID, TG_TABLE_NAME, TG_OP, to_jsonb(NEW)) returning id into audit_pk;
 NEW.audit_id := audit_pk;
RETURN NEW;
ELSIF TG_OP = 'UPDATE'
THEN
IF NEW != OLD THEN
 INSERT INTO audit.table_audit (rel_id, table_name, operation, before, after)
VALUES (TG_RELID, TG_TABLE_NAME, TG_OP, to_jsonb(OLD), to_jsonb(NEW)) returning id into audit_pk;
END IF;
 NEW.audit_id := audit_pk;
RETURN NEW;
ELSIF TG_OP = 'DELETE'
THEN
INSERT INTO audit.table_audit (rel_id, table_name, operation, before)
VALUES (TG_RELID, TG_TABLE_NAME, TG_OP, to_jsonb(OLD)) returning id into audit_pk;
OLD.audit_id := audit_pk;
RETURN OLD;
END IF;
end;
$function$;

В результате при вставке или обновлении строк моей таблицы я возвращаю идентификатор аудита соответствующей операции, но когда я запускаю команду DELETE, я возвращаю идентификатор аудита предыдущей операции, а не самого DELETE. Так что думаю проблема в OLD.audit_id := audit_pk;

Точнее, я запускаю, например, INSERT INTO table VALUES (this, that) RETURNING audit_id и получаю обратно audit_id операции INSERT.

После этого при запуске DELETE FROM table WHERE id = sth RETURNING audit_id я получаю audit_id операции INSERT, а не DELETE.

Любая помощь приветствуется, спасибо.

P.S. Вот как я создаю триггер

CREATE TRIGGER table_trigger
BEFORE INSERT OR UPDATE OR DELETE
ON table
FOR EACH ROW
EXECUTE PROCEDURE my_audit_trigger();           

Я не совсем понимаю. Как вы «возвращаете» что-то из DELETE?

Laurenz Albe 03.04.2019 12:47

Добро пожаловать в StackOverflow! Не могли бы вы улучшить свой вопрос, поделившись выводом, который вы видите, и тем, что вы ожидаете вместо этого?

A. Stam 03.04.2019 12:48

Когда я запускаю ``` DELETE FROM table WHERE id = 12 RETURNING * ```, я возвращаю строку, которая возвращается функцией триггера

Sophio 03.04.2019 12:48

Мы не можем видеть, как поле id, которое возвращается в audit_pk, получает свое значение, так как это поле не указано в операторе вставки. Проблема должна заключаться в том, откуда берется это значение и почему оно устанавливается на неожиданное значение? Я не вижу проблемы в самом триггере, он должен быть в фактических данных в этой таблице аудита. Принимая во внимание, что это даже не таблица, в которую записываются операторы вставки или обновления, так как же это значение устанавливается в таблице affiliate_audit? Только у вас есть доступ к информации, чтобы понять это.

404 03.04.2019 14:27

@404 Идентификатор автоматически генерируется при каждой вставке в таблицу аудита. Я думаю, что эта часть в порядке, поскольку она работает точно так, как ожидалось для INSERT и UPDATE. При выполнении DELETE OLD содержит всю удаляемую строку, включая audit_id предыдущей операции. Что я пытаюсь сделать, так это обновить этот старый audit_id новым, но это не работает, я не знаю, почему

Sophio 03.04.2019 14:36

На данный момент игнорируйте бит OLD. Когда вы выполняете DELETE ... RETURNING *, возвращается ли audit_id то же самое, что и поле id строки аудита удаления в audit.table_audit? Если да, то триггер правильный. Если вы считаете, что audit_id должно быть новым значением, вы должны убедиться, что id записывается с новым значением при вставке записи об удалении.

404 03.04.2019 14:42

@ 404 В этом вся проблема, когда я возвращаю DELETE ... RETURNING * audit_id, это не то же самое, что поле id операции DELETE в audit.table_audit, вместо этого оно совпадает с идентификатором предыдущей операции, например. ВСТАВЛЯТЬ. С другой стороны, когда я делаю INSERT ... RETUNING *, audit_id совпадает с id операции вставки в таблицу аудита. P.S. id таблицы аудита — это целое число, автоматически увеличивающееся. Новая строка добавляется в эту таблицу каждый раз, когда происходит INSERT, UPDATE or DELETE

Sophio 03.04.2019 14:48

Какая версия постгреса?

404 03.04.2019 14:58

@404 PostgreSQL 10.6 на x86_64-pc-linux-gnu, скомпилированный gcc (GCC) 4.8.3 20140911 (Red Hat 4.8.3-9), 64-разрядная версия

Sophio 03.04.2019 15:02

Я надеялся сделать это для REST API (используя PostgREST) для конечной точки, которая имеет поля status и last_modified. Когда DELETE получен, я надеялся поместить «удалено» в status и NOW() в поля last_modified и показать это в возвращаемом значении, когда указан заголовок Prefer: return=representation.

user9645 31.12.2019 15:58
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
4
10
1 377
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

У меня похожая проблема. Похоже, PG сейчас просто не поддерживает модификацию OLD, но, возможно, эта возможность будет включена в список TODO.

В настоящее время вы можете изменить Только NEW для операторов INSERT и UPDATE.

Подробности смотрите в этой ветке почты: Поддерживает ли триггер «вместо удаления» модификацию OLD

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