2013-07-16 4 views
17

ero confuso dietro il ragionamento della seguenti:Perché PostgreSQL non restituiscono valori nulli quando la condizione è <> vero

SELECT * FROM table WHERE avalue is null 

Restituisce x numero di righe in cui 'Avalue' è nullo

SELECT * FROM table WHERE avalue <> true 

non righe di ritorno in cui 'valore' è nullo.

mio ragionamento (che sembra essere errata) è che null è un valore unico (non è nemmeno uguale a null) significa che dovrebbe mostrare nel set di risultati non è uguale a true entrambi.

Immagino che si possa sostenere che dicendo column <> value si implichi che la colonna abbia un valore, ignorando quindi i valori null del tutto.

Qual è il ragionamento alla base di questo ed è lo stesso in altri DB SQL comuni?

Il mio ragionamento (ipotesi) mi dice che questo è contro-intuitivo e volevo sapere perché.

+8

[Tre valori logica] (http://en.wikipedia.org/wiki/Three-valued_logic). Supponi che le uniche risposte possibili a '<>' siano 'true' o' false' - mentre in SQL, c'è l'opzione di 'unknown'. Questo è negli standard. (Confusamente, MySQL confonde 'UNKNOWN' e' NULL' così là, i possibili risultati sono 'TRUE',' FALSE' e 'NULL') –

+1

SQL Server lo fa allo stesso modo. – Fanda

+0

Come dice Damien ... Questo è comunemente chiamato la logica dei tre valori. – Kuberchaun

risposta

27

Ogni decente RDBMS lo fa allo stesso modo, perché è corretto .
Sto citando the Postgres manual here:

operatori di confronto ordinarie rendimento nullo (che significa "sconosciuto"), non vero o falso, quando uno di ingresso è nullo. Ad esempio, 7 = NULL restituisce null, così come 7 <> NULL.Quando questo comportamento non è adatto, utilizzare i IS [ NOT ] DISTINCT FROM costrutti:

expression IS DISTINCT FROM expression 
expression IS NOT DISTINCT FROM expression 

Si noti che queste espressioni di eseguire un po 'più lento di semplice confronto expression <> expression.

Per i valori boolean c'è anche il più semplice IS NOT [TRUE | FALSE].
per ottenere quello che ci si attende in vostra seconda query, scrivere:

SELECT * FROM table WHERE avalue IS NOT TRUE;

SQL Fiddle.

+0

IMHO, questa è una logica imperfetta e non "corretta". Se confronto 7 con NULL, la risposta non dovrebbe essere sconosciuta, la risposta dovrebbe essere falsa. Questa è la logica di piegatura SQL. Comunque, grazie per l'ottima risposta, il 'IS DISTINCT FROM' ha salvato la giornata. – sandre89

+1

@ sandre89 Il problema è che non è possibile definire un operatore che combini o confronti NULL (o "sconosciuto") con qualcos'altro. Quale dovrebbe essere il risultato per '7> NULL' o' 7 NULL' non ha senso, e il risultato è quindi sconosciuto (che è rappresentato come' NULL'). –

+0

@WizardofOgz Sono d'accordo che 7> NULL non ha senso. Ma 7 <> NULL è vero e non c'è modo di aggirarlo: è diverso. Allo stesso modo 7 = NULL dovrebbe essere falso. – sandre89

2

È normale. SQL Server lo fa allo stesso modo. In SQL Server è possibile utilizzare

SELECT * FROM table WHERE ISNULL(avalue, 0) <> 1 

per PostgreSQL equivalente guardare questo: What is the PostgreSQL equivalent for ISNULL()

considerare di usare specifica colonna NOT NULL con valore di default, se ha un senso.

MODIFICA:

Penso che sia logica. NULL non è un valore, quindi è escluso dalla ricerca - devi specificarlo esplicitamente. Se i progettisti SQL decidono di passare in secondo piano (includi automaticamente i valori null), si avranno più problemi se non si devono riconoscere valori

4

This link fornisce una panoramica utile. In modo efficace come sottolinea @Damien_The_Unbeliever, utilizza la logica a tre valori e sembra essere (secondo l'articolo) l'argomento del dibattito.

È possibile trovare un paio di altri collegamenti validi here e here.

Penso che si riduce a null non essendo un valore, ma un segnaposto per un valore e una decisione doveva essere presa e questo era ... quindi NULL non è uguale a nessun valore perché non lo è un valore e nemmeno non sarà uguale a nessun valore .... se questo ha un senso.

+0

L'articolo in simple-talk contiene un errore con la tabella AND. Dichiara che "falso E sconosciuto è sconosciuto" quando dovrebbe essere "falso E sconosciuto è falso". Allo stesso modo con "sconosciuto e falso", dovrebbe essere "falso". Questo è discusso nei commenti dell'articolo ma l'articolo non è stato aggiornato. – mangoDrunk