有没有办法,当你有一个记录列表时,在你试图删除任何这些记录之前检查这些记录是否都有外键引用?
例如,如果我有一份借款人名单和一份书籍清单,如果他还有借书,你就不应该从系统中删除借款人. (我的实际系统比那复杂得多 – 更多的表格.)
我想删除任何有借书的借款人的删除选项(在该示例中).
如果我尝试删除带有外键引用的记录,我会收到一个错误:
Database access failed: Cannot delete or update a parent row: a foreign key constraint fails (
dbname
.tablename
, CONSTRAINTfkfieldid
FOREIGN KEY (fieldid
) REFERENCEStablename
(fieldid
))
一种解决方案是编写查询以检查记录列表中的每个记录是否在可以引用的任何可能表中具有任何外键引用.
但是,如果我希望在我的内容管理系统中显示来自表中的100条记录的列表,并且我必须运行100个子查询才能显示该列表,那么它显然效率很低!
最终用户在尝试删除记录时会感到困惑,但他们不能,因为这些数据在其他地方“正在使用”,所以我宁愿删除删除选项以避免混淆.
关于什么是最好的事情的任何想法?
谢谢.
解决方法:
您可以使用子查询或连接轻松完成此操作.
即.子查询
SELECT B.*, (SELECT COUNT(*) FROM loans L WHERE L.book_id = b.id) loan_count
FROM books B
或加入(请注意,如果您允许多个同时发放的贷款,此类图书将在结果中出现多次):
SELECT B.*, L.book_id AS loaned_out_if_not_null
FROM books B
LEFT JOIN loans L ON B.id = L.book_id
这当然可以通过GROUP BY缩短:
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也有开销):
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
其中,我会使用GROUP BY变体.