简体   繁体   English

在尝试删除MySQL中的任何这些记录之前,如何检查记录列表的外键引用?

[英]How can you check for foreign key references for a list of records before attempting to delete any of these records in MySQL?

Is there a way, when you have a list of records, to check if each of these records have foreign key references before you attempt to delete any of these records? 当您有记录列表时,有没有办法在尝试删除这些记录中的任何一个之前检查其中每个记录是否都具有外键引用?

As an example, if I have a list of borrowers and a list of books, you should not be able to delete a borrower from the system if he still has books on loan. 例如,如果我有一个借阅者列表和一本账簿,那么如果借阅者仍然有借书的话,那么您就不能从系统中删除该借阅者。 (My actual system is much more complicated than that however - a lot more tables.) (但是,我的实际系统要比这复杂得多-表格要多得多。)

I would like to remove the delete option from any borrowers that have books on loan (in that example). 我想从所有有借书的借款人中删除删除选项(在该示例中)。

If I try to delete a record with foreign key references, I get an error to the effect of: 如果我尝试删除带有外键引用的记录,则会收到以下错误:

Database access failed: Cannot delete or update a parent row: a foreign key constraint fails ( dbname . tablename , CONSTRAINT fkfieldid FOREIGN KEY ( fieldid ) REFERENCES tablename ( fieldid )) 数据库访问失败:不能删除或更新父行,外键约束失败( dbnametablename ,约束fkfieldid外键( fieldid )参考tablenamefieldid ))

One solution is to write a query to check if each record, in a list of records, has any foreign key references in any of the possible tables it could be referenced. 一种解决方案是编写查询,以检查记录列表中的每个记录是否在可以引用的任何可能表中具有任何外键引用。

However, if I wish to display a list of 100 records from a table in my content management system, and I have to run 100 sub-queries in order to display that list, it is obviously very inefficient! 但是,如果我希望在内容管理系统中显示一个表中的100条记录的列表,并且我必须运行100个子查询才能显示该列表,那么显然效率很低!

End users become confused when they try to delete a record but they can't because that data is 'in use' elsewhere, so I would rather remove the option to delete to avoid confusion. 最终用户在尝试删除记录时会感到困惑,但由于在其他地方“正在使用”该数据而无法做到这一点,因此我宁愿删除该选项以免造成混乱。

Any ideas on what would be the best thing to do? 关于什么是最好的事情的任何想法? Thanks. 谢谢。

You can easily do this using either a sub-query or a join. 您可以使用子查询或联接轻松地执行此操作。

ie. 即。 sub-query 子查询

SELECT B.*, (SELECT COUNT(*) FROM loans L WHERE L.book_id = b.id) loan_count
FROM books B

or join (note that if you allow multiple simultaneous loans, such a book will appear more than once in the results): 或加入(请注意,如果您允许同时进行多次借贷,则该书在结果中会出现多次):

SELECT B.*, L.book_id AS loaned_out_if_not_null
FROM books B
    LEFT JOIN loans L ON B.id = L.book_id

This can of course be shortened down with a GROUP BY: 当然可以使用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

If your database engine has support for CASE, you can avoid the multiple rows in the result by combining that with DISTINCT (of course, DISTINCT also has overhead): 如果您的数据库引擎支持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

Of these, I would go with the GROUP BY variant. 其中,我将使用GROUP BY变体。

What you maybe like are transactions. 您可能喜欢的是交易。

1) Delete all entries. 1)删除所有条目。

2a) If any error occured -> Rollback 2b) If no error occured -> Commit 2a)如果发生任何错误->回滚2b)如果没有发生错误->提交

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM