2016-05-02 96 views
0

我有以下表Widget,它將擁有與每行相關聯的所有者。SQL - 具有3個所有者表的外鍵一個表

店主可以是UserCompanyDepartment表中的一個編號。我猜如何設置這個鏈接表是這樣的?

id  | user  | company | department 
---------|----------|----------|---------- 
1  | 4  | NULL  | NULL 
2  | 6  | 3  | 6 
3  | 10  | 3  | 8 

然後有Widget表使用該ID作爲owner提供的邏輯是在應用程序中,如果company is not null然後所有者是公司否則所有者將是用戶。

如果沒有公司,部門不能存在。

+0

您可能要考慮使用繼承,但是您的版本非常合理,並且允許正確的外鍵引用。我會添加額外的約束,所以所有的值都是NULL。 –

+0

你能提供一個鏈接來解釋繼承嗎? – whoisearth

+1

http://www.postgresql.org/docs/current/static/ddl-inherit.html。 –

回答

2

如果要在WIDGET表中分別從三個表(USER,COMPANY,DEPARTMENT)中添加三個外鍵(FK)列,則這不是問題。您可以使用下面介紹的JOIN操作區分真正的所有者;

CREATE TABLE WIDGET (
    WIDGET_NAME VARCHAR(20), 
    OWNER_USER_ID INTEGER REFERENCES USER(ID), 
    OWNER_COMPANY_ID INTEGER REFERENCES COMPANY(ID), 
    OWNER_DEPART_ID INTEGER REFERENCES DEPARTMENT(ID), 
); 
-- retrieve OWNER_USER (you can JOIN with the USER table) 
SELECT OWNER_USER_ID, WIDGET_NAME FROM WIDGET WHERE OWNER_COMPANY_ID IS NULL; 
-- retrieve OWNER_COMPANY (plus OWNER_DEPART) (you can JOIN with the COMPANY and DEPARTMENT table) 
SELECT OWNER_COMPANY_ID, OWNER_DEPART_ID, WIDGET_NAME FROM WIDGET WHERE OWNER_COMPANY_ID IS NOT NULL; 

如果你想從三個表添加只是一個單一的PK列,它沒有任何意義從理論上說,但你可以一些額外的條件下做到這一點。你說WIDGET表中的一個小部件的所有者是公司,如果公司不爲空。但是如果公司爲空,那麼所有者就是用戶。如果WIDGET表中的用戶(或對應標識符)列總是不爲空,無論公司(或相應標識符)列是否爲空,那麼您可以將USER表的主鍵(PK)列作爲WIDGET的單個FK表。爲什麼?用戶→公司和用戶→部門依賴關係由此條件生成。這意味着,如果你選擇了一個用戶A,那麼不再有兩個公司與他或她相關,並且與用戶和部門之間相同。

-- Schema of USER, COMPANY, DEPARTMENT table 
CREATE TABLE USER (
    ID INTEGER PRIMARY KEY, 
    NAME VARCHAR(20), 
    COMPANY_ID INTEGER REFERENCES COMPANY(ID), 
    DEPART_ID INTEGER REFERENCES DEPARTMENT(ID) 
); 

CREATE TABLE COMPANY (
    ID INTEGER PRIMARY KEY, 
    NAME VARCHAR(20) 
); 

CREATE TABLE DEPARTMENT (
    ID INTEGER PRIMARY KEY, 
    NAME VARCHAR(20) 
); 

-- Schema of WIDGET table 
CREATE TABLE WIDGET (
    WIDGET_NAME VARCHAR(20), 
    OWNER_ID INTEGER REFERENCES USER(ID) 
); 

-- retrieve OWNER_USER 
SELECT U.NAME AS OWNER_USER_NAME, W.WIDGET_NAME 
FROM WIDGET W, USER U 
WHERE U.ID = W.OWNER_ID AND U.COMPANY_ID IS NULL; 

-- retrieve OWNER_COMPANY 
SELECT C.NAME AS OWNER_COMPANY_NAME, W.WIDGET_NAME 
FROM WIDGET W, USER U, COMPANY C 
WHERE U.ID = W.OWNER_ID AND U.COMPANY_ID = C.ID; 

-- retrieve OWNER_DEPARTMENT 
SELECT D.NAME AS OWNER_DEPART_NAME, W.WIDGET_NAME 
FROM WIDGET W, USER U, DEPARTMENT D 
WHERE U.ID = W.OWNER_ID AND U.COMPANY_ID IS NOT NULL AND U.DEPART_ID IS NOT NULL AND U.DEPART_ID = D.ID; 

但是,如果在WIDGET表用戶列可以爲空,即使公司列不爲空,那麼你建立另一個主表,讓您的所有者信息(用戶,公司,部門)。當然,WIDGET的每個記錄都必須是唯一的,因此可能需要複合唯一索引。 (請參閱http://www.postgresql.org/docs/current/static/indexes-unique.html

-- Schema of OWNER table 
CREATE TABLE OWNER (
    ID INTEGER PRIMARY KEY. 
    OWNER_USER_ID INTEGER REFERENCES USER(ID), 
    OWNER_COMPANY_ID INTEGER REFERENCES COMPANY(ID), 
    OWNER_DEPARTMENT_ID INTEGER REFERENCES DEPARTMENT(ID) 
); 

-- unique index on OWNER 
CREATE UNIQUE INDEX OWNER_UIDX ON OWNER(OWNER_USER_ID, OWNER_COMPANY_ID, OWNER_DEPARTMENT_ID); 

-- Schema of WIDGET table 
CREATE TABLE WIDGET (
    WIDGET_NAME VARCHAR(20), 
    OWNER_ID INTEGER REFERENCES OWNER(ID) 
); 
+1

請注意'user'是一個保留關鍵字。您需要引用它:'「USER」' –

相關問題