[英]FOR EACH STATEMENT trigger example
我一直在查看postgresql triggers 的文檔,但它似乎只顯示了行級觸發器的示例,但我找不到語句級觸發器的示例。
特別是,還不清楚如何在單個語句中迭代更新/插入的行,因為NEW
是針對單個記錄的。
OLD
和NEW
為 null 或未在語句級觸發器中定義。根據文檔:
NEW
數據類型
RECORD
; 為行級觸發器中的INSERT
/UPDATE
操作保存新數據庫行的變量。 此變量在語句級觸發器和DELETE
操作中為空。
OLD
數據類型記錄; 保存舊數據庫行的變量,用於行級觸發器中的
UPDATE
/DELETE
操作。 此變量在語句級觸發器和INSERT
操作中為空。
大膽強調我的。
直到 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)
);
觸發功能:
OLD
和NEW
仍然為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.