Почему возникает ошибка "отношение «new» не existe" при использовании триггера AFTER INSERT FOR EACH ROW?

Добрый день! 

Я разрабатываю триггерную функцию и столкнулся с проблемой. Вот код, который я использую для создания функции: 
```sql
create function trigger_test_func() returns trigger
as
$$
declare
v text;
begin
select txt into v from new;
insert into test_after(val) values(v);
end;
$$
language plpgsql;
```

После этого я создал триггер следующего вида: 
```sql
create trigger trigger_test after insert on test
for each row
execute function trigger_test_func();
```

Теперь я пытаюсь вставить данные в таблицу `test` с помощью следующей команды: 
```sql
insert into test(txt) values('mytext');
```

Однако я получаю ошибку: 
*ERROR:  отношение "new" не существует.*

При этом в документации указано, что для строковых триггеров типа INSERT отношение NEW доступно. Можете объяснить, в чем может быть проблема?
  • 13 марта 2025 г. 8:54
Ответы на вопрос 2
Ошибка "отношение «new» не существует" возникает из-за того, что вы пытаетесь использовать `new` как строку в SQL-запросе. В PL/pgSQL `new` это специальный псевдозапись, которая содержит значения новых вставленных строк, и ее неправильно использовать в контексте SQL-запроса.

Вместо того, чтобы писать:

```sql
select txt into v from new;
```

вам нужно получить значение поля `txt` из объекта `NEW` напрямую, так как `NEW` не является именем таблицы, а является специальным объектом, представляющим новую строку. Вот как исправить вашу функцию:

```sql
create function trigger_test_func() returns trigger
as
$$
declare
v text;
begin
v := new.txt;  -- Получаем значение поля txt из NEW
insert into test_after(val) values(v);
return new;  -- Возвращаем NEW, чтобы триггер работал корректно
end;
$$
language plpgsql;
```

Обратите внимание на следующие изменения:

1. Вместо `select txt into v from new;`, используется `v := new.txt;`, что позволяет извлечь значение прямо из объекта `NEW`.
2. Добавлен `return new;` в конце функции, что является необходимым для триггеров, чтобы указать, что новая строка (или измененная строка в случае триггеров на UPDATE) будет использована в дальнейшем. Это также является обязательным для корректной работы триггера.

Теперь, когда вы вставите данные в таблицу `test`, ваш триггер должен работать без ошибок.
insert into test_after(val) values(new.txt);
Похожие вопросы