4

当你有一个记录列表时,有没有办法在你尝试删除这些记录之前检查这些记录中的每一个是否有外键引用?

例如,如果我有一个借阅者列表和一个图书列表,那么如果一个借阅者仍有借阅的图书,那么您应该无法从系统中删除该借阅者。(然而,我的实际系统比这复杂得多 - 更多的表。)

我想从任何有借书的借款人中删除删除选项(在该示例中)。

如果我尝试删除具有外键引用的记录,则会收到以下错误:

数据库访问失败:无法删除或更新父行:外键约束失败 ( dbname. tablename, CONSTRAINT fkfieldidFOREIGN KEY ( fieldid) REFERENCES tablename( fieldid))

一种解决方案是编写一个查询来检查记录列表中的每条记录是否在它可能被引用的任何可能的表中具有任何外键引用。

但是,如果我希望在我的内容管理系统中显示一个包含 100 条记录的列表,并且我必须运行 100 个子查询才能显示该列表,这显然是非常低效的!

最终用户在尝试删除记录时会感到困惑,但他们不能,因为该数据在其他地方“正在使用”,所以我宁愿删除删除选项以避免混淆。

关于什么是最好的事情的任何想法?谢谢。

4

2 回答 2

1

您可以使用子查询或连接轻松完成此操作。

IE。子查询

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 变体。

于 2010-07-01T20:50:03.337 回答
1

你可能喜欢的是交易。

1) 删除所有条目。

2a) 如果发生任何错误 -> 回滚 2b) 如果没有发生错误 -> 提交

http://dev.mysql.com/doc/refman/5.0/en/commit.html

于 2010-07-01T20:55:31.283 回答