簡體   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