我有一个父表A,其中包含以下属性(列){PKA,a1,a2 ...}和子表B,其中包含以下属性{FKA,b1,b2 ...} PKA是表A的主键(自动增量),表B没有任何主键,但它有一个引用表A的PKA列的外键列FKA(1:n关系)
添加条目: 当我在表A中添加一个条目...我使用PDO API lastInsertId()来获取插入的记录,并使用该值填充表B中的FKA。
问题: 1.但是在删除条目时,我没有找到可以类似方式使用的API“lastDeleteId()”
更大的问题: 当我的删除发生在表A上时,按照设计,删除命令为:表A中的DELETE,其中a1 =。此a1列是非唯一的,因此DELETE命令可以返回需要从表B刷新的多个PKA密钥
注意事项:
感谢您的任何指示。
答案 0 :(得分:2)
您可以在删除查询后立即使用此查询,也可以作为批量清理方法,对于未与父母一起删除的任何子项都可以追溯使用:
DELETE
FROM table_a
WHERE a1 = ?;
SELECT id
FROM table_b
WHERE FKA NOT IN(SELECT id FROM table_a);
或者您可以使用相同的WHERE子句在删除查询之前运行它:
START TRANSACTION;
SELECT id
FROM table_b
WHERE FKA NOT IN(
SELECT id
FROM table_a
WHERE a1 = ?;
);
DELETE
FROM table_a
WHERE a1 = ?;
COMMIT;
第二种方法需要包含在事务中,以确保您只删除在选择时匹配的ID,即使某些其他线程可能已输入与这些过滤器匹配的新数据。
如果您正在使用$pdo->beginTransaction()
然后发出一个SELECT
语句,请获取ID,在应用程序级别使用它们,然后发出delete
语句,这将保留事务处于活动状态,某些记录可能会在该事务中被锁定,尤其是如果您在初始FOR UPDATE
语句中使用select
和/或您有ISOLATION LEVEL
s。
如果您在应用程序层中使用耗时的操作,这将长时间保持数据库中的活动锁定并降低并发连接的应用程序容量。
我擅长避免与数据库服务器进行多次通信会话。这就是为什么我不会首先使用$pdo->beginTransaction()
。
我会将“将要删除的ID”查询扩展为“获取处理已删除记录所需的所有数据”。我会在事务中的一个通信会话中将查询发送到服务器,并且即使数据已从存储中删除,SELECT
声明的结果集也将被发送回应用程序。应用程序收到有效负载的时间。
答案 1 :(得分:1)
您要做的是选择要删除的记录的记录ID,并将它们放在临时表中。然后先从子表中删除,然后从父表中删除。在事务中执行此操作,因此如果错误,则回滚数据。
答案 2 :(得分:0)
我认为最简单的方法可能是将表A的内容复制到临时表中,然后执行删除,然后执行临时表的LEFT OUTER JOIN到更新的表,并使用它来查找没有的行更长的对手。
另外,如果您没有明确地制作主键,那么InnoDB是否会为您制作一个主键?我认为InnoDB存储引擎需要一个。
答案 3 :(得分:0)
如何处理您的数据可能不一致的想法。也就是说,可能存在对已经删除的pk的引用。每次使用fk时都要检查一下。
然后添加一个计划任务来清理记录,方法是选择fk不在的地方(选择pk)。