我想創建一個已洗掉的日志并從 OLD 行列插入資料。問題是每個表的列都不相同,有些表只有 ,transaction_date而其他表只有created_at。所以我想檢查是否transaction_date只使用它,否則使用created_at列。我嘗試使用coalesce函式但仍然回傳:
錯誤:記錄“old”沒有欄位“transaction_date”背景關系:SQL陳述句“INSERT INTO“public”.“delete_logs”(“table”,“date”)VALUES(TG_TABLE_NAME,coalesce(OLD.transaction_date,coalesce(OLD.created_at) , now())))" PL/pgSQL 函式 delete_table() 第 2 行在 SQL 陳述句
這是我的功能:
CREATE OR REPLACE FUNCTION delete_table() RETURNS trigger AS
$$BEGIN
INSERT INTO "public"."deleted_logs" ("table", "created_at") VALUES (TG_TABLE_NAME, coalesce(OLD.transaction_date, coalesce(OLD.created_at, now())));
RETURN OLD;
END;$$ LANGUAGE plpgsql;
CREATE TRIGGER "testDelete" AFTER DELETE ON "exampletable" FOR EACH ROW EXECUTE PROCEDURE "delete_table"();
其實我想為每個表創建一個函式,但我認為將來更新該函式會很困難,所以我需要為所有表創建一個函式。
uj5u.com熱心網友回復:
如果您只有兩個替代列transaction_dateand created_at,那么您可以嘗試使用例外處理來管理 ERROR :
CREATE OR REPLACE FUNCTION delete_table() RETURNS trigger AS
$$BEGIN
INSERT INTO "public"."deleted_logs" ("table", "created_at") VALUES (TG_TABLE_NAME, OLD.transaction_date);
RETURN OLD;
EXCEPTION WHEN OTHERS THEN
INSERT INTO "public"."deleted_logs" ("table", "created_at") VALUES (TG_TABLE_NAME, OLD.created_at);
RETURN OLD ;
END;$$ LANGUAGE plpgsql;
uj5u.com熱心網友回復:
所以我想檢查是否
transaction_date只使用它,否則使用created_at列。
您可以通過將行轉換為 json 來避免您看到的例外:
CREATE OR REPLACE FUNCTION log_ts_after_delete()
RETURNS trigger
LANGUAGE plpgsql AS
$func$
BEGIN
INSERT INTO public.deleted_logs
(table_name , created_at) -- "table" is a reserved word
VALUES (TG_TABLE_NAME, COALESCE(to_json(OLD)->>'transaction_date', to_json(OLD)->>'created_at')::timestamptz);
RETURN NULL; -- not used in AFTER trugger
END
$func$;
我的回答假設transaction_date是定義的NOT NULL。否則,運算式默認為created_at。可能不是你想要的。
JSON 不像 SQL 那樣嚴格。對不存在的 JSON 鍵的參考會導致 NULL 而不是對不存在的表列的參考的例外。所以COALESCE才有效。
有關的:
- 如何使用動態SQL設定復合變數欄位的值
如果行很寬,那么只轉換為 JSON 一次并將其保存到變數中,或者在子查詢或 CTE 中執行可能會更便宜。
有關的:
- 快速從 Python 陣列轉換為 PostgreSQL?
如果表格未曾在考慮切換欄,傳遞一個引數在觸發定義是多少便宜。您發現(在觸發器創建時)一次:
SELECT attname
FROM pg_attribute
WHERE attrelid = 'public.exampletable'::regclass
AND attname IN ('transaction_date', 'created_at')
AND NOT attisdropped
ORDER BY attname DESC
如果表中存在這樣的列,則回傳“transaction_date”,否則回傳“created_at”,否則回傳 NULL(無行)。有關的:
- PostgreSQL 僅在列存在時重命名列
為每種型別的觸發器設定單獨的觸發器功能仍然是最便宜的。只是兩個功能而不是一個。如果觸發經常解雇我會做那。
如果可以,請避免例外處理。手冊:
提示
包含
EXCEPTION子句的塊比沒有子句的塊進入和退出的成本要高得多。因此,不要在EXCEPTION沒有需要的情況下使用。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/361554.html
標籤:sql PostgreSQL的 触发器 sql-删除
上一篇:滑動擴展影片旁邊的專案
