外鍵是關係資料庫參考完整性的基石。DB2 提供豐富的 ON DELETE / ON UPDATE 規則選項,正確選擇直接影響業務資料的一致性與應用行為。本文透過完整建表腳本,詳細解析各選項語意、適用場景與陷阱。
-- 清理既有物件
DROP TABLE STUDENT_CLASS;
DROP TABLE CLASS;
DROP TABLE STUDENT;
-- 父表:學生
CREATE TABLE STUDENT (
STUDENT_ID INTEGER NOT NULL,
STUDENT_NAME VARCHAR(200),
CONSTRAINT P_KEY_1 PRIMARY KEY (STUDENT_ID)
) IN LUZL_32K_TB INDEX IN LUZL_32K_TB;
-- 父表:課程
CREATE TABLE CLASS (
CLASS_ID INTEGER NOT NULL,
CLASS_NAME VARCHAR(200),
CONSTRAINT P_KEY_2 PRIMARY KEY (CLASS_ID)
) IN LUZL_32K_TB INDEX IN LUZL_32K_TB;
-- 子表:學生-課程關聯
CREATE TABLE STUDENT_CLASS (
STUDENT_CLASS_ID INTEGER,
STUDENT_ID INTEGER,
CLASS_ID INTEGER
) IN LUZL_32K_TB INDEX IN LUZL_32K_TB;
-- 外鍵:CLASS_ID 參考 CLASS,級聯刪除、限制更新
ALTER TABLE STUDENT_CLASS
ADD CONSTRAINT IF_CLASS FOREIGN KEY (CLASS_ID)
REFERENCES CLASS (CLASS_ID)
ON DELETE CASCADE ON UPDATE RESTRICT;
-- 外鍵:STUDENT_ID 參考 STUDENT,級聯刪除、限制更新
ALTER TABLE STUDENT_CLASS
ADD CONSTRAINT IF_STUDENT FOREIGN KEY (STUDENT_ID)
REFERENCES STUDENT (STUDENT_ID)
ON DELETE CASCADE ON UPDATE RESTRICT;
-- 測試資料
INSERT INTO STUDENT (STUDENT_ID, STUDENT_NAME) VALUES (1, 'luzl');
INSERT INTO CLASS (CLASS_ID, CLASS_NAME) VALUES (1, 'db2');
INSERT INTO STUDENT_CLASS (STUDENT_CLASS_ID, STUDENT_ID, CLASS_ID) VALUES (1, 1, 1);
| 選項 | 行為 | 適用場景 | 風險提示 |
|---|---|---|---|
| RESTRICT / NO ACTION | 存在子記錄時拒絕刪除父記錄,回傳錯誤 | 嚴格保護主資料,防誤刪 | 應用需捕獲錯誤處理 |
| CASCADE | 刪除父記錄時自動刪除所有關聯子記錄(級聯刪除) | 主從關係緊密,子資料無獨立意義(如訂單-明細) | 誤刪父記錄會連帶刪除大量子資料,不可逆 |
| SET NULL | 刪除父記錄時,將子表對應外鍵欄位設為 NULL(欄位需允許 NULL) | 子資料保留但解除關聯(如員工離職,專案負責人暫時空缺) | 外鍵欄位必須可為 NULL,且不影響 NOT NULL 約束 |
DB2 僅支援 RESTRICT / NO ACTION 兩種,語意相同:若有子記錄引用,拒絕更新父表主鍵值。不支援 CASCADE 或 SET NULL。
ALTER TABLE ... ACTIVATE NOT LOGGED INITIALLY 配合 DELETE。FK_子表_父表_欄位,便於資料字典管理。-- 測試 CASCADE 刪除
DELETE FROM CLASS WHERE CLASS_ID = 1; -- 子表 STUDENT_CLASS 關聯列自動刪除
-- 測試 RESTRICT 更新
UPDATE STUDENT SET STUDENT_ID = 2 WHERE STUDENT_ID = 1; -- 失敗,SQL0531N
-- 測試 SET NULL(需先修改欄位允許 NULL)
ALTER TABLE STUDENT_CLASS ALTER COLUMN CLASS_ID DROP NOT NULL;
ALTER TABLE STUDENT_CLASS DROP FOREIGN KEY IF_CLASS;
ALTER TABLE STUDENT_CLASS ADD CONSTRAINT IF_CLASS
FOREIGN KEY (CLASS_ID) REFERENCES CLASS (CLASS_ID)
ON DELETE SET NULL ON UPDATE RESTRICT;
DELETE FROM CLASS WHERE CLASS_ID = 1; -- 子表 CLASS_ID 變 NULL
精準掌握外鍵行為選項,能在資料庫層面落實業務規則,減少應用程式防衛性程式碼,提升系統健壯度。