我们正在使用"1 audit table for each monitored Table"设计;但是,在我们的案例中,emp(PARENT)
表中有一个子表emp_address
,需要对其进行监控,因此我们有emp_audit
和emp_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个场景来理解需要什么:
emp
个属性。然后在单独的事务中,创建emp_addr
中的相应行。所以,现在,我们在emp_audit
表中有1行,在emp_addr_audit
表中有1行。该报告将有2行(每个事务各一个)。emp
和emp_addr
属性都是在单个事务中创建的。这将确保emp_audit
中有1行,emp_addr_audit
中有1行。现在,报告将只有1行(因为两个表行都是在单个事务中创建的)。 情景:
事务#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过滤掉?
答案 0 :(得分:1)
FULL JOIN将从两个表创建一个表,并用NULL值填充空(不匹配)行。当您仅选择emp.empnum = 20的行时,它当然不会返回emp.empnum中具有NULL的最后一行。
也许你只能在emp_id上加入,然后做一些GROUP BY txid。但这不会那么容易。您可能必须始终对两个表进行更新。或者使用一些更高级的逻辑(类似于:选择一个emp_id的所有事务,其中一边为空,直到下一个完整行,并用最后一个完整行填充缺失的部分)。