2011-11-07 9 views
24

Questa è solo una domanda per curiosità, ma sto guardando un database e estraendo dati da una tabella con una query su una delle colonne. La colonna ha quattro possibili valori null, 0, 1, 2. Quando eseguo la query come:SQL non visualizza valori nulli su una query non uguale a?

SELECT * FROM STATUS WHERE STATE != '1' AND STATE != '2'; 

ottengo gli stessi risultati di esecuzione:

SELECT * FROM STATUS WHERE STATE = '0'; 

vale a dire le righe con un valore nullo nel comando superiore nella colonna interrogata sembrano essere omesse dai risultati, avviene sempre in SQL?

Sto eseguendo i miei comandi tramite Oracle SQL Developer.

+4

"questo accade sempre in SQL?" - Risposta breve: no. SQL presenta [logica a tre valori (3VL)] (http: //en.wikipedia.org/wiki/Tre-valued_logic). Dico "mostre" molto volutamente perché le specifiche per il 3VL di SQL sono incoerenti e incomplete. Devi semplicemente imparare tutti i casi limite. L'approccio migliore IMO è di evitare i null in SQL. – onedaywhen

+1

So che questo non aggiunge intuizione, ma il 'OR 'dovrebbe essere un' AND'? – user123444555621

+0

Da quello che posso ricordare quando stavo facendo questo averlo come O è corretto, io volevo solo STATE 0 righe, ma stavo anche ottenendo NULL rows. Non ero a conoscenza della logica a tre valori come descrive @Vash nella sua risposta. Avrei dovuto usare STATE NOT IN ('1', '2') come indicato da Michael Durrant. Il mio SQL è molto meglio di allora era lol. –

risposta

20

In diverse lingue NULL viene gestito in modo diverso: la maggior parte delle persone conosce la logica a due valori in cui true e false sono gli unici valori confrontabili in ex booleano pressioni (anche false è definito come 0 e vero come qualsiasi altra cosa).

In SQL standard è necessario pensare a three-valued logic. NULL non è considerato come un valore reale, potresti piuttosto chiamarlo "sconosciuto". Quindi, se il valore è sconosciuto, non è chiaro se nel tuo caso state è 0, 1 o qualsiasi altra cosa. Quindi risultati NULL != 1 a NULL di nuovo.

Questo conclude che ogni volta che si filtra qualcosa che potrebbe essere NULL, è necessario trattare i valori NULL da soli. Notare che la sintassi è diversa: i valori NULL possono essere confrontati solo con x IS NULL anziché x = NULL. Vedi Wikipedia per una tabella di verità che mostra i risultati delle operazioni logiche.

+0

Vedo, evviva la risposta rapida Vash :) Lo terrò sicuramente a mente in futuro. –

+1

Penso che allo stackexchange riceverai risposte molto veloci in generale. Se provi a rispondere alle tue domande, scoprirai che è difficile trovare una domanda senza risposta a cui sei in grado di rispondere e che vuoi rispondere. Comunque anche questa è stata una risposta breve, e ora che sono a casa lo aggiornerò anch'io, per riflettere la logica a tre valori. – Alex

7

Yest è normale, si può forse mettere un impostazioni del database a fisso che

ma si potrebbe modificare il codice e fare qualcosa di simile:

SELECT * FROM STATUS WHERE STATE != '1' OR STATE != '2' or STATE is null; 

Guardate questo per ulteriori informazioni: http://www.w3schools.com/sql/sql_null_values.asp

3

più or con where possono diventare rapidamente difficili da leggere e incerti sui risultati.

Vorrei raccomandare una parentesi aggiuntiva più l'uso dell'istruzione IN (NOT IN in questo caso), ad es.

SELECT * FROM STATUS WHERE (STATE NOT IN ('1', '2')) or STATE is null;

Implmentations possono variare tra fornitore del database ma quanto sopra sintassi esplicita dovrebbe rendere sicuri dei risultati.

0

ho creato script per research Oracle comportamento:

create table field_values 
(
is_user_deletable VARCHAR2(1 CHAR), 
resource_mark VARCHAR2(3 CHAR) 
) 

insert into field_values values (NULL, NULL); 
insert into field_values values ('Y', NULL); 
insert into field_values values ('N', NULL); 

select * from field_values; -- 3 row 

-- 1 row, bad 
update field_values set resource_mark = 'D' where is_user_deletable = 'Y'; 
update field_values set resource_mark = 'D' where is_user_deletable <> 'N'; 
update field_values set resource_mark = 'D' where is_user_deletable != 'N'; 
update field_values set resource_mark = 'D' where is_user_deletable not in ('Y'); 

-- 2 rows, good, but needs more SQL and more comparisons. Does DB optimizes? 
update field_values set resource_mark = 'D' where is_user_deletable = 'N' or is_user_deletable is null; 

-- it better to have ('Y' and NULL) or ('N' and NULL), but not 'Y' and 'N' and NULL (avoid quires with https://en.wikipedia.org/wiki/Three-valued_logic) 
-- adding new column which is 'Y' or 'N' only into existing table may be very long locking operation on existing table (or running long DML script) 

0

uso NVL in questo modo: SELECT * FROM STATUS WHERE NVL(STATE,'X') != '1' AND NVL(STATE,'X')!= '2';