关于sql:如何在MySQL表中找到无效密钥?

How can I find the invalid keys in a MySQL table?

我有一个MySQL表,我想添加一个外键约束。

在这种情况下,它是一个自引用键...

1
2
3
4
5
6
7
8
CREATE TABLE `contracts` (
  `id` int(11) NOT NULL auto_increment,
  `contract_id_amend_source` int(11) default NULL,

  # ...

  PRIMARY KEY  (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14834 DEFAULT CHARSET=latin1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC;

(我在这里使用遗留数据库 - 我没有想出列名。)

我试着像这样应用密钥......

1
2
3
4
5
ALTER TABLE contracts
ADD CONSTRAINT fk_parent_id
FOREIGN KEY ( contract_id_amend_source )
REFERENCES contracts( id )
ON DELETE CASCADE;

但我得到一个错误......

Cannot add or update a child row: a foreign key constraint fails (contract_tracker/#sql-e18_e9d0a, CONSTRAINT fk_parent_id FOREIGN KEY (contract_id_amend_source) REFERENCES contracts (id) ON DELETE CASCADE)

好的,有一些无效的parent_id

我试着像这样找到他们......

1
2
3
4
5
6
7
SELECT id, contract_id_amend_source
FROM contracts
WHERE contract_id_amend_source
NOT IN (
  SELECT id
  FROM contracts
);

这将返回大约20条记录。 我手动修复了密钥。 然后再次运行上面的查询。 现在它不返回任何记录。

我再次尝试ADD FK,但我仍然得到"无法添加或更新..."错误。

我想我的查询找到坏键一定是错的? 我该如何解决?


看看截断外键约束表。

具体来说,如果您只是更改表的数据,则可以使用:

1
2
3
SET FOREIGN_KEY_CHECKS=0;
... do whatever you need here that is giving you problems...
SET FOREIGN_KEY_CHECKS=1;

我有这个书签,它非常有用。

您还可以尝试通过以下方式查找其他隐藏记录:

1
2
3
4
5
6
7
SELECT id
FROM contracts
LEFT JOIN contracts  
ON contracts.id=contracts.parent_id
WHERE contracts.id IS NOT NULL
AND
contracts.parent_id IS NULL;

快点不要关于@Michael - sqlbot的评论......他是绝对正确的。 这通常不是截断时的问题(你不关心数据的完整性),但在这种情况下你需要关心,所以这个答案的第一部分充其量是半解决方案。