从包含审计跟踪的表中获取原始内容和修改内容

问题描述 投票:1回答:2

我遇到了下面的表结构,我需要对它执行某种类型的查询。

  • ID
  • 名字
  • 地址
  • 电子邮件
  • audit_parent_id
  • audit_entry_type
  • audit_change_date

最后三个字段用于审计跟踪。有一个约定:所有原始条目的值为“audit_parent_id”的值为“0”,“audit_entry_type”的值为“master”。所有修改的条目都具有audit_parent_id的父id的值和“audit_entry_type”的值“modified”。

现在我想要做的是能够获得字段的原始值和修改后的值,并且我想用尽可能少的查询来实现。

有任何想法吗?谢谢。

sql postgresql audit-trail
2个回答
1
投票

假设一个简单的情况,当您想要获取id为50的记录的最新地址值更改时,此查询符合您的需求。

select
    p.id,
    p.adress as original_address,
    (select p1.adress from persons p1 where p1.audit_parent_id = p.id order by audit_change_date desc limit 1) as latest_address
from
    persons p -- Assuming it's the table name
where
    p.id = 50

但是这假设,即使address值在一次审计与另一次审计之间没有变化,它在该领域仍然是相同的。

这是另一个例子,显示所有有地址变化的人:

select
    p.id,
    p.adress as original_address,
    (select p1.adress from persons p1 where p1.audit_parent_id = p.id order by audit_change_date desc limit 1) as latest_address
from
    persons p -- Assuming it's the table name
where
    p.audit_parent_id = 0
    and
    p.adress not like (select p1.adress from persons p1 where p1.audit_parent_id = p.id order by audit_change_date desc limit 1)

0
投票

这可以通过使用WITH RECURSIVE的现代Postgres中的纯SQL来解决。

对于PostgreSQL 8.3,这个plpgsql函数可以完成这项工作,同时它也是现代PostgreSQL的一个不错的解决方案。你想要 ..

获取字段的原始值和修改值

该演示选择first_name作为提交:

CREATE OR REPLACE FUNCTION f_get_org_val(integer
                                       , OUT first_name_curr text
                                       , OUT first_name_org  text) AS
$func$
DECLARE
     _parent_id int;
BEGIN
   SELECT INTO first_name_curr, first_name_org, _parent_id
               first_name,      first_name,     audit_parent_id
   FROM   tbl
   WHERE  id = $1;

   WHILE _parent_id <> 0
   LOOP
     SELECT INTO first_name_org, _parent_id
                 first_name,     audit_parent_id
     FROM   tbl
     WHERE  id = _parent_id;
   END LOOP;
END
$func$  LANGUAGE plpgsql;

COMMENT ON FUNCTION f_get_org_val(int) IS 'Get current and original values for id.
 $1 .. id';

呼叫:

SELECT * FROM f_get_org_val(123);

这假设所有树都有一个带parent_id = 0的根节点。没有循环引用,或者你最终会得到一个无限循环。您可能希望添加计数器并在x次迭代后退出循环。

© www.soinside.com 2019 - 2024. All rights reserved.