0

「監視対象テーブルごとに 1 つの監査テーブル」設計を使用しています。ただし、この場合、テーブルには監視する必要がemp(PARENT)ある子テーブルがあるため、 と があります。emp_addressemp_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_audit テーブルの 1 行に対して emp_addr_audit テーブルに複数 (たとえば 5) 行ある可能性があります。また、その逆も同様です。

レポートには、トランザクション (変更) ごとに 1 行が必要です。レポートには次の列があります

empname, line1, operation(insert/delete/update), updatetime

何が必要かを理解するために、2 つのシナリオを考えてみましょう。

  1. 最初のトランザクションでは、emp属性のみが作成されます。次に、別のトランザクションで、対応する行emp_addrが作成されます。これで、emp_auditテーブルに 1 行、テーブルに 1 行ができましたemp_addr_audit。レポートには 2 行 (トランザクションごとに 1 行) があります。
  2. empと属性の両方emp_addrが 1 つのトランザクションで作成されます。これにより、 に 1 行、 に 1 行あることが保証さemp_auditemp_addr_auditます。これで、レポートには 1 行のみが表示されます (両方のテーブル行が 1 つのトランザクションで作成されたため)。

シナリオ:
トランザクション #1: emp と emp_addr の両方に行を挿入します。これにより、emp_audit と emp_addr_audit でそれぞれ 1 行になります。(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 行しか返されません。行が欠落しているのはトランザクション #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;

empnumに基づいて除外できるように、3 つのトランザクションに対して 3 つの行を取得できるSQL は何ですか?

4

1 に答える 1

1

FULL JOINは、両方のテーブルからテーブルを作成し、空の(一致しない)行にNULL値を入力します。emp.empnum = 20の行のみを選択すると、もちろんemp.empnumにNULLがある最後の行は返されません。

たぶん、emp_idでのみ参加してから、GROUPBYtxidを実行できます。しかし、これはそれほど簡単ではありません。両方のテーブルを常に更新する必要がある場合があります。または、より高度なロジックを使用します(たとえば、次の完全な行まで片側がnullである1つのemp_idのすべてのトランザクションを選択し、欠落している部分を最後の完全な行で埋めます)。

于 2010-11-30T13:03:40.903 に答える