我疯了:PostgreSQL IN运算符使用嵌套查询返回意外结果

Pau*_*ora 6 postgresql subquery in-subquery

以下查询返回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
Run Code Online (Sandbox Code Playgroud)

但以下语句仅更新了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
)
Run Code Online (Sandbox Code Playgroud)

这怎么可能?

编辑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
)
Run Code Online (Sandbox Code Playgroud)

我疯了吗?

编辑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"
)
Run Code Online (Sandbox Code Playgroud)

但是,我仍然不明白为什么原来没有接他们.如果嵌套查询选择166 "FooUID"秒,为什么它们不匹配"Foo"表中的行使用IN

编辑4:我想的越多,这个背景可能很重要:

这一切都发生在最近从另一个克隆的数据库服务器上.我跟那个做克隆的IT人员交谈过,结果发现他没有关闭在原始数据库之上运行的应用程序,然后将其删除以克隆它.这意味着数据库很可能在交易中被放下(我不知道如何不合理).是否有可能数据库中的某些东西处于损坏的状态,导致我看到这些幻像行?

不幸的是,我无法再重复它,因为运行wildplasser的修复程序.原始数据库(再次启动并提供应用程序)没有我试图在副本上修复的无效数据,更不用说我目睹的任何诡计.

我应该指出,在运行修复之前,我的问题减少到最基本的荒谬:我首先选择了FooUID从嵌套查询中编辑2,它复制到剪贴板,然后跑从查询选择Foo,其中FooUID相当于被粘贴值-这仍然返回0行.

wil*_*ser 2

如果你用 NOT EXIST 重写它会发生什么,比如

UPDATE Foo ff
SET baruid = 'aNewUID'
WHERE ff.baruid IS NOT NULL
AND NOT EXISTS (SELECT * FROM bar bb
    WHERE bb.baruid = ff.baruid
    );
Run Code Online (Sandbox Code Playgroud)

在我看来,这比选择外部连接的肢体腿要干净得多。