[英]Foreign key from a NON audit trail table to an audit trail table
在现有模式中,我仅对其中一个表引入审计跟踪/里程碑支持。 为了讨论问题,我们将使用以下简化的玩具示例来更好地说明问题。
DEPARTMENT
ID | NAME | CREATED_TS | MODIFIED_TS | VERSION
1 | "ABC" | 11/20/2015 | 12/1/9999 | 1
现在,每次收到对id = 1的department
记录的更新请求时,系统都会执行以下操作。 基本上每个更新是一个INSERT
-这改变现有记录的MODIFIED_TS
的时间UPDATE
请求进来,最新记录的MODIFIED_TS
始终保持为12/1/9999
(又名INFINITY
TIMESTAMP)
假设更新ID = 1记录更改了名称,下面是db中的样子。
DEPARTMENT
ID | NAME | CREATED_TS | MODIFIED_TS | VERSION
1 | "ABC" | 11/20/2015 | 11/22/2015 | 1
1 | "XYZ" | 11/22/2015 | 12/1/9999 | 2
现在假设存在一个现有的EMPLOYEE
表,其中DEPT_ID
为外键。 请注意, EMPLOYEE
表没有审核跟踪要求,因此那里没有INFINITY
时间戳或VERSION
概念。 EMPLOYEE
表如下所示
EMPLOYEE
ID | NAME | AGE | DEPT_ID
1 | "John" | 31 | 1
就雇员与DEPT有FK关系而言,一切都很好,而DEPT以前将ID作为PK。 现在, DEPARTMENT
表的PK已更改为复合PK(ID,VERSION)
在对DEPARTMENT
表进行这些模式更改以为其数据创建auit跟踪之后, EMPLOYEE
FK必须以某种方式创建FK,其中不仅DEPT_ID
还要包括DEPT
记录的INFINITY
时间戳( MODIFIED_TS
),因为EMPLOYEE
将始终引用最新的DEPT
记录(要求)
更改EMPLOYEE
表的FK以指向DEPT
表中的最新记录的最佳方法是什么?
这是解决您的问题的可怕的数据建模技巧。 不要在家尝试这个...
由于部门的PK是{id,modified_ts},因此员工的FK也必须是复合的(否则它可能指向另一组唯一的列)。 因此,解决方案是根据需要提供给它:恒定值为'infinity'的列。 (“ infinity”是postgres中日期和时间戳的有效值,您无需发明自己的哨兵值)
CREATE TABLE department
( id INTEGER NOT NULL
, name varchar
, created_ts timestamp
, modified_ts timestamp
, version integer not null default 0
, PRIMARY KEY (id, modified_ts)
);
INSERT INTO department (id, name, created_ts, modified_ts, version) VALUES
(1 , 'ABC', '2015-11-20' , '2015-11-22' , 1) ,
(1 , 'XYZ', '2015-11-22' , 'infinity' , 2) ;
-- CREATE UNIQUE INDEX ON department (id) WHERE modified_ts = 'infinity'::timestamp;
-- Now assume there is an existing EMPLOYEE table with DEPT_ID as a foreign key. Note that EMPLOYEE table doesn't have an audit trail requirement so there is no INFINITY timestamp or VERSIONing concept there. EMPLOYEE table looks like as below
CREATE TABLE employee
( id INTEGER NOT NULL PRIMARY KEY
, name varchar
, age integer not null default 0
, modified_ts timestamp NOT NULL DEFAULT 'infinity'::timestamp CHECK (modified_ts = 'infinity'::timestamp)
, dept_id INTEGER NOT NULL
, FOREIGN KEY (id,modified_ts)
REFERENCES department(id, modified_ts)
);
INSERT INTO employee(id ,name,age,dept_id) VALUES
(1 , 'John' , 31 , 1);
DEFERRABLE INITIALLY DEFERRED
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.