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 во время компиляции

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