Postgres SQL для соединения таблиц аудита родитель-потомок - PullRequest
0 голосов
/ 01 октября 2010

Мы используем "1 таблица аудита для каждой отслеживаемой таблицы" design;Однако в нашем случае таблица emp(PARENT) имеет дочернюю таблицу emp_address, которую также необходимо отслеживать, поэтому у нас есть emp_audit и emp_addr_audit tables.

SQL аудита postgres: как объединить 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 только для тех таблиц, столбцы которых были изменены в операции обновления.Учитывая это, у меня может быть несколько (скажем, 5) строк в таблице emp_addr_audit на 1 строку в таблице emp_audit.И наоборот.

В отчете требуется 1 строка для каждой транзакции (модификации).Отчет будет иметь следующие столбцы

empname, строка1, операция (вставка / удаление / обновление), время обновления

Давайте рассмотрим 2 сценария, чтобы понять, что необходимо:

  1. В исходной транзакции создаются только emp атрибуты.Затем в отдельной транзакции создается соответствующая строка в emp_addr.Итак, теперь у нас есть 1 строка в таблице emp_audit и 1 строка в таблице emp_addr_audit.Отчет будет иметь 2 строки (по одной на каждую транзакцию).
  2. Оба атрибута emp и emp_addr создаются в одной транзакции.Это обеспечит наличие 1 строки в emp_audit и 1 строки в emp_addr_audit.Теперь отчет будет иметь ТОЛЬКО 1 строку (поскольку обе строки таблицы были созданы в одной транзакции).

Сценарий :
Транзакция # 1: я вставляю строкув обоих emp и emp_addr.Это приводит к появлению строки в emp_audit и emp_addr_audit. (INSERT)
Транзакция № 2: Я обновляю вышеупомянутый атрибут emp '.Это приводит к появлению строки UPDATE в emp_audit.
Транзакция № 3: Я обновляю вышеуказанный атрибут emp_addr.Это приводит к появлению строки UPDATE в emp_addr_audit.

Я попробовал следующий 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;

Какой SQL будет STILL смог получить мне 3 строки для 3 транзакций, чтобы я мог отфильтровать их по empnum?

1 Ответ

1 голос
/ 30 ноября 2010

FULL JOIN создаст таблицу из обеих таблиц и заполнит пустые (не совпадающие) строки значениями NULL. Когда вы выбираете только строки с emp.empnum = 20, это, конечно, не вернет последнюю строку, которая имеет NULL в emp.empnum.

Может быть, вы можете ПРИСОЕДИНЯТЬСЯ только к emp_id, а затем выполнить txid для GROUP BY. Но это будет не так просто. Возможно, вам придется всегда обновлять обе таблицы. Или используйте более продвинутую логику (что-то вроде: выберите все транзакции одного emp_id, где одна сторона равна нулю до следующей полной строки, и заполните недостающие части последней полной строкой).

...