2012-07-28 21 views
10

Ho incontrato un caso in cui una query sqlite che mi aspetto di restituire un errore è effettivamente valida e mi chiedevo se qualcuno potesse indicare perché questa query è valida .unione tutte con query con un diverso numero di colonne

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

penserei che unioning due selezionano che hanno un diverso numero di colonne restituirebbe un errore. Se rimuovo il più esterno SELECT *, ricevo l'errore che mi aspetto: SELECTs to the left and right of UNION ALL do not have the same number of result columns.

+0

Sembra una stranezza nel SQLite! – Andomar

+0

Strano - e cosa restituisce? NULL per la colonna mancante? –

+0

Oh ho controllato la demo e omette la colonna. –

risposta

10

La risposta a questo sembra essere semplice: Sì, questa è una stranezza. Vorrei dimostrarlo con un breve esempio. Ma prima, andiamo a consultare il documentation:

due o più semplici istruzioni SELECT possono essere collegati insieme per formare un composto selezionare usando l'UNION, UNION ALL, INTERSECT o EXCEPT dell'operatore. In un composto SELECT, tutti i SELECTs costitutivi devono restituire lo stesso numero di colonne di risultati.

Quindi la documentazione dice molto chiaramente che due SELECTs devono fornire lo stesso numero di colonne. Tuttavia, come hai detto, il più esterno SELECT evita stranamente questa "limitazione".

Esempio 1

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

risultati:

k|v 
4|5 
4|5 

La terza colonna rowid ottiene semplicemente omesso, come evidenziato nei commenti.

Esempio 2

Siamo solo commutazione l'ordine delle due istruzioni SELECT.

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

Risultato

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

Ora, SQLite non omettere la colonna, ma aggiungere un valore nullo.

Conclusione

Questo mi porta alla mia conclusione, che SQLite gestisce semplicemente il UNION ALL in modo diverso se viene elaborato come una sottoquery.

PS: Se si utilizza solo UNION non riesce in qualsiasi scenario.

7

UNION ALL restituirà i risultati con valori null nelle colonne aggiuntive.

Un'UNIONE di base non riuscirà perché UNION senza ALL deve avere lo stesso numero di colonne da entrambe le tabelle.

Quindi:

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

restituisce 3 colonne con valori nulli nella colonna 3.

e:

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

dovrebbe fallire a causa del numero di colonne non corrispondono.

In conclusione, è possibile aggiungere una colonna vuota all'UNION in modo da selezionare 3 colonne da ogni tabella e funzionerebbe comunque.

EX:

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

buon approccio !! –

Problemi correlati