以下查询返回 2036 行:
SELECT "FooUID" from "Foo" f
LEFT JOIN "Bar" b ON f."BarUID" = b."BarUID"
WHERE f."BarUID" IS NOT NULL AND b."BarUID" IS NULL
但是下面的语句只更新了 1870 行:
UPDATE "Foo" f1 set "BarUID" = 'aNewUID'
WHERE f1."FooUID" IN (
SELECT f2."FooUID" from "Foo" f2
LEFT JOIN "Bar" b ON f2."BarUID" = b."BarUID"
WHERE f2."BarUID" IS NOT NULL AND b."BarUID" IS NULL
)
这怎么可能?
编辑 1:第一个查询继续返回 166 行,第二个继续更新 0 行。
编辑2:
在下面,嵌套查询返回包含 UID 的行,但外部查询返回 0 行。
SELECT * from "Foo" f1
WHERE f1."FooUID" = (
SELECT f2."FooUID" FROM "Foo" f2
LEFT JOIN "Bar" b ON f2."BarUID" = b."BarUID"
WHERE f2."BarUID" IS NOT NULL AND b."BarUID" IS NULL
LIMIT 1
)
我疯了吗?
编辑 3:
@wildplasser提供的以下语句成功更新了剩余的 166 行:
UPDATE "Foo" ff
SET "BarUID" = 'aNewUID'
WHERE ff."BarUID" IS NOT NULL
AND NOT EXISTS (
SELECT * FROM "Bar" bb
WHERE bb."BarUID"= ff."BarUID"
)
但是,我仍然不明白为什么原版没有接他们。如果嵌套查询选择了 166"FooUID"
秒,为什么它们不能使用 匹配到"Foo"
表中的行IN
?
编辑 4:我想得越多,这个背景可能很重要:
这一切都发生在最近从另一台克隆的数据库服务器上。我与进行克隆的 IT 人员进行了交谈,结果发现他没有关闭在原始数据库之上运行的应用程序,然后才将其关闭以进行克隆。这意味着数据库很可能在事务中被关闭(我不知道这有多不优雅)。是否有可能数据库中的某些内容处于损坏状态,导致我看到这些幻像行?
不幸的是,我无法再复制它,因为运行了 wildplasser 的修复程序。原始数据库(再次启动并为应用程序提供服务)没有我试图在副本上修复的任何无效数据,更不用说我目睹的恶作剧的任何痕迹。
我应该提一下,在运行修复程序之前,我将问题简化为最基本的荒谬:我首先从编辑 2中FooUID
的嵌套查询中选择了仍然返回 0 行。Foo
FooUID