对于每个语句触发器示例

dif*_*ism 16 postgresql triggers plpgsql

我一直在查看postgresql触发器文档,但它似乎只显示行级触发器的示例,但我找不到语句级触发器的示例.

特别是,如何在单个语句中迭代更新/插入行并不是很清楚,因为它NEW是针对单个记录的.

Erw*_*ter 17

OLD并且NEW未在语句级触发器中定义.每个文件:

NEW

数据类型RECORD; 变量为行级触发器中的INSERT/ UPDATEoperations 保存新数据库行.此变量在语句级触发器DELETE操作中未分配.

OLD

数据类型RECORD; 在行级触发器中为UPDATE/ DELETEoperations 保存旧数据库行的变量.此变量在语句级触发器INSERT操作中未分配.

大胆强调我的.

示例语句级触发器

那些并不常见.一个有用的示例是在某些DML命令之后发送通知.
这是我使用的简化版本:

-- Generic trigger function, can be used for multiple triggers:
CREATE OR REPLACE FUNCTION trg_notify_after()
  RETURNS trigger AS
$func$
BEGIN
   PERFORM pg_notify(TG_TABLE_NAME, TG_OP);
   RETURN NULL;
END
$func$  LANGUAGE plpgsql;

-- Trigger
CREATE TRIGGER notify_after
AFTER INSERT OR UPDATE OR DELETE ON my_tbl
FOR EACH STATEMENT
EXECUTE PROCEDURE trg_notify_after();
Run Code Online (Sandbox Code Playgroud)

  • 我希望语句触发器对于多记录案例有一些*等效的"NEW"和"OLD",并且有一些方法来迭代这些. (5认同)
  • @user1760150:确实,这个老问题的游戏规则改变者。我更新了。 (3认同)
  • @diffeomorphism:不.这不是它的工作原理. (2认同)
  • @ErwinBrandstetter我认为这在较新的版本中已经发生了变化...我相信现在在语句级触发器内部可以访问NEW和OLD表 (2认同)

小智 10

好吧,这里有一些语句级触发器的示例。

桌子:

CREATE TABLE public.test (
    number integer NOT NULL,
    text   character varying(50)
);
Run Code Online (Sandbox Code Playgroud)

触发函数:
OLDNEW仍然 ,NULL
返回值也可以一直保留NULL

CREATE OR REPLACE FUNCTION public.tr_test_for_each_statement()
   RETURNS trigger
   LANGUAGE plpgsql
AS
$$
DECLARE
    x_rec record;
BEGIN
    raise notice '=operation: % =', TG_OP;
    IF (TG_OP = 'UPDATE' OR TG_OP = 'DELETE') THEN
        FOR x_rec IN SELECT * FROM old_table LOOP
            raise notice 'OLD: %', x_rec;
        END loop;
    END IF;
    IF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN
        FOR x_rec IN SELECT * FROM new_table LOOP
            raise notice 'NEW: %', x_rec;
        END loop;
    END IF;

    RETURN NULL;
END;
$$;
Run Code Online (Sandbox Code Playgroud)

设置语句级触发器
AFTER且仅支持一个事件。

CREATE TRIGGER tr_test_for_each_statement_insert
   AFTER INSERT ON public.test
   REFERENCING NEW TABLE AS new_table
   FOR EACH STATEMENT
   EXECUTE PROCEDURE public.tr_test_for_each_statement();

CREATE TRIGGER tr_test_for_each_statement_update
   AFTER UPDATE ON public.test
   REFERENCING NEW TABLE AS new_table OLD TABLE AS old_table
   FOR EACH STATEMENT
   EXECUTE PROCEDURE public.tr_test_for_each_statement();

CREATE TRIGGER tr_test_for_each_statement_delete
   AFTER DELETE ON public.test
   REFERENCING OLD TABLE AS old_table
   FOR EACH STATEMENT
   EXECUTE PROCEDURE public.tr_test_for_each_statement();
Run Code Online (Sandbox Code Playgroud)

例子:

INSERT INTO public.test(number, text) VALUES (1, 'a');
Run Code Online (Sandbox Code Playgroud)

=操作:插入=
新:(1,a)

INSERT INTO public.test(number, text) VALUES (2, 'b'),  (3, 'b');
Run Code Online (Sandbox Code Playgroud)

=操作:INSERT =
新:(2,b)
新:(3,b)

UPDATE public.test SET number = number + 1 WHERE text = 'a';
Run Code Online (Sandbox Code Playgroud)

=操作:更新=
旧的:(1,a)
新的:(2,a)

UPDATE public.test SET number = number + 10 WHERE text = 'b';
Run Code Online (Sandbox Code Playgroud)

=操作:更新 =
旧的:(2,b)
旧的:(3,b)
新的:(12,b)
新的:(13,b)

DELETE FROM public.test;
Run Code Online (Sandbox Code Playgroud)

=操作:删除 =
旧:(2,a)
旧:(12,b)
旧:(13,b)