postgresql rails + psql与结构转储一起使用PROCEDURE而不是FUNCTION

30byixjq  于 2022-11-23  发布在  PostgreSQL
关注(0)|答案(2)|浏览(121)

每次我将structure.sql转储到rails应用程序上时,我得到的是PROCEDURE而不是FUNCTION。FUNCTION是我们的默认设置,我必须提交文件的各个部分,这很烦人,有时我会漏掉行,这更糟糕,因为它是一个相当大的structure.sql文件。
git差异示例:

-CREATE TRIGGER cache_comments_count AFTER INSERT OR DELETE OR UPDATE ON public.comments FOR EACH ROW EXECUTE PROCEDURE public.update_comments_counter();
+CREATE TRIGGER cache_comments_count AFTER INSERT OR DELETE OR UPDATE ON public.comments FOR EACH ROW EXECUTE FUNCTION public.update_comments_counter();

我肯定在某个地方有一个postgresql设置,但是我找不到。

e4yzc0pl

e4yzc0pl1#

无论你使用函数还是过程,你得到的结果都是一样的。

CREATE [ CONSTRAINT ] TRIGGER name... 
    EXECUTE { FUNCTION | PROCEDURE } function_name ( arguments )

这意味着您可以使用术语FUNCTION或PROCEDURE,但无论使用哪种方式,function_name 总是被调用。请参见demo。对于演示,我为insertupdate提供了单独的触发器。使用execute procedure插入,使用execute function更新。这在Postgres中无法更改,它必须是Rails设置。**注意:**在v11之前,Postgres只允许 * 执行过程 *,即使您必须创建一个被调用的触发器function

n9vozmp4

n9vozmp42#

在Postgres 11和12之间,函数pg_get_triggerdef()在Postgres引入了真实的的过程时发生了变化。从Postgres 12开始,它总是返回一个使用EXECUTE FUNCTION的语法,因为实际上它一个在触发器触发时调用的函数,而不是一个过程。
所以这段代码:

create table t1 (id int);

create function trg_func()
returns trigger
as
$$
begin
return new;
end;
$$
language plpgsql;

create trigger test_trigger
  before insert or update 
  on t1
  for each row
  execute procedure trg_func();

select pg_get_triggerdef(oid)
from pg_trigger 
where tgname = 'test_trigger';

在Postgres 11和更早版本中返回以下内容:

CREATE TRIGGER test_trigger BEFORE INSERT OR UPDATE ON public.t1 FOR EACH ROW EXECUTE PROCEDURE trg_func()

以及Postgres 12和更高版本中的以下内容:

CREATE TRIGGER test_trigger BEFORE INSERT OR UPDATE ON public.t1 FOR EACH ROW EXECUTE FUNCTION trg_func()

我猜Rails使用pg_get_triggerdef()来获取触发源。所以你无能为力。如果你想得到一致的结果,你应该在任何地方使用相同的Postgres版本。

相关问题