2011-09-11 36 views
6

下面的查詢返回2036行:我瘋了:PostgreSQL的IN操作符與嵌套查詢返回意外結果

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" s,爲什麼它們不會使用IN"Foo"表中的行匹配?

編輯4:我越仔細想想,這樣的背景下可能是重要的:

這一切的事,這是最近從另外一個克隆的數據庫服務器上進行。我跟那些做過克隆的IT人員交談,結果發現他沒有關閉在原始數據庫之上運行的應用程序,然後將其複製到克隆中。這意味着數據庫大部分可能會在交易中被拖垮(我不知道該如何非常)。數據庫中是否有可能存在損壞的狀態,導致我看到這些幻像行?

不幸的是,自從運行wildplasser的修復程序以來,我不能再重複它。最初的數據庫(重新啓動並再次提供應用程序)沒有任何我試圖修復的無效數據,更不用說我目睹的那些惡意軟件。

我應該指出,在運行修復之前,我的問題減少到最基本的荒謬:我首先從嵌套查詢選擇的FooUID在編輯2,它複製到剪貼板,然後跑一個查詢從Foo,其中,選擇FooUID等於粘貼值 - 這仍然返回0行。

+0

什麼類型是'FooUID',哪一個是由EDIT 2中的內部查詢返回的?不知道發生了什麼,只是稍微探索一下。 –

+0

@mu太短 - 'FooUID'類型爲'uuid'。不知道我理解你的問題的第二部分。 –

+0

你的編輯2讓我難堪。必須是不等於自身的值。你的內心是否正在返回一個非NULL'FooUID'? –

回答

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 
    ); 

看起來比選擇外肢體腿加入乾淨多了給我。

+0

另外,外鍵約束可能會避免這種混亂。 – wildplasser

+0

有趣的你應該提到的是,這是我試圖清理壞的數據來添加外鍵。 –

+0

Gheghe。嘗試將相關名稱添加到子查詢中。也許有人看到兩個foos會感到困惑。你也可以檢查wuery計劃(相關名字也派上用場) – wildplasser

相關問題