用于加入父子审计表的Postgres SQL

时间:2010-10-01 15:57:56

标签: sql postgresql parent-child audit full-outer-join

我们正在使用"1 audit table for each monitored Table"设计;但是,在我们的案例中,emp(PARENT)表中有一个子表emp_address,需要对其进行监控,因此我们有emp_auditemp_addr_audit tables

postgres audit 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,operation(insert / delete / update),updatetime

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

  1. 在初始事务中,仅创建emp个属性。然后在单独的事务中,创建emp_addr中的相应行。所以,现在,我们在emp_audit表中有1行,在emp_addr_audit表中有1行。该报告将有2行(每个事务各一个)。
  2. empemp_addr属性都是在单个事务中创建的。这将确保emp_audit中有1行,emp_addr_audit中有1行。现在,报告将只有1行(因为两个表行都是在单个事务中创建的)。
  3. 情景
    事务#1:我在emp和emp_addr中插入一行。这会在emp_audit和emp_addr_audit中产生一行。(INSERT)
    事务#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);
    

    但是,当我向SQL添加where子句时,它只返回2行。丢失的行是Transaction#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过滤掉?

1 个答案:

答案 0 :(得分:1)

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

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