0

我们正在使用“每个受监控表的 1 个审计表”设计;但是,在我们的例子中,emp(PARENT)表有一个子表emp_address也需要监控,所以我们有emp_auditand emp_addr_audit tables

postgres 审计 SQL:如何连接 PARENT 和 CHILD 表以进行报告。

/* Employee table */    
create table emp (
 emp_id integer primary key,
 empnum  integer,
 empname varchar(50),
);

/* Address table */    
create table emp_addr (
 addr_id integer primary key,
 emp_id integer, -- references table emp
 line1 varchar(30),
);

/* Audit table for emp table */    
create table emp_audit (
 operation   character(1),
 emp_id integer,
 empnum  integer,
 empname varchar(50),
 updatetime timestamp,
 txid bigint
);

/* Audit table for emp_addr table */    
create table emp_addr_audit (
 operation   character(1),
 addr_id integer,
 emp_id integer,
 line1 varchar(30),
 updatetime timestamp,
 txid bigint
);

我们使用 hibernate(java) 进行持久化,hibernate 只更新那些在更新操作中修改了列的表。鉴于此,我可能在 emp_addr_audit 表中有多个(比如 5)行,而 emp_audit 表中有 1 行。反之亦然。

每个事务(修改)报告需要 1 行。该报告将包含以下列

empname、line1、操作(插入/删除/更新)、更新时间

让我们考虑 2 个场景来了解需要什么:

  1. 在初始事务中,仅emp创建属性。然后在一个单独的事务中,创建相应的行emp_addr。所以,现在,我们在表格中有 1 行,在emp_audit表格中有 1 行emp_addr_audit。该报告将有 2 行(每笔交易一行)。
  2. emp和属性都是emp_addr在单个事务中创建的。这将确保 1 行 inemp_audit和 1 行 in emp_addr_audit。现在,报告将只有 1 行(因为两个表行都是在单个事务中创建的)。

场景
事务 #1:我在 emp 和 emp_addr 中都插入了一行。这导致 emp_audit 和 emp_addr_audit.(INSERT)
Transaction #2 中各有一行:我更新了上面的 emp' 属性。这会在 emp_audit 中产生一个 UPDATE 行。
事务 #3:我更新了上述 emp_addr 的属性。这会在 emp_addr_audit 中产生一个 UPDATE 行。

我尝试了以下 SQL #1,它返回了 3 行(如预期的那样);

SQL #1

SELECT emp.*, addr.*
 FROM  emp_audit emp 
 FULL OUTER JOIN emp_addr_audit addr USING(emp_id, txid);

但是,当我where在 SQL 中添加一个子句时,它只返回 2 行。丢失的行是事务 #3 的结果,其中只有 emp_addr 表行已更新,而 emp 表行未受影响。
SQL #2

SELECT emp.*, addr.*
 FROM  emp_audit emp 
        FULL OUTER JOIN emp_addr_audit addr USING(emp_id, txid);
WHERE  emp.empnum = 20;

什么 SQL仍然能够为 3 个事务获取 3 行,以便我仍然可以根据 empnum 过滤掉?

4

1 回答 1

1

FULL JOIN 将从两个表中创建一个表,并用 NULL 值填充空(不匹配)行。当您仅选择 emp.empnum = 20 的行时,它当然不会返回 emp.empnum 中具有 NULL 的最后一行。

也许你只能在 emp_id 上加入,然后做一些 GROUP BY txid。但这不会那么容易。您可能必须始终对两个表进行更新。或者使用一些更高级的逻辑(例如:选择一个 emp_id 的所有事务,其中一侧为空,直到下一个完整行,并用最后一个完整行填充缺失的部分)。

于 2010-11-30T13:03:40.903 回答