postgresql - 使用旧的触发器动态获取列名
问题描述
我想写一个通用的触发函数(Postgres 过程)。有许多主表,如TableA、TableB等,以及它们对应的审计表TableA_Audit、TableB_Audit。结构如下。
TableA 和 TableA_Audit 具有列 aa integer、ab integer。
TableB 和 TableB_Audit 的列是整数。
同样,可以有许多主表及其审计表。
要求是任何主表都得到更新,然后它们的条目应插入各自的审计表中。
例如:- 如果 TableA 有这样的条目
---------------------
| **TableA** |
---------------------
|aa | ab |
|--------|----------|
| 5 | 10 |
---------------------
然后我写了一个更新,比如
更新 TableA 设置 aa= aa+15,
那么 TableA 的旧值应该插入到 TableA_Audit 表中,如下所示
TableA_audit 包含:-
---------------------
| **TableA_Audit** |
---------------------
|aa | ab |
|--------|----------|
| 5 | 10 |
---------------------
为了简化上述场景,我编写了一个名为 insert_in_audit 的通用函数。每当主表中有任何更新时,应调用函数 insert_in_audit。该功能应达到以下要求:-
- 使用主表在相应的 audit_table 中动态插入条目。如果表 B 中有更新,则应仅在 TableB_Audit 中插入条目。
到现在为止我能做到的。我得到了发生更新的主表的所有列的名称。例如:对于查询 - 更新 TableA 设置 aa=aa+15,我能够在 varchar 数组中获取 TableA 中的所有列名。
column_names varchar[ ] := '{"aa", "ab"}';
我的问题是如何获取 aa 和 ab 列的旧值。我试着这样做
foreach i in array column_names
loop
raise notice '%', old.i;
end loop;
但是上面给了我错误:-记录“旧”没有字段“i”。任何人都可以帮助我获得旧值。
解决方案
这是一个代码示例,您可以如何从OLD
PL/pgSQL 中动态提取值:
CREATE FUNCTION dynamic_col() RETURNS trigger
LANGUAGE plpgsql AS
$$DECLARE
v_col name;
v_val text;
BEGIN
FOREACH v_col IN ARRAY TG_ARGV
LOOP
EXECUTE format('SELECT (($1).%I)::text', v_col)
USING OLD
INTO v_val;
RAISE NOTICE 'OLD.% = %', v_col, v_val;
END LOOP;
RETURN OLD;
END;$$;
CREATE TABLE trigtest (
id integer,
val text
);
INSERT INTO trigtest VALUES
(1, 'one'), (2, 'two');
CREATE TRIGGER dynamic_col AFTER DELETE ON trigtest
FOR EACH ROW EXECUTE FUNCTION dynamic_col('id', 'val');
DELETE FROM trigtest WHERE id = 1;
NOTICE: OLD.id = 1
NOTICE: OLD.val = one
推荐阅读
- ocaml - 在 Ocaml 中调用嵌套对象中的方法的语法
- node.js - 什么是“npm run dev”和“npm run prod”
- java - 对于参数类型 int、Distance 和更多错误,运算符 <= 未定义
- python - 启动 tkinter 应用程序时,有没有办法将资产加载为空闲任务?
- sql - 将列中的嵌套 JSON 解析为 SQL Server 中的表
- c# - C# 奇怪的字符串行为
- swift - 如何为 SwiftUI 配置提供默认值但让用户覆盖它们?
- javascript - 计时器结束但显示 0:01
- c# - 在单独的 Web Api 上进行 JWT 验证
- css - 预处理 XSL 样式表 - 包括外部文档