簡體   English   中英

SQL-具有3個所有者表的外鍵一個表

[英]SQL - foreign key one table with 3 owner tables

我有下表Widget ,它將與每個行關聯一個所有者。

所有者可以是UserCompanyDepartment Tables中的ID。 我猜想如何設置是使鏈接表像這樣?

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

然后讓Widget表使用該ID作為owner前提是應用中的邏輯是:如果company is not null則所有者為公司,否則所有者為用戶。

沒有公司,部門就不存在。

如果要從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表中一個小部件的所有者是公司。 但是,如果company為null,則所有者是用戶。 如果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;

但是,即使company列不為null,即使WIDGET表中的user列也可以為null,則您將建立另一個OWNER表以保留所有者信息(USER,COMPANY,DEPARTMENT)。 當然,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)
);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM