PostgreSQL:创建一个触发器尝试在不存在的表上工作

时间:2018-09-18 15:17:32

标签: postgresql triggers edb

当我们开始将应用程序从使用Oracle迁移到PostgreSQL时,我们遇到了以下问题:

我们的许多Oracle脚本都会创建可在PostgreSQL中不存在的Oracle特定表上使用的触发器。在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 个答案:

答案 0 :(得分:0)

除非您有configured Postgres在创建函数时推迟验证,否则它将触发错误。

在创建触发器之前尝试发出此消息:

set check_function_bodies = on;

创建触发器应显示

ERROR:  syntax error at or near "trigger"
LINE 1: create or replace trigger Invalid_Trigger

答案 1 :(得分:0)

在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 vs Oracle: “compile-time” checking of PL/pgSQL