mysql - 添加行后如何检查给定行中的引用完整性?

标签 mysql innodb referential-integrity

我正在尝试查看在 foreign_key_checks 设置为 0 时是否有一种方法可以在将单行插入 InnoDB 表后检查其参照完整性。

所以给定两个表:

CREATE TABLE `book` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `author_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `book_cc846901` (`author_id`),
  CONSTRAINT `author_id_refs_id_7fdd0933` FOREIGN KEY (`author_id`) REFERENCES `person` (`id`)
) ENGINE=InnoDB;


CREATE TABLE `person` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

我们对它们运行以下语句:

SET foreign_key_checks=0
INSERT INTO `book` (`id`, `name`, `author_id`) VALUES (1, 'Cryptonomicon', 3)
INSERT INTO `person` (`id`, `name`) VALUES (4, 'Neal Stephenson')
SET foreign_key_checks=1

所以我们在这里放了一些错误的数据 -- author_id 指的是不存在的 person.id 3. 我正在尝试找到一种方法来触发对该行的某种检查,如果有,则会抛出错误像这样的引用问题。

我最初尝试采用的方法是用完全相同的数据更新行。我试过这个:

UPDATE `book` SET `name` = 'Cryptonomicon', `author_id` = 3 WHERE `book`.`id` = 1 

我预计这会触发一个错误——然而,它并没有。由于数据没有改变,显然没有进行完整性检查?例如,将 author_id 设置为 2确实失败。

那么我的问题是:是否有替代方法允许我检查给定的行并在出现问题时触发完整性错误?我用谷歌搜索,但一无所获。我想避免检查整个表,但这可能是唯一的途径。

任何我没有想到的见解或其他方法都将不胜感激。

(如果您对为什么我尝试做这一切感到好奇,那是因为我正在尝试帮助解决 Django 框架中的 open issue,其中不能包含具有前向引用的固定装置已加载。建议的解决方案是在加载固定装置时禁用外键检查,并在加载完成后重新启用它们。我试图弄清楚此时如何返回并检查已加载的行的引用完整性在关闭外键检查时添加,并在出现问题时引发错误。)

最佳答案

我想出了一个解决方案,这要归功于这个问题的答案:Force InnoDB to recheck foreign keys on a table/tables?

我以前见过这个问题,但我最终花了大约 20 分钟来解开所有的抽象概念,并试图以具体的方式理解它在做什么。实际上并没有那么复杂。根据我在这个问题中给出的示例来表述解决方案的核心,您基本上有两个 SELECT 语句:

SELECT *
FROM information_schema.KEY_COLUMN_USAGE
WHERE
    `CONSTRAINT_SCHEMA` LIKE `test`
    AND `TABLE_NAME` = `book`

这将返回 book 表中的所有键列。我们可以迭代这些结果并检查它们的引用,如下所示——在本例中使用“author_id”:

SELECT * FROM `book` as REFERRING
LEFT JOIN `person` as REFERRED
ON (REFERRING.`author_id` = REFERRED.`id`)
WHERE REFERRING.`author_id` IS NOT NULL
AND REFERRED.`id` IS NULL

基本上,该语句将返回 author_id 中有值但相关表中 id 没有相应值的任何行。这些是“坏行”。

我不需要直接在 MySQL 中触发错误——为了我的目的,我可以在应用程序代码中引发错误——所以这就是我需要做的。但这最终成为一个相当直接和快速的解决方案,所以我很高兴我找到了它!

关于mysql - 添加行后如何检查给定行中的引用完整性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6470393/

相关文章:

java - 使用java查询mysql中的四个表

sql - 高级不同 SQL 查询的问题

mysql - 在mysql源代码中,有 'DBUG_ENTER'函数,现在我使用GDB来调试服务器,如何打开 'DBUG_ENTER'开关来打印日志?

mysql - Magento 升级 1.3 和 INNODB/MYISAM

php - 在我的本地主机上安装crete5时出现SQL错误

mysql - 优化每月 # 次购买的 SQL 脚本

mysql - 具有较大自动增量值的行是否可以比具有较小自动增量值的行出现得更快?

domain-driven-design - CQRS/DDD : Checking referential integrity

postgresql - 具有外键约束的关系数据库如何摄取顺序可能错误的数据?

postgresql - "polymorphism"用于 FOREIGN KEY 约束