用于联接父子审核表的Postgres SQL
我们使用的是;然而,在我们的例子中,用于联接父子审核表的Postgres SQL,sql,postgresql,reporting,parent-child,audit,Sql,Postgresql,Reporting,Parent Child,Audit,我们使用的是;然而,在我们的例子中,emp(父)table有一个子表emp\u address,它也需要监控,因此我们有emp\u audit和emp\u address\u audit tables postgres audit SQL:如何连接父表和子表以进行报告 /* Employee table */ create table emp ( emp_id integer primary key, empnum integer, empname varchar(50), l
emp(父)
table有一个子表emp\u address
,它也需要监控,因此我们有emp\u audit
和emp\u address\u audit tables
postgres audit SQL:如何连接父表和子表以进行报告
/* Employee table */
create table emp (
emp_id integer primary key,
empnum integer,
empname varchar(50),
loginid varchar(20),
updatetime timestamp
);
/* Address table */
create table emp_addr (
addr_id integer primary key,
emp_id integer, -- references table emp
line1 varchar(30),
line2 varchar(30),
loginid varchar(20),
updatetime timestamp
);
/* Audit table for emp table */
create table emp_audit (
operation character(1),
emp_id integer,
empnum integer,
empname varchar(50),
loginid varchar(20),
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),
line2 varchar(30),
loginid varchar(20),
updatetime timestamp,
txid bigint
);
我们使用hibernate(java)进行持久化,hibernate只更新那些列在更新操作中被修改的表。鉴于此,对于1个emp_审计表,我可能在emp_addr_审计表中有多个(比如5个)记录
每个事务(修改)报告需要1行。
报告将包含以下列
empnum、empname、第1行、第2行、操作(插入/删除/更新)、loginid、updatetime
让我们考虑2种情况来理解需要什么:
emp
属性。然后在单独的事务中,创建emp_addr
中的对应行。现在,我们在emp\u audit
表中有一行,在emp\u addr\u audit
表中有一行。报告将有两行(每个事务一行)emp
和emp\u addr
属性都是在单个事务中创建的。这将确保在emp\u audit
中有一行,在emp\u addr\u audit
中有一行。现在,报告将只有一行(因为两个表行都是在一个事务中创建的)场景:
事务#1:我在emp和emp#u addr中插入一行。这将在emp_audit和emp_addr_audit中分别生成一行。(插入)
事务#2:我更新上面的emp属性。这将导致emp_audit中的更新行。
事务#3:我更新上述emp#u addr的属性。这将导致emp_addr_audit中的更新行。
我尝试了下面的SQL#1,它按预期返回了3行 SQL#1 但是,当我向SQL添加where子句时,它只返回2行。缺少的行是事务#3的结果,其中仅更新了emp#U addr表格行,未触及emp表格行。
SQL#2 什么样的SQL仍然能够为3个事务获取3行,这样我仍然可以基于empnum进行筛选
谢谢,首先在审核表中添加一个附加列
txid bigint
,然后修改执行审核的存储过程,以调用txid\u current()
,将当前事务id与审核记录一起存储
CREATE OR REPLACE FUNCTION process_emp_audit() RETURNS TRIGGER AS $emp_audit$
BEGIN
--
-- Create a row in emp_audit to reflect the operation performed on emp,
-- make use of the special variable TG_OP to work out the operation.
--
IF (TG_OP = 'DELETE') THEN
INSERT INTO emp_audit SELECT 'D', now(), user, txid_current(), OLD.*;
RETURN OLD;
ELSIF (TG_OP = 'UPDATE') THEN
INSERT INTO emp_audit SELECT 'U', now(), user, txid_current(), NEW.*;
RETURN NEW;
ELSIF (TG_OP = 'INSERT') THEN
INSERT INTO emp_audit SELECT 'I', now(), user, txid_current(), NEW.*;
RETURN NEW;
END IF;
RETURN NULL; -- result is ignored since this is an AFTER trigger
END;
$emp_audit$ LANGUAGE plpgsql;
然后,当您需要报告审计记录时,使用emp_id和txid在两个表之间进行外部联接,以便您可以在一行上显示同一事务中发生的两个独立插入
SELECT emp_audit.*, emp_addr_audit.*
FROM emp_audit
FULL OUTER JOIN ON emp_audit.emp_id = emp_addr_audit.emp_id
AND emp_audit.txid = emp_addr_audit.txid;
CREATE OR REPLACE FUNCTION process_emp_audit() RETURNS TRIGGER AS $emp_audit$
BEGIN
--
-- Create a row in emp_audit to reflect the operation performed on emp,
-- make use of the special variable TG_OP to work out the operation.
--
IF (TG_OP = 'DELETE') THEN
INSERT INTO emp_audit SELECT 'D', now(), user, txid_current(), OLD.*;
RETURN OLD;
ELSIF (TG_OP = 'UPDATE') THEN
INSERT INTO emp_audit SELECT 'U', now(), user, txid_current(), NEW.*;
RETURN NEW;
ELSIF (TG_OP = 'INSERT') THEN
INSERT INTO emp_audit SELECT 'I', now(), user, txid_current(), NEW.*;
RETURN NEW;
END IF;
RETURN NULL; -- result is ignored since this is an AFTER trigger
END;
$emp_audit$ LANGUAGE plpgsql;
SELECT emp_audit.*, emp_addr_audit.*
FROM emp_audit
FULL OUTER JOIN ON emp_audit.emp_id = emp_addr_audit.emp_id
AND emp_audit.txid = emp_addr_audit.txid;