MariaDB/MySQL 外键约束:可以在删除时请求级联吗?
MariaDB/MySQL foreign key constraint: possible to request cascade at time of delete?
多年来我一直使用 PHP 代码来保持数据库完整性,但现在我正在从 MyISAM 切换到 InnoDB,并且认为利用外键约束可能会很好,让数据库承担更多负载.但我想在进行级联之前与用户确认,因此约束将声明为 ON DELETE RESTRICT
。当我得到错误时,我会让用户知道有依赖记录以及有多少,如果他们说,"Sure, delete them," 让数据库进行级联删除会很好。是否可以告诉特定的 DELETE
语句继续进行级联?我希望 DELETE
命令上有一个选项或其他内容(例如伪代码 DELETE FROM table WHERE ... CASCADE TO child-table
),但我什么也没看到。
示例(非常标准的多对多):
CREATE TABLE `person` (
`PersonID` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`FullName` varchar(100) CHARACTER SET utf8mb4 NOT NULL DEFAULT '',
<many other fields>,
PRIMARY KEY (`PersonID`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `category` (
`CategoryID` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`Category` varchar(60) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
PRIMARY KEY (`CategoryID`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `percat` (
`PersonID` mediumint(8) unsigned NOT NULL DEFAULT 0,
`CategoryID` mediumint(8) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`PersonID`,`CategoryID`),
FOREIGN KEY (`PersonID`) REFERENCES `person`(`PersonID`) ON DELETE RESTRICT,
FOREIGN KEY (`CategoryID`) REFERENCES `category`(`CategoryID`) ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=ascii COLLATE=ascii_bin;
我找到了 ,但是:(a) 它是针对 SQLServer 的,而不是 MySQL(好吧,从技术上讲,我使用的是 MariaDB 10.2.4,如果有区别的话),所以我不我不知道我是否有其他可用的选项,并且 (b) 这样的存储过程代码不会比我已经拥有的 PHP 代码更简单(并且在我开发时不太明显),所以我看不出用一个换另一个的意义。
简答:否
更长的答案:
答案是头脑简单:FK就是头脑简单。当您要求的不仅仅是琐碎的操作时,您要求的 FK 太多了,您需要将 "business logic" 构建到您的应用程序中。
触发器同上。
MySQL(和 MariaDB)与重量级选手相比一直是 "lean and mean"。 FK 作为功能列表 "yes, we have FKs, too" 的检查存在。因此,FK 细节中的任何深奥内容都可能丢失。
有时语法是在没有任何实际代码的情况下实现的 -- CHECK
; INDEX(x DESC)
。 (后者最终在 8.0 中实现,但我估计用例数量约为千分之一。)
多年来我一直使用 PHP 代码来保持数据库完整性,但现在我正在从 MyISAM 切换到 InnoDB,并且认为利用外键约束可能会很好,让数据库承担更多负载.但我想在进行级联之前与用户确认,因此约束将声明为 ON DELETE RESTRICT
。当我得到错误时,我会让用户知道有依赖记录以及有多少,如果他们说,"Sure, delete them," 让数据库进行级联删除会很好。是否可以告诉特定的 DELETE
语句继续进行级联?我希望 DELETE
命令上有一个选项或其他内容(例如伪代码 DELETE FROM table WHERE ... CASCADE TO child-table
),但我什么也没看到。
示例(非常标准的多对多):
CREATE TABLE `person` (
`PersonID` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`FullName` varchar(100) CHARACTER SET utf8mb4 NOT NULL DEFAULT '',
<many other fields>,
PRIMARY KEY (`PersonID`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `category` (
`CategoryID` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`Category` varchar(60) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
PRIMARY KEY (`CategoryID`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `percat` (
`PersonID` mediumint(8) unsigned NOT NULL DEFAULT 0,
`CategoryID` mediumint(8) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`PersonID`,`CategoryID`),
FOREIGN KEY (`PersonID`) REFERENCES `person`(`PersonID`) ON DELETE RESTRICT,
FOREIGN KEY (`CategoryID`) REFERENCES `category`(`CategoryID`) ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=ascii COLLATE=ascii_bin;
我找到了
简答:否
更长的答案:
答案是头脑简单:FK就是头脑简单。当您要求的不仅仅是琐碎的操作时,您要求的 FK 太多了,您需要将 "business logic" 构建到您的应用程序中。
触发器同上。
MySQL(和 MariaDB)与重量级选手相比一直是 "lean and mean"。 FK 作为功能列表 "yes, we have FKs, too" 的检查存在。因此,FK 细节中的任何深奥内容都可能丢失。
有时语法是在没有任何实际代码的情况下实现的 -- CHECK
; INDEX(x DESC)
。 (后者最终在 8.0 中实现,但我估计用例数量约为千分之一。)