多表關聯是關係型資料庫的核心能力。本文系統講解 LEFT JOIN、INNER JOIN、RIGHT JOIN 的語法差異、執行邏輯,並重點演示 **多表關聯刪除** 的標準寫法與避坑指南。
| JOIN 類型 | 語法 | 結果集 | 適用場景 |
|---|---|---|---|
| INNER JOIN | A INNER JOIN B ON A.id = B.id | 僅返回**雙方都匹配**的行 | 主從表強關聯,如訂單-訂單項 |
| LEFT JOIN | A LEFT JOIN B ON A.id = B.id | 返回**左表所有行**,右表無匹配則 NULL | 主表必須保留,如用戶-訂單(無訂單用戶也要查出) |
| RIGHT JOIN | A RIGHT JOIN B ON A.id = B.id | 返回**右表所有行**,左表無匹配則 NULL | 較少用,可改寫為 LEFT JOIN 互換表順序 |
| FULL JOIN | MySQL 不支援 | 雙方所有行,無匹配填 NULL | 用 LEFT JOIN UNION RIGHT JOIN 模擬 |
-- 建表
CREATE TABLE `product` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`amount` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM;
CREATE TABLE `product_details` (
`id` int(10) unsigned NOT NULL,
`weight` int(10) unsigned DEFAULT NULL,
`exist` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM;
-- 測試資料
INSERT INTO product (id, amount) VALUES (1,100),(2,200),(3,300),(4,400);
INSERT INTO product_details (id, weight, exist) VALUES (2,22,0),(4,44,1),(5,55,0),(6,66,1);
-- 查詢:所有產品 + 明細(無明細顯示 NULL)
SELECT p.id, p.amount, pd.weight, pd.exist
FROM product p
LEFT JOIN product_details pd ON p.id = pd.id;
+----+--------+--------+------+
| id | amount | weight | exist|
+----+--------+--------+------+
| 1 | 100 | NULL | NULL |
| 2 | 200 | 22 | 0 |
| 3 | 300 | NULL | NULL |
| 4 | 400 | 44 | 1 |
+----+--------+--------+------+
注意:product_details 中 id=5,6 在 product 中不存在,**LEFT JOIN 不會顯示**(因以左表為基準)。若需雙向保留,用 FULL JOIN 模擬。
-- 刪除 category 表中 id=1 的分類,同時刪除 news 表中對應的文章
DELETE c, n
FROM category c
LEFT JOIN news n ON c.id = n.category_id
WHERE c.id = 1;
DELETE c, n 表示同時刪除兩表匹配行;DELETE c 僅刪除主表。INNER JOIN:僅刪除**雙方都存在**的匹配行。LEFT JOIN:刪除**左表所有符合 WHERE 的行**,右表**有匹配則一併刪除**,無匹配則不影響右表。刪除重插(REPLACE)會導致自增 ID 變更、外鍵級聯、觸發器雙重觸發。**多表關聯刪除 + 單獨 INSERT** 更可控。
SELECT c.nom, e.nom
FROM consultant c
INNER JOIN affaire a ON c.consultant_id = a.consultant_id
INNER JOIN besoin b ON a.besoin_id = b.besoin_id
INNER JOIN salarie sa ON b.salarie_id = sa.salarie_id
INNER JOIN site s ON sa.site_id = s.site_id
INNER JOIN entreprise e ON s.entreprise_id = e.entreprise_id;
等價於舊式逗號連接 + WHERE,但語義更清晰、優化器更易產生最佳計劃。
STRAIGHT_JOIN 強制順序。LIMIT 下推、游標分頁。