在尝试删除MySQL中的任何记录之前,如何检查记录列表的外键引用?
当您有记录列表时,在尝试删除这些记录之前,是否有方法检查这些记录中的每个记录是否都有外键引用 例如,如果我有一个借书人列表和一个图书列表,那么如果借书人仍然有借书,你就不能从系统中删除他。(然而,我的实际系统要复杂得多——表格多得多。) 我想删除任何借书的借款人的删除选项(在那个例子中) 如果尝试删除包含外键引用的记录,则会出现以下错误: 数据库访问失败:无法删除或更新父行:外键约束失败(在尝试删除MySQL中的任何记录之前,如何检查记录列表的外键引用?,mysql,foreign-keys,records,referential-integrity,Mysql,Foreign Keys,Records,Referential Integrity,当您有记录列表时,在尝试删除这些记录之前,是否有方法检查这些记录中的每个记录是否都有外键引用 例如,如果我有一个借书人列表和一个图书列表,那么如果借书人仍然有借书,你就不能从系统中删除他。(然而,我的实际系统要复杂得多——表格多得多。) 我想删除任何借书的借款人的删除选项(在那个例子中) 如果尝试删除包含外键引用的记录,则会出现以下错误: 数据库访问失败:无法删除或更新父行:外键约束失败(dbnametablename,约束fkfieldid外键(fieldid)引用tablename(fiel
dbname
tablename
,约束fkfieldid
外键(fieldid
)引用tablename
(fieldid
)
一种解决方案是编写一个查询,以检查记录列表中的每个记录在其可能引用的任何表中是否有任何外键引用
但是,如果我希望在我的内容管理系统中显示一个表中包含100条记录的列表,并且我必须运行100个子查询才能显示该列表,这显然是非常低效的
最终用户在尝试删除记录时会感到困惑,但他们不能,因为该数据在其他地方“正在使用”,因此我宁愿删除该选项以避免混淆
有什么好主意吗?
谢谢。您可以使用子查询或联接轻松完成此操作 即子查询
SELECT B.*, (SELECT COUNT(*) FROM loans L WHERE L.book_id = b.id) loan_count
FROM books B
或加入(请注意,如果您允许多个同时贷款,则这样一本书将在结果中出现多次):
当然,这可以通过以下方式缩短:
SELECT B.id, B.name, COUNT(L.book_id) AS loan_count
FROM books B
LEFT JOIN loans L ON B.id = L.book_id
GROUP BY B.id, B.name
如果您的数据库引擎支持CASE,则可以通过将其与DISTINCT结合使用来避免结果中的多行(当然,DISTINCT也有开销):
其中,我会根据变量分组。您可能喜欢的是交易 1) 删除所有条目 2a)如果发生任何错误->回滚 2b)如果未发生错误->提交
加入重复记录的风险;EXISTS是一个更好的选择这是我开始考虑的解决方案类型,但我所做的是创建查询,检查每个表,其中有一个字段的外键。然后使用UNION连接这些查询,并与包含主键的表进行左外连接。我希望这个解决方案不会太低效。
SELECT B.id, B.name, COUNT(L.book_id) AS loan_count
FROM books B
LEFT JOIN loans L ON B.id = L.book_id
GROUP BY B.id, B.name
SELECT DISTINCT B.*,
CASE WHEN L.book_id IS NOT NULL THEN 1 ELSE 0 END AS loaned_out_if_one
FROM books B
LEFT JOIN loans L ON B.id = L.book_id