繁体   English   中英

从NON审计跟踪表到审计跟踪表的外键

[英]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);

  • FK真的不应该指向移动目标
  • 为使以上各项起作用,FK约束将需要DEFERRABLE INITIALLY DEFERRED
  • 但实际上,您应该使用稳定键,(并将路径移动到单独的表中)
  • 而在现实生活中, 无论是员工和部门应该允许历史,所以他们应该(M:N)结表。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM