2016-08-19 52 views
1

我想知道是否有任何方式可以在繼承關係中引用tableoid作爲外鍵。例如:在Postgresql中使用tableoids作爲外鍵

CREATE TABLE employee 
(
    name TEXT, 
    PRIMARY KEY(name, TABLEOID) 
); 

CREATE TABLE hourly_employee 
(
    hours_worked INT, 
    PRIMARY KEY(name) 
) INHERITS(employee); 

CREATE TABLE salaried_employee 
(
    anniversary_date DATE, 
    PRIMARY KEY(name) 
) INHERITS(employee); 

CREATE TABLE employee_training 
(
    training_id SERIAL, 
    due_date DATE, 
    employee_name TEXT, 
    emp_oid OID, 
    PRIMARY KEY(training_id), 
    FOREIGN KEY(employee_name, emp_oid) REFERENCES employee(name, TABLEOID) 
); 

INSERT INTO hourly_employee (name, hours_worked) VALUES ('Joe Smith', 40); 
INSERT INTO salaried_employee(name, anniversary_date) VALUES ('Bob Brown', '2014-02-20'); 

INSERT INTO employee_training (due_date, employee_name, emp_oid) VALUES ('2016-08-16', 'Bob Brown', 'salaried_employee'::REGCLASS); 

在這個例子中,外鍵沒有問題產生,但最後插入將與錯誤Key (employee_name, emp_oid)=(Bob Brown, 16403) is not present in table "employee"失敗,即使我可以確認,16403是salaried_employee正確tableoid。

有什麼辦法可以使這項工作?

+0

表'employee'保持爲空,因此不包含任何行,以滿足外鍵。你似乎誤解了表繼承。你想達到什麼目的? –

+0

顯然,我重新閱讀文檔。我試圖做的是產生一個「或/或」外鍵約束;換句話說,我想確保有薪或小時工的員工已經完成了所需的培訓。 – Brad

回答

1

可悲的遺傳有一些嚴重的侷限性。多個元素(包括唯一索引/外鍵)僅適用於一個表,而不適用於子級。就我個人而言,我發現它比我想要的要少得多。

我知道它很煩人,建議你重新設計,但在我看來,你最好有一個單一的表employee與可選列,而不是父/子關係。

CREATE TABLE employee 
(
    name TEXT, 
    employee_type TEXT, 
    hours_worked INT, 
    anniversary_date DATE, 
    PRIMARY KEY(name, TABLEOID) 
); 

從長遠來看,您經常會發現代碼變得更簡單,坦率地說,DBMS之間的代碼更加便攜。

您可以確保使用約束條件爲正確類型輸入了正確的字段,以管理哪些字段對於每種類型都是必需的。

如:

ALTER TABLE employee ADD CHECK (
    (type = 'hourly' and hours worked is not null) 
or (type = 'salaried' and anniversary_date is not null)) 
+1

我欣賞這個建議。這裏的設計大大簡化了;有從僱員表繼承的44個不同的表。這些會是一些複雜的檢查約束:/ – Brad