【发布时间】:2017-04-19 16:16:40
【问题描述】:
参考我之前的帖子。
Sql Cleanup script, delete from one table that's not in the other1
使用 DB2 for IBM i(As400、Db2)。
我在凌晨 3 点执行以下 sql 作为清理脚本。
DELETE FROM p6prodpf A WHERE (0 = (SELECT COUNT(*) FROM P6OPIPF B WHERE B.OPIID = A.OPIID))
我有一个不同的过程,在这条sql运行的同时插入两条记录,第一条记录是P6OPIPF记录,然后将详细记录插入P6PRODPF。
问题。
在 SQL 清理运行后,P6PRODPF 记录丢失。但请记住,存储记录的进程同时运行。
我对 SQL 的理解是它通过 P6PRODPF 并检查记录是否在 P6OPIPF 如果它不在 P6OPIPF 然后删除 P6PRODPF。
但随后我在系统导航器中对该 SQL 运行 Visual Explain,并得到以下结果。
现在我很困惑。
Visual explain 之后看起来语句以检查P6OPIPF 开头。
那么它的内容是:如果在P6OPIPF 中的那个时间实例中有一条记录,而P6PRODPF 中没有具有相同键的记录,则删除P6PRODPF。
这可以解释我的问题,即当我的插入记录的进程和 sql 脚本同时运行时,P6PRODPF 被删除。
那么我如何看待它。(我的理论)
插入两条记录的进程启动。
插入两条记录的进程将第一条记录插入到
P6OPIPF.- SQL 清理同时运行。查询看到的是
P6OPIPF记录并检查它是否有P6PRODPF记录。在这个阶段 仍然没有插入P6PRODPF,所以 Sql 认为它需要 删除P6PRODPF中的记录。 - 同时插入两条记录的进程插入
P6PRODPF中的第二条记录。 - 而且因为 Sql 在那个阶段没有看到
P6PRODPF删除P6PRODPF中新插入的记录,留下P6OPIPF没有P6PRODPF记录的记录。
我说的对吗?
我真正想知道的只是上面列出的删除脚本。我对 SQL 的理解是它通过 P6PRODPF 并检查记录是否在 P6OPIPF 中,如果它不在 P6OPIPF 中,然后删除 P6PRODPF。但是在视觉解释之后,我可以看到它从检查 P6OPIPF 开始。那么 delete 语句首先会检查什么?
插入的代码在 CA PLEX 生成器中生成。 RPGIV 代码。
我的一个函数将首先插入P6OPIPF(OperationsItem.Update.InsertRow),然后在P6PRODPF(ProductDetail.Update.InsertRow) 中插入其详细信息。
将执行删除脚本的我的计划函数代码。
Scheduled delete script function
希望它有意义。
【问题讨论】:
-
旁注:进行无行删除的更惯用方法是这样的:
DELETE FROM P6ProdPF A WHERE NOT EXISTS (SELECT 1 FROM P6OpiPF B WHERE A.opId = B.opId)。在多对一的情况下,这可能会更快(不需要计算行数,它只检查任何行)。 -
@Clockwork-Muse 感谢您的提示,我将在未来使用它。
标签: sql db2 ibm-midrange db2-400