2011-09-11 11 views
6

La siguiente consulta devuelve 2036 filas:estoy loco: PostgreSQL en el operador con la consulta anidada devolver resultados inesperados

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 

Pero la siguiente declaración única actualizado 1870 filas:

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 
) 

cómo es esto posible ?

EDITAR 1: La primera consulta continúa generando 166 filas, y la segunda sigue actualizando 0 filas.

EDIT 2:

En lo siguiente, la consulta anidada devuelve una fila que contiene un UID, pero la consulta externa devuelve 0 filas.

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 
) 

Am I crazy?

Datos 3:

la siguiente declaración, proporcionada por @wildplasser tuvo éxito en la actualización de las filas restantes 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" 
) 

Sin embargo, todavía no entiendo por qué el original no se recuperó hacia arriba. Si la consulta anidada se seleccionó 166 "FooUID" s, ¿por qué no deberían coincidir con las filas en la tabla "Foo" utilizando IN?

EDITAR 4: El más lo pienso, este fondo podría ser importante:

Todo esto tuvo lugar en un servidor de bases de datos que ha sido recientemente clonado a partir de otro. Hablé con el técnico de TI que hizo la clonación, y resulta que no cerró una aplicación que se ejecuta en la parte superior de la base de datos original antes de bajarla para clonarla. Esto significa que la DB probablemente se redujo a mediados de la transacción (no sé cómo desvergonzadamente). ¿Es posible que algo en la base de datos se haya quedado corrupto, lo que me lleva a ver estas filas fantasmas?

Lamentablemente ya no puedo reproducirlo, ya que ejecuta la solución de wildplasser. La base de datos original (para volver a abrir la aplicación y servirla) no contiene ninguno de los datos no válidos que estaba tratando de corregir en la copia, y mucho menos ningún rastro de los chanchullos que presencié.

Debo mencionar que antes de ejecutar la revisión, he reducido el problema a lo absurdo más básico: La primera vez seleccionada la FooUID de la consulta anidada en Editar 2, copiado en el portapapeles, y luego corrió una consulta seleccionando de Foo donde FooUID igualó el valor pegado - este todavía devolvió 0 filas.

+0

¿Qué tipo es 'FooUID' y cuál es devuelto por la consulta interna en EDIT 2? Ni idea de lo que está pasando todavía, solo hurgando un poco. –

+0

@mu es demasiado corto - 'FooUID' es tipo' uuid'. Sin embargo, no estoy seguro de entender la segunda parte de tu pregunta. –

+0

Tu EDIT 2 me ha dejado perplejo. Debe ser un valor que no se compare igual a sí mismo. ¿Estás seguro? ¿La parte interna está devolviendo un 'FooUID' no NULL? –

Respuesta

2

¿Qué pasa si vuelve a escribir esto con no existen, como

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

se ve mucho más limpio para mí que la selección de la pierna extremidad de una combinación externa.

+0

Además, una restricción de clave externa probablemente evitaría este desastre. – wildplasser

+0

Es curioso que lo menciones, este soy yo tratando de limpiar los datos incorrectos para agregar claves foráneas. –

+0

Gheghe. Intente agregar un nombre de correlación a la subconsulta. Quizás alguien se confundió al ver los dos foos. También puede consultar los planes de wuery (los nombres de las correlaciones también son útiles) – wildplasser

Cuestiones relacionadas