你跟我現在算什麼關係…? 現實世界中曖昧總是讓人受盡委屈,而在資料庫的世界裡,則是不能找不到資料表關聯的證據,那麼何時該確認呢? 在資料庫系統設計一開始我們就必需了解資料表彼此之間的關係,因為資料表所會出現的三種關係將會影響到整個系統的資料表要如何被設計。
一對多 | 多對多 | 一對一 |
---|---|---|
One-to-Many | Many-to-Many | One-to-One |
1:n | n:n | 1:1 |
我們用幾個例子來理解
進行這段描述的分析,想一下,在現實世界中,你會把哪些東西當成不同東西在講?
搞清楚表格關係該如何配對,這個過程中可能會經過反覆的確認,最終定義出關係。
資料表的關係,我們可以透過 ERD (Entity Relationship Diagram) 來更加方便看出整體的關係,市場上有許多可以繪製ERD的軟體,我個人覺得 Lucidchart 直覺好用,所以推薦給大家,註冊後就可以使用免費版本,雖然有數量的限制,但是可以透過匯出匯入的小技巧,達到使用到更多的數量,不過如果公司願意噴預算,那當然要省下這個麻煩啦:)
一對一跟一對多都可以很容易用看的就理解了,但是在資料庫世界中要直接多對多其實很困難,幸好有一個已經被當成多對多解答的方法,必需在兩個多對多關係中的資料表中間再放一張表,這張表的功能是組合兩個主鍵形成兩個一對多,道理是兩個一對多關係,串再一起便會是多對多。
透過下列表格來理解一下,安安計畫在對應表當中有王大通、陳小聰跟廖小明,這樣可以看出一對多的關係,接著來看王大通同時在安安計畫跟你好計畫當中,所以是多對一的關係,因此計畫跟成員就能形成多對多的對應。
計畫表
Projects |
---|
安安計畫 |
你好計畫 |
員工表
Employess |
---|
王大通 |
陳小聰 |
廖小明 |
林小美 |
對應表
project_id | emplouee_id |
---|---|
安安計畫 | 王大通 |
安安計畫 | 陳小聰 |
安安計畫 | 廖小明 |
你好計畫 | 林小美 |
你好計畫 | 王大通 |
CREATE TABLE units (
id SERIAL PRIMARY KEY,
code VARCHAR(300) NOT NULL,
name VARCHAR(300) NOT NULL
);
CREATE TABLE employees (
id SERIAL PRIMARY KEY,
name VARCHAR(300) NOT NULL,
birthdate DATE NOT NULL,
email VARCHAR(200) UNIQUE NOT NULL,
unit_id INT REFERENCES units (id) ON DELETE SET NULL
);
CREATE TABLE projects (
id SERIAL PRIMARY KEY,
code VARCHAR(300) NOT NULL,
name VARCHAR(300) NOT NULL,
principal_investigator INT REFERENCES employees (id) ON DELETE SET NULL,
date_beg DATE NOT NULL,
date_end DATE NOT NULL
);
CREATE TABLE accounts (
id SERIAL PRIMARY KEY,
email VARCHAR(200) REFERENCES employees (email) ON DELETE CASCADE,
password VARCHAR(200) NOT NULL
);
CREATE TABLE projects_employees (
id SERIAL PRIMARY KEY,
project_id INT REFERENCES projects ON DELETE CASCADE,
employee_id INT REFERENCES employees ON DELETE CASCADE
);
這一段沒什麼好介紹的,從一開始跟到現在,大家應該也是老熟了,給這個架構一點點基本的資料。
INSERT INTO units (code,name)
VALUES
('A001','研發部'),
('B001','開發部'),
('C001','分析部');
INSERT INTO employees
(name, birthdate, email, unit_id)
VALUES
('呂光晴','1962-06-18','misawa1981@gmail.com', 1),
('橘建太', '1967-03-27', 'kobashi1988@gmail.com', 1),
('黃利明', '1963-12-08', 'kawada1982@gmail.com', 2),
('宏上明', '1961-05-08', 'akira1980@gmail.com', 2);
INSERT INTO projects
(code ,name, principal_investigator, date_beg, date_end)
VALUES
('2022JP00001', '諾亞方舟計畫', 1, '2022-01-01','2024-12-31'),
('2022JP00002', '迴旋肘擊離心力研究', 1, '2022-04-01','2023-12-31'),
('2022JP00003', '綠寶石飛瀑怒濤', 1, '2022-07-01','2022-12-31');
INSERT INTO projects_employees
(project_id, employee_id)
VALUES
(1,2),
(2,2),
(2,4),
(3,3),
(3,4);
最後把資料串起來,employees表格JOIN兩次是因為第二次是要對應計畫主持人的編號,這邊也再帶到一個技巧,同一張表不是只能JOIN一次。
SELECT
p.code AS 計畫代碼,
p.name AS 計畫名稱,
e.name AS 計畫人員,
e2.name AS 計畫主持人,
date_beg AS 計畫起始日,
date_end AS 計畫結束日
FROM projects AS p
JOIN projects_employees AS pe ON pe.project_id = p.id
JOIN employees AS e ON pe.employee_id = e.id
JOIN employees AS e2 ON e2.id = p.principal_investigator
ORDER BY p.code, date_beg, date_end;