博客系統:blogs (文章) 1:N comments (評論)。MyISAM 不支援外鍵,應用層必須手動處理:
blog_id。CREATE TABLE `blogs` (
`id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`title` TEXT, `content` TEXT, `author` VARCHAR(45)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `comments` (
`id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`blog_id` INT UNSIGNED NOT NULL,
`comment` TEXT, `author` VARCHAR(45),
INDEX `idx_blog_id` (`blog_id`),
CONSTRAINT `fk_comments_blogs` FOREIGN KEY (`blog_id`) REFERENCES `blogs` (`id`)
ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
| 子句 | 父表操作 | 子表自動響應 |
|---|---|---|
ON UPDATE CASCADE | 更新 PK | 同步更新 FK |
ON DELETE CASCADE | 刪除行 | 級聯刪除關聯行 |
ON UPDATE SET NULL | 更新 PK | FK 置 NULL (需 FK 允許 NULL) |
ON DELETE SET NULL | 刪除行 | FK 置 NULL |
ON UPDATE RESTRICT / NO ACTION | 更新 PK | 阻止操作,拋錯誤 |
ON DELETE RESTRICT / NO ACTION | 刪除行 | 阻止操作,拋錯誤 (預設) |
-- 插入測試資料
INSERT INTO blogs (title, content, author) VALUES ('First Post', 'Hello', 'Ian');
INSERT INTO comments (blog_id, comment, author) VALUES (1, 'Good!', 'Susan'), (1, 'Nice', 'Rose');
-- 更新文章 ID:CASCADE 自動同步 comments.blog_id
UPDATE blogs SET id = 2 WHERE id = 1;
-- comments 表 blog_id 自動變為 2,無需應用層介入
-- 刪除文章:CASCADE 自動刪除評論
DELETE FROM blogs WHERE id = 2;
-- 關聯評論自動消失
MyISAM 僅解析語法不執行約束,務必使用 InnoDB。
$pdo = new PDO('mysql:host=localhost;dbname=blog;charset=utf8', 'user', 'pass');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
$pdo->beginTransaction();
$pdo->exec("DELETE FROM blogs WHERE id = 1"); -- 外鍵自動清理 comments
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
echo "Failed: " . $e->getMessage();
}
外鍵約束是關聯式資料庫的核心特性,InnoDB 完整支援級聯更新/刪除、SET NULL、RESTRICT 等行為。善用它能將資料一致性下沉到儲存層,大幅簡化應用邏輯,但需權衡寫入效能與鎖影響,視業務場景取捨。