PostgreSQL: создание триггера, который пытается выполнить работу с несуществующей таблицей
Когда мы начинаем переносить наше приложение из Oracle в PostgreSQL, мы столкнулись со следующей проблемой:
Многие из наших сценариев Oracle создают триггеры, которые работают с таблицами, специфичными для Oracle, которых нет в PostgreSQL. При запуске этих сценариев в базе данных PG они не будут выдавать ошибку. Только при срабатывании триггера выдается ошибка.
Пример кода:
-- Invalid query under PostgreSQL
select * from v$mystat;
-- Create a view with the invalid query does not work (as expected)
create or replace view Invalid_View as
select * from v$mystat;
-- Create a test table
create table aaa_test_table (test timestamp);
-- Create a trigger with the invalid query does(!) work (not as expected)
create or replace trigger Invalid_Trigger
before insert
on aaa_test_table
begin
select * from v$mystat;
end;
-- Insert fails if the trigger exists
insert into aaa_test_table (test) values(sysdate);
-- Select from the test table
select * from aaa_test_table
order by test desc;
Есть ли способ изменить это поведение, чтобы вместо этого выдавать ошибку при создании триггера?
С уважением, Хаммерфельс
Редактировать:
Мне стало известно, что мы на самом деле используем не базовый PostgreSQL, а EDB. Это, вероятно, объясняет, почему синтаксис для триггера создания кажется неправильным. Я прошу прощения за путаницу.
2 ответа
Это вызовет ошибку, если вы не настроили Postgres на откладывание проверки при создании функций.
Попробуйте выполнить это до создания триггера:
set check_function_bodies = on;
Создание триггера должно показать
ERROR: syntax error at or near "trigger"
LINE 1: create or replace trigger Invalid_Trigger
В Postgres триггеры основаны на функциях. Синтаксис EDB скрывает это, но на самом деле функция триггера создается автоматически.
Вы можете правильно создать функцию, которая ссылается на несуществующую таблицу, например:
create or replace function select_from_non_existing_table()
returns bigint language plpgsql as $$
begin
select count(*)
from non_existing_table;
end $$;
Если таблица не существует, ошибка возникает при выполнении функции:
select select_from_non_existing_table();
ERROR: relation "non_existing_table" does not exist
LINE 2: from non_existing_table
^
QUERY: select count(*)
from non_existing_table
CONTEXT: PL/pgSQL function select_from_non_existing_table() line 3 at SQL statement
Однако вы можете создать таблицу, а затем успешно выполнить функцию.
Это совершенно другая ситуация, чем при создании представления. create view ...
Команда выполняется немедленно, поэтому она не может быть успешно завершена.
В Postgres нет способа делать такие семантические проверки во время создания функции. См. Также PostgreSQL против Oracle: проверка PL/pgSQL во время компиляции