2011-09-11 4 views
6

Następująca kwerenda zwraca 2036 wierszy:jestem szalony: PostgreSQL oraz operatora z zagnieżdżonych zapytań powrocie nieoczekiwane rezultaty

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 

Ale następujące oświadczenie aktualizowane tylko 1870 wierszy:

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 
) 

Jak to możliwe ?

EDYCJA 1: Pierwsze zapytanie nadal zwraca 166 wierszy, a drugie kontynuuje aktualizację 0 wierszy.

EDIT 2:

Poniżej zapytanie zagnieżdżone zwraca się wiersz zawierający UID, a zapytanie zewnętrznej zwraca 0 wierszy.

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 
) 

Czy jestem szalony?

EDIT 3:

następujące oświadczenie, dostarczone przez @wildplasser udało się aktualizację pozostałych 166 rzędów:

UPDATE "Foo" ff 
SET "BarUID" = 'aNewUID' 
WHERE ff."BarUID" IS NOT NULL 
AND NOT EXISTS (
    SELECT * FROM "Bar" bb 
    WHERE bb."BarUID"= ff."BarUID" 
) 

Jednak ja nadal nie rozumiem, dlaczego nie wybrać oryginalny ich. Jeśli zapytanie zagnieżdżone zostało wybrane 166 "FooUID" s, dlaczego nie byłyby one dopasowane do wierszy tabeli "Foo" przy użyciu IN?

EDIT 4: Im więcej o tym myślę, to tło może być ważne:

To wszystko miało miejsce na serwerze bazy danych, który został niedawno sklonowanego z inną. Rozmawiałem z informatykiem, który przeprowadził klonowanie, i okazało się, że nie zamknął aplikacji działającej na oryginalnym DB, zanim zdążył ją sklonować. Oznacza to, że DB został najprawdopodobniej sprowadzony w dół w połowie transakcji (nie wiem, jak bezwstydnie). Czy jest możliwe, że coś w bazie danych zostało w stanie uszkodzonym, prowadząc mnie do tych widmowych wierszy?

Niestety nie mogę już repro, ponieważ działa poprawka wildplasser. Oryginalna DB (ponownie i obsługująca aplikację) nie ma żadnych niepoprawnych danych, które próbowałem naprawić na kopii, a tym bardziej śladu shenaniganów, których byłem świadkiem.

należy wspomnieć, że przed uruchomieniem poprawkę, ja zmniejszona problem do najbardziej podstawowych absurdu: Po raz pierwszy wybrano FooUID z zapytania zagnieżdżonego w Edit 2, kopiować go do schowka, a następnie prowadził kwerendę Wybieranie z Foo gdzie FooUID równa się wklejonej wartości - ta nadal zwróciła 0 wierszy.

+0

Jakiego typu jest 'FooUID' i który jest zwracany przez wewnętrzne zapytanie w EDIT 2? Nie mam pojęcia, co się dzieje, tylko trochę pogrzebać. –

+0

@mu jest za krótki - 'FooUID' to typ' uuid'. Nie jestem pewien, czy rozumiem drugą część twojego pytania. –

+0

Twoja EDIT 2 mnie zaskoczyła. Musi to być wartość, która nie równa się sama. Jesteś pewny, że wewnętrzna część zwraca nie-NULL 'FooUID'? –

Odpowiedz

2

Co się dzieje, jeśli przepisać to z nie istnieje, podobnie jak

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

Wygląda mi znacznie czystsze niż wybierając nogę kończyn z zewnętrznej przyłączyć.

+0

Ponadto, ograniczenie klucza obcego prawdopodobnie uniknie tego bałaganu. – wildplasser

+0

Zabawne, powinieneś wspomnieć, że to ja próbuję usunąć złe dane, aby dodać klucze obce. –

+0

Gheghe. Spróbuj dodać nazwę korelacji do podkwerendy. Może ktoś wpadł w zakłopotanie, widząc dwa filmy. Możesz także sprawdzić plany wuery (przydatne są tam również nazwy korelacji) – wildplasser

Powiązane problemy