用于连接父子审计表的 Postgres SQL
我们正在使用 "1 审核每个受监控表的表";但是,在我们的示例中,emp(PARENT)
表有一个子表 emp_address
,也需要对其进行监控,因此我们有 emp_audit
和 emp_address_audit 表
。
postgres 审计 SQL:如何连接 PARENT 和 CHILD 表以进行报告。
/* 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_audit 表的 emp_addr_audit 表中有多个(例如 5 条)记录。
每笔交易(修改)报告需要 1 行。 该报告将包含以下列
empnum、empname、line1、line2、操作(插入/删除/更新)、loginid、updatetime
让我们考虑 2 个场景来了解需要什么:
- 在初始事务中只有
emp
属性被创建。然后在单独的事务中,创建emp_addr
中的相应行。因此,现在,emp_audit
表中有 1 行,emp_addr_audit
表中有 1 行。该报告将有 2 行(每笔交易各一行)。 emp
和emp_addr
属性都是在单个事务中创建的。这将确保emp_audit
中有 1 行,emp_addr_audit
中有 1 行。现在,报告将只有 1 行(因为两个表行都是在单个事务中创建的)。
什么样的 SQL 可以满足上述两种情况?
更新
场景:
事务#1:我在 emp 和 emp_addr 中插入一行。这会在 emp_audit 和 emp_addr_audit 中各生成一行。(插入)
事务#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 addr USING(emp_id, txid);
但是,当我向 SQL 添加 where 子句时,它仅返回 2 行。丢失的行是事务 #3 的结果,其中仅 emp_addr 表行被更新,而 emp 表行未受影响。
SQL #2
SELECT emp.*, addr.*
FROM emp_audit emp
FULL OUTER JOIN emp_addr addr USING(emp_id, txid);
WHERE emp.empnum = 20;
什么 SQL仍然能够为我的 3 个事务获取 3 行,以便我仍然可以根据 empnum 进行过滤?
谢谢你,
We're using a "1 audit table for each monitored Table"; However, in our case emp(PARENT)
table has a child table emp_address
which also needs to be monitored, so we have emp_audit
and emp_address_audit tables
.
postgres audit SQL : how to join PARENT and CHILD tables for reporting purposes.
/* 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
);
We're using hibernate(java) for persistence and hibernate updates only those tables whose columns were modified in the update operation. Given this, I might have multiple(say, 5) records in the emp_addr_audit table for 1 emp_audit table.
The report needs 1 row for each transaction(modification).
The report will have the following columns
empnum, empname, line1, line2, operation(insert/delete/update), loginid, updatetime
Let's consider 2 scenarios to understand what's needed:
- In the initial transaction only
emp
attributes are created. Then in a separate transaction, the corresponding row inemp_addr
is created. So, now, we have 1 row inemp_audit
table and 1 row inemp_addr_audit
table. The report will have 2 rows (one each for each transaction). - Both
emp
andemp_addr
attributes are created in a single transaction. This will ensure that there is 1 row inemp_audit
and 1 row inemp_addr_audit
. Now, the report will have ONLY 1 row (since both table rows were created in a single transaction).
What SQL will satisfy both the above scenarios?
UPDATE
Scenario :
Transaction #1 : I insert a row into both emp and emp_addr. This results in a row each in emp_audit and emp_addr_audit.(INSERT)
Transaction #2 : I update the above emp' attribute. This results in a UPDATE row in emp_audit.
Transaction #3 : I update the above emp_addr's attribute. This results in a UPDATE row in emp_addr_audit.
I tried the following SQL #1 and it returned 3 rows as expected;
SQL #1
SELECT emp.*, addr.*
FROM emp_audit emp
FULL OUTER JOIN emp_addr addr USING(emp_id, txid);
However, when I added a where clause to the SQL, it returns only 2 rows. The missing row was the result of Transaction #3, where only emp_addr table row was UPDATED and emp table row was untouched.
SQL #2
SELECT emp.*, addr.*
FROM emp_audit emp
FULL OUTER JOIN emp_addr addr USING(emp_id, txid);
WHERE emp.empnum = 20;
What SQL will STILL be able to get me 3 rows for the 3 transactions so that I can still filter out based on empnum ?
Thank you,
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先在审计表中添加一个额外的列
txid bigint
,然后修改执行审计的存储过程以调用txid_current()
来存储当前事务id和审计记录。然后,当您需要报告审计记录时,使用 emp_id 和 txid 在 2 个表之间进行外连接,以便您可以在一行上呈现同一事务中发生的 2 个单独的插入。
Firstly add an additional column
txid bigint
to the audit tables, then modify the stored proc that does the audit to calltxid_current()
to store the current transaction id with the audit record.Then when you need to report the audit records do an outer join between the 2 tables using the emp_id and the txid so that you can present the 2 separate inserts that occur within the same transaction on a single line.