簡體   English   中英

FOR EACH STATEMENT 觸發器示例

[英]FOR EACH STATEMENT trigger example

我一直在查看postgresql triggers 的文檔,但它似乎只顯示了行級觸發器的示例,但我找不到語句級觸發器的示例。

特別是,還不清楚如何在單個語句中迭代更新/插入的行,因為NEW是針對單個記錄的。

OLDNEW為 null 或未在語句級觸發器中定義。根據文檔:

NEW

數據類型RECORD 為行級觸發器中的INSERT / UPDATE操作保存新數據庫行的變量。 此變量在語句級觸發器DELETE操作中為空。

OLD

數據類型記錄; 保存舊數據庫行的變量,用於行級觸發器中的UPDATE / DELETE操作。 此變量在語句級觸發器INSERT操作中為空。

大膽強調我的。

直到 Postgres 10,這讀起來略有不同,但效果大致相同:

...此變量在語句級觸發器中未分配 ...

雖然這些記錄變量對於語句級觸發器仍然沒有用處,但一個新功能非常重要:

Postgres 10+ 中的轉換表

Postgres 10 引入了轉換表。 這些允許訪問整個受影響的行集。 手冊:

AFTER觸發器還可以使用轉換表來檢查由觸發語句更改的整個行集。 CREATE TRIGGER命令將名稱分配給一個或兩個轉換表,然后該函數可以引用這些名稱,就好像它們是只讀臨時表一樣。 示例 43.7顯示了一個示例。

按照手冊的鏈接獲取代碼示例。

沒有轉換表的語句級觸發器示例

在轉換表出現之前,這些甚至更不常見。 一個有用的示例是在某些 DML 命令之后發送通知
這是我使用的基本版本:

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

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

對於 Postgres 11 或更高版本,請使用等效的、不那么容易混淆的語法:

...
EXECUTE FUNCTION trg_notify_after();

看:

好吧,這里有一些語句級觸發器的示例。

桌子:

CREATE TABLE public.test (
    number integer NOT NULL,
    text   character varying(50)
);

觸發功能:
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;
$$;

設置語句級觸發器
僅支持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();

例子:

INSERT INTO public.test(number, text) VALUES (1, 'a');

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

INSERT INTO public.test(number, text) VALUES (2, 'b'),  (3, 'b');

=操作:插入 =
新:(2,b)
新:(3,b)

UPDATE public.test SET number = number + 1 WHERE text = 'a';

=操作:更新=
舊:(1,一)
新:(2,a)

UPDATE public.test SET number = number + 10 WHERE text = 'b';

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

DELETE FROM public.test;

=操作:刪除 =
舊:(2,a)
舊:(12,b)
舊:(13,b)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM