当 DELETE 由于外键约束而失败时显示示例行

Show example row when a DELETE fails due to a foreign key constraint

我正在尝试从具有多个 table 的 MySQL 数据库中删除一些旧的历史数据。 有一个“卷”table 和一个“元数据”table。当然,你不能有一个不存在的卷的元数据,所以有一个外键约束。

这是我正在尝试执行的查询:

DELETE FROM volumes 
       WHERE deleted > 0 AND 
             deleted_at IS NOT NULL AND 
             deleted_at < '2020-01-01T00:00:00' AND 
             status = 'deleted' AND 
             attach_status = 'detached' 
       LIMIT 5000

这会导致以下错误(为便于阅读而重新格式化):

Integrity error: 'DELETE FROM volumes WHERE deleted > 0 AND deleted_at IS NOT NULL AND deleted_at < '2020-01-01T00:00:00' AND status = 'deleted' AND attach_status = 'detached' LIMIT 5000' 
(1451, 'Cannot delete or update a parent row: 
        a foreign key constraint fails 
        (`volume_glance_metadata`, 
         CONSTRAINT `volume_glance_metadata_ibfk_1` FOREIGN KEY (`volume_id`) REFERENCES 
                                                                `volumes` (`id`))')

如果我尝试搜索此内容,我找到的所有答案都是对不同问题的答案,例如“我怎样才能删除它”或“我怎样才能删除约束”?不过那不是我感兴趣的。

我想知道的是:如何从 volumes table 中找到 DELETE 查询试图删除但无法删除的行示例, 因为在 volume_glance_metadata table 中还有一行有对应的 id (volume_glance_metadata.volume_id = volumes.id)?或者换句话说:给我一个删除失败的例子。

我推测至少有一行不能删除;或者可能不存在可以删除的行。 MySQL 没有尽力找到要删除的 other 行,这似乎有点令人失望,如果有一些行会失败的话。

只需对 volumes 中的行执行具有等效条件的 SELECT,然后将这些行连接到从属 table metadata.

SELECT m.*
FROM volumes AS v
INNER JOIN metadata AS m ON m.volume_id = v.id
WHERE v.deleted > 0 
 AND v.deleted_at IS NOT NULL 
 AND v.deleted_at < '2020-01-01T00:00:00' 
 AND v.status = 'deleted' 
 AND v.attach_status = 'detached' 

连接是内连接,不是外连接,所以它自然returns只匹配行。

如果此连接查询 returns 结果中没有行,则 metadata 不包含会阻止您删除的行。