У меня есть триггерная функция в 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();
Добро пожаловать в StackOverflow! Не могли бы вы улучшить свой вопрос, поделившись выводом, который вы видите, и тем, что вы ожидаете вместо этого?
Когда я запускаю ``` DELETE FROM table WHERE id = 12 RETURNING * ```, я возвращаю строку, которая возвращается функцией триггера
Мы не можем видеть, как поле id, которое возвращается в audit_pk, получает свое значение, так как это поле не указано в операторе вставки. Проблема должна заключаться в том, откуда берется это значение и почему оно устанавливается на неожиданное значение? Я не вижу проблемы в самом триггере, он должен быть в фактических данных в этой таблице аудита. Принимая во внимание, что это даже не таблица, в которую записываются операторы вставки или обновления, так как же это значение устанавливается в таблице affiliate_audit? Только у вас есть доступ к информации, чтобы понять это.
@404 Идентификатор автоматически генерируется при каждой вставке в таблицу аудита. Я думаю, что эта часть в порядке, поскольку она работает точно так, как ожидалось для INSERT и UPDATE. При выполнении DELETE OLD содержит всю удаляемую строку, включая audit_id предыдущей операции. Что я пытаюсь сделать, так это обновить этот старый audit_id новым, но это не работает, я не знаю, почему
На данный момент игнорируйте бит OLD. Когда вы выполняете DELETE ... RETURNING *, возвращается ли audit_id то же самое, что и поле id строки аудита удаления в audit.table_audit? Если да, то триггер правильный. Если вы считаете, что audit_id должно быть новым значением, вы должны убедиться, что id записывается с новым значением при вставке записи об удалении.
@ 404 В этом вся проблема, когда я возвращаю DELETE ... RETURNING * audit_id, это не то же самое, что поле id операции DELETE в audit.table_audit, вместо этого оно совпадает с идентификатором предыдущей операции, например. ВСТАВЛЯТЬ. С другой стороны, когда я делаю INSERT ... RETUNING *, audit_id совпадает с id операции вставки в таблицу аудита. P.S. id таблицы аудита — это целое число, автоматически увеличивающееся. Новая строка добавляется в эту таблицу каждый раз, когда происходит INSERT, UPDATE or DELETE
Какая версия постгреса?
@404 PostgreSQL 10.6 на x86_64-pc-linux-gnu, скомпилированный gcc (GCC) 4.8.3 20140911 (Red Hat 4.8.3-9), 64-разрядная версия
Я надеялся сделать это для REST API (используя PostgREST) для конечной точки, которая имеет поля status и last_modified. Когда DELETE получен, я надеялся поместить «удалено» в status и NOW() в поля last_modified и показать это в возвращаемом значении, когда указан заголовок Prefer: return=representation.


У меня похожая проблема. Похоже, PG сейчас просто не поддерживает модификацию OLD, но, возможно, эта возможность будет включена в список TODO.
В настоящее время вы можете изменить Только NEW для операторов INSERT и UPDATE.
Подробности смотрите в этой ветке почты: Поддерживает ли триггер «вместо удаления» модификацию OLD
Я не совсем понимаю. Как вы «возвращаете» что-то из
DELETE?