6

次のクエリは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行を返し、2番目のクエリは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担当者に話を聞いたところ、元のDB上で実行されているアプリケーションをシャットダウンしてからクローンを作成しなかったことがわかりました。これは、DBがトランザクションの途中でダウンした可能性が高いことを意味します(どれほど優雅にダウンしたかはわかりません)。データベース内の何かが破損した状態のままになっていて、これらの幻の行が表示される可能性はありますか?

残念ながら、wildplasserの修正を実行しているため、再現できなくなりました。元のDB(アプリケーションを稼働させて再度提供する)には、コピーで修正しようとした無効なデータはなく、目撃したシェナニガンの痕跡もありません。

修正を実行する前に、問題を最も基本的な不条理に減らしたことに言及する必要があります。最初FooUIDに編集2でネストされたクエリからを選択し、クリップボードにコピーしてから、貼り付けられた値と等しいFoo場所からクエリを実行しました。これはまだ0行を返しました。FooUID

4

1 に答える 1

2

これをNOTEXISTで書き直すとどうなりますか?

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

外側の接合部の四肢の脚を選択するよりも、私にははるかにきれいに見えます。

于 2011-09-11T20:26:41.723 に答える