【问题标题】:Is there any method to create trigger and trigger function in a single query in PostgreSQL是否有任何方法可以在 PostgreSQL 的单个查询中创建触发器和触发器函数
【发布时间】:2017-06-22 03:27:01
【问题描述】:

我对 PostgreSQL 有疑问。我想在单个查询中创建触发器和触发器函数,这样我就可以更快地进行触发器。 这是我的触发函数:

    CREATE FUNCTION public.tda_a1()
      RETURNS trigger
      LANGUAGE 'plpgsql'
      COST 100.0
      VOLATILE NOT LEAKPROOF 
      COST 100.0
    AS $BODY$
    BEGIN
      DELETE FROM ref_dati2 where kd_propinsi = OLD.kd_propinsi;
      RETURN OLD;
    END;
    $BODY$;

这就是触发器:

    CREATE TRIGGER tda_a1
      BEFORE DELETE
      ON public.ref_propinsi
      FOR EACH ROW
      EXECUTE PROCEDURE public.tda_a1();

我尝试将它们加入到一个查询中,但失败了。也许有人可以帮助我。

【问题讨论】:

  • 不,这是不可能的。为什么你认为这会“更快”?目前运行这两个语句需要多长时间?你需要多快?
  • @a_horse_with_no_name 如果只有 2 或 3 个触发器,则不需要很长时间,但我有 192 个触发器。我想像在 Oracle 中那样在单个查询中执行它们
  • @a_horse_with_no_name 当然,我可以一个一个地执行它们,但是这需要很长时间,并且每次执行都必须小心。实际上我可以在单个查询中执行多个触发器(绑定到表上的特定操作),但对触发器函数不起作用
  • 我仍然不明白您要解决的实际问题是什么。如果没有函数,就无法在 Postgres 中定义触发器。该函数确实可以重复使用,因此每个触发器不需要两个语句。你说你“需要小心每次执行”。如果您缺少有关如何管理架构定义和迁移的正确概念,这听起来对我来说很重要。查看 [Liquibase](liquibase.org) 或 Flyway 之类的工具,它们将帮助您管理和运行架构迁移

标签: sql postgresql plpgsql ddl database-trigger


【解决方案1】:

谢谢大家的回答,但我终于找到了答案, 我刚刚从我的查询中删除了这个脚本。

  NOT LEAKPROOF 
  COST 100.0

这是 pgadmin 的默认设置,当我删除它时,我可以在单个查询中运行触发函数,只要我想要的次数就可以

【讨论】:

  • 你仍然不能在同一个语句中创建一个触发器一个触发器函数。
【解决方案2】:

更新困惑:

我有 192 个触发器。我想像在 Oracle 中那样在单个查询中执行它们

以下是对被误解的原帖的回答。它回答了一次包装创建多个触发器的性能。虽然 OP 的意思可能是在触发器本身中定义 PGSQL,而不是作为单独的触发器函数。

准备:

t=# create schema s1;
CREATE SCHEMA
t=# set search_path to s1;
SET
t=# create table t1 (i int);
CREATE TABLE
t=# \timing on
Timing is on.

在一个DO 语句中运行:

t=# do
$$
begin
for i in 1..99 loop
execute format('create function %I() returns trigger as $f$begin return new;end;$f$ language plpgsql','f'||i);
execute format('create trigger %I before delete on t1 for each row execute procedure %I()','t'||i,'f'||i);
end loop;
end;
$$
;
DO
Time: 54.545 ms

花费时间:Time: 54.545 ms

现在使用相同的DO 来生成分隔语句的脚本:

t=# do
$$
begin
for i in 1..99 loop
raise info '%', format('create function %I() returns trigger as $f$begin return new;end;$f$ language plpgsql;','f'||i);
raise info '%', format('create trigger %I before delete on t1 for each row execute procedure %I();','t'||i,'f'||i);
end loop;
end;
$$
;

将其保存到文件中:

t=# \! vi s1
:%s/INFO:  //g
-- adding select clock_timestamp(); and begin; end; to avoid overhead on autocommit each statement
t=# \! wc -l s1
202 s1

202 行。 198 条语句加上 4 条添加。扫一扫:

t=# drop schema s1 cascade;
DROP SCHEMA
t=# create schema s1;
CREATE SCHEMA
t=# set search_path to s1;
SET
t=# create table t1 (i int);
CREATE TABLE
t=# \i s1
        clock_timestamp
-------------------------------
 2017-06-22 07:49:05.78448+00
(1 row)

Time: 0.202 ms
CREATE FUNCTION
Time: 1.407 ms
CREATE TRIGGER
....
....
CREATE TRIGGER
Time: 1.033 ms
        clock_timestamp
-------------------------------
 2017-06-22 07:49:05.823402+00
(1 row)

时间差异:

t=# select '2017-06-22 07:49:05.823402+00'::timestamptz - '2017-06-22 07:49:05.78448+00'::timestamptz;
    ?column?
-----------------
 00:00:00.038922
(1 row)

时间38.922ms

我做了几次测试,动态执行有时更快,有时不是。您可以实现的主要性能提升是在一个事务中运行多行脚本。但是再次 - 我们在这里比较毫秒......

另外 - 也许你的意思是通过一个陈述?.. 如果是这样,请用你在 Oracle 中如何做到这一点的代码示例更新原始帖子

【讨论】:

  • 在 Oracle 中它是一个单个 create trigger 语句。
  • @a_horse_with_no_name 我刚刚意识到单个语句意味着在触发器定义中定义 pgsql 块!一个语句中没有多个触发器。 G! :) >“我有 192 个触发器。我想像在 Oracle 中所做的那样在单个查询中执行它们”完全让我感到困惑。我什至重读了 CREATE TRIGGER 参考,寻找魔法。一直在想“为什么首先要为多个 trigegrs 使用一个语句!”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-03
  • 1970-01-01
  • 1970-01-01
  • 2015-03-24
  • 2021-08-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多