2012-07-28 14 views
10

Me encontré con un caso en el que una consulta sqlite que esperaba devolver un error realmente está teniendo éxito y me preguntaba si alguien podría señalar por qué esta consulta es válida .unión todo con consultas que tienen un número diferente de columnas

CREATE TABLE test_table(
    k INTEGER, 
    v INTEGER 
); 

INSERT INTO test_table(k, v) VALUES(4, 5); 

SELECT * FROM(
    SELECT * FROM(
    SELECT k, v FROM test_table WHERE 1 = 0 
) 
    UNION ALL 
    SELECT * FROM(
    SELECT rowid, k, v FROM test_table 
) 
) 

sqlfiddle of above

Me gustaría pensar que unificante dos casillas que tienen un número diferente de columnas devolvería un error. Si elimino el SELECT * más externo, recibo el error que esperaba: SELECTs to the left and right of UNION ALL do not have the same number of result columns.

+0

Parece que una peculiaridad en SQLite! – Andomar

+0

Raro, y ¿qué devuelve? NULLs para la columna faltante –

+0

Oh, verifiqué la demostración y omite la columna. –

Respuesta

10

La respuesta a esto parece ser simple: Sí, esto es un capricho. Me gustaría demostrar esto con un breve ejemplo. Pero antes, vamos a consultar la documentation:

Dos o más sencillas instrucciones SELECT pueden conectarse entre sí para formar un compuesto seleccionar usando la UNION, UNION ALL, INTERSECT o EXCEPT operador. En un compuesto SELECT, todos los SELECTs constituyentes deben devolver la misma cantidad de columnas de resultados.

Por lo que la documentación dice muy claramente que dos SELECTs deben proporcionar el mismo número de columnas. Sin embargo, como dijiste, el extremo SELECT extrañamente evita esta 'limitación'.

Ejemplo 1

SELECT * FROM(
    SELECT k, v FROM test_table 
    UNION ALL 
    SELECT k, v,rowid FROM test_table 
); 

Resultado:

k|v 
4|5 
4|5 

La tercera columna rowid consigue simplemente se omite, como se ha señalado en los comentarios.

Ejemplo 2

Sólo están cambiando el orden de las dos sentencias de selección.

SELECT * FROM(
    SELECT k, v, rowid FROM test_table 
    UNION ALL 
    SELECT k, v FROM test_table 
); 

Resultado

k|v|rowid 
4|5|1 
4|5| 

Ahora, sqlite no omite la columna además de añadir un valor nulo.

Conclusión

Esto me lleva a mi conclusión, que sqlite simplemente se encarga de la UNION ALL diferente si se procesa como una subconsulta.

PD: Si solo está utilizando UNION falla en cualquier situación.

7

UNION ALL devolverá los resultados con valores nulos en las columnas adicionales.

Un UNION básico fallará porque UNION sin el TODO debe tener el mismo número de columnas en ambas tablas.

Así:

SELECT column1, column2 FROM table a 
UNION ALL 
SELECT column1, column2, column3 FROM table b 

retornos 3 columnas con valores nulos en la columna 3.

y:

SELECT column1, column2 FROM table a 
UNION 
SELECT column1, column2, column3 FROM table b 

debe fallar porque el número de columnas no coinciden.

En conclusión, podría agregar una columna en blanco a la UNIÓN para que esté seleccionando 3 columnas de cada tabla y aún así funcionaría.

EX:

SELECT column1, column2, '' AS column3 FROM table a 
UNION 
SELECT column1, column2, column3 FROM table b 
+0

buen enfoque !! –

Cuestiones relacionadas