Innodb

外鍵不像我預期的那樣工作

  • February 4, 2016

這是我的桌子;

CREATE TABLE `borclular` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `tc` char(11) COLLATE utf8_turkish_ci NOT NULL,
 `borclu` varchar(255) COLLATE utf8_turkish_ci NOT NULL,
 PRIMARY KEY (`id`),
 UNIQUE KEY `tc` (`tc`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_turkish_ci

CREATE TABLE `dosyalar` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `kurum_id` int(11) NOT NULL,
 `borclu_id` int(11) NOT NULL,
 `hizmetno` varchar(255) COLLATE utf8_turkish_ci DEFAULT NULL,
 PRIMARY KEY (`id`),
 KEY `kurum_id_index` (`kurum_id`),
 KEY `borclu_id_index` (`borclu_id`),
 CONSTRAINT `borclu_id_foreign` FOREIGN KEY (`borclu_id`) REFERENCES `borclular` (`id`),
 CONSTRAINT `kurum_id_foreign` FOREIGN KEY (`kurum_id`) REFERENCES `kurumlar` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_turkish_ci

當我從 borclular 中刪除一行時,我希望也刪除 dosyalar 中的相關行。但是,當我嘗試從 borclular 中刪除一行時,出現以下錯誤;

Cannot delete or update a parent row: a foreign key constraint fails (`iletisim`.`dosyalar`, CONSTRAINT `borclu_id_foreign` FOREIGN KEY (`borclu_id`) REFERENCES `borclular` (`id`))

正如布朗斯通先生所指出的(這只是一個評論,但結果太長了)如果您將密鑰定義為 ,則可以實現您所期望的行為ON DELETE CASCADE

我會非常小心ON DELETE CASCADE,事實上我幾乎從不使用它並且通常建議不要使用它。這也適用於根據被刪除的行採取行動的觸發器。如果一個天真的程序員後來UPSERT通過執行 aDELETE後跟 an來實現父行INSERT(這是我的經驗中非常常見的模式),那麼子數據將全部失去,因為刪除是級聯的,並且級聯刪除的行顯然不是替換為後續插入。

此外,如果您的使用者界面由於錯誤而允許使用者嘗試刪除他們確實不應該刪除的內容,因為其他地方的行依賴於它,您(或使用者)會收到錯誤,而不是數據庫默默地刪除錯誤的內容及其子項.

沒有打開級聯選項有時意味著您需要在數據訪問或業務邏輯層中進行額外的工作才能在父母之前手動刪除子對象,但我認為這通常是一個很小的代價。

警告:有些人認為我的立場是一種不必要的偏執狂。你的旅費可能會改變。

您需要指定您希望刪除操作像這樣級聯:

CONSTRAINT `borclu_id_foreign` 
FOREIGN KEY (`borclu_id`) REFERENCES `borclular` (`id`) ON DELETE CASCADE

如果您未指定ON DELETEON UPDATE則預設為RESTRICT, 從文件中:

對於未指定的 ON DELETE 或 ON UPDATE,預設操作始終是 RESTRICT。

可以在這裡找到:

https://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html

引用自:https://dba.stackexchange.com/questions/128287