Perché NULL = NULL viene valutato come falso in SQL Server


147

Nel server SQL se si dispone nullParam=NULLdi una clausola where, viene sempre considerato falso. Questo è controintuitivo e mi ha causato molti errori. Capisco le parole chiave IS NULLe IS NOT NULLsono il modo corretto per farlo. Ma perché il server SQL si comporta in questo modo?


166
Non ho una sorella, e nemmeno il mio amico. Se "NULL = NULL" allora abbiamo una sorella comune e quindi siamo imparentati! :)
Matt Hamilton,

11
Esiste una lunga controversia sui NULL SQL (vedere ad esempio: en.wikipedia.org/wiki/Null_%28SQL%29#Controversy e firstsql.com/inulls.htm ). Il punto specifico qui è che l'uguaglianza è un concetto matematico consolidato da tempo e SQL lo viola - l'uguaglianza è riflessiva: per ogni x, x = x. Questo deve essere sempre vero, altrimenti si sta introducendo un'interpretazione dell'uguaglianza che non è standard e la confusione è il risultato ovvio.
MaD70,

14
Non viola affatto la matematica. Sto pensando a due numeri. Non ho intenzione di dirti cosa sono però. Quindi ora mi dici, sono uguali?
Tom H,

10
@Matt, non sono d'accordo con la tua analogia. NULL = NULL non significherebbe che hai una sorella comune, vorrebbe dire che a entrambi manca una sorella.
reustmd

5
@ manu08 No, l'attuale implementazione (che NULL non è mai uguale a NULL) significa che a entrambi manca una sorella, che era il mio punto.
Matt Hamilton,

Risposte:


206

Pensa al null come "sconosciuto" in quel caso (o "non esiste"). In nessuno di questi casi, non si può dire che siano uguali, perché non si conosce il valore di nessuno di essi. Quindi, null = null viene valutato come non vero (false o null, a seconda del sistema), perché non si conoscono i valori per dire che SONO uguali. Questo comportamento è definito nello standard ANSI SQL-92.

EDIT: dipende dall'impostazione di ansi_nulls . se hai ANSI_NULLS disattivato, questo VALUTA come vero. Esegui il seguente codice per un esempio ...

set ansi_nulls off

if null = null
    print 'true'
else
    print 'false'


set ansi_nulls ON

if null = null
    print 'true'
else
    print 'false'

11
x = x è valido solo quando x è un valore noto . NULL è una rappresentazione testuale di un valore sconosciuto . Se hai due valori sconosciuti, non puoi affermare in modo conclusivo nulla sulla loro uguaglianza. Credo che ciò sia vero anche da alcuni secoli.
Dewayne Christensen,

4
Dato che è dicembre, usiamo un esempio stagionale. Ho due regali sotto l'albero. Ora, dimmi se ne ho due o meno della stessa cosa.
Dewayne Christensen,

5
SQL NULL non è diverso dal NaN in virgola mobile IEEE, dove hai anche (NaN == NaN) == false && (NaN != Nan) == false && (NaN < NaN) == false && ...- perché, beh, se non è un numero, non puoi dire molto al riguardo; è qualcosa di sconosciuto. Il concetto è valido, anche se non intuitivo per le persone che non l'hanno mai visto prima.
Pavel Minaev il

8
Qui non c'è violazione della riflessività, perché NULL non è un membro dell'insieme di valori (dominio, in termini relazionali). NULL non è un valore . È un segnaposto per il valore sconosciuto.
Pavel Minaev il

9
Per dirla in altre parole, ogni NULLespressione di SQL può essere trattata come una variabile matematica distinta . Quindi un'espressione NULL = NULLdovrebbe essere trattata come x = y, dove xe ysono variabili non associate. Ora, se qualcuno ti chiede, qual è il valore di x = y? L'unica risposta ragionevole è "alcuni z". Così abbiamo (x = y) = z- o, trascrivere di nuovo a SQL, (NULL = NULL) = NULL.
Pavel Minaev il

131

Quanti anni ha Frank? Non lo so (null).

Quanti anni ha Shirley? Non lo so (null).

Frank e Shirley hanno la stessa età?

La risposta corretta dovrebbe essere "Non lo so" (null), non "no", dato che Frank e Shirley potrebbero avere la stessa età, semplicemente non lo sappiamo.


4
Non sono d'accordo sul fatto che null significhi "sconosciuto". Ciò che significa in realtà è "nessun dato". Potrebbe essere usato per rappresentare il caso in cui le informazioni non sono note, ma in realtà è più probabile che vengano utilizzate per indicare che qualcosa non esiste. Per continuare il tuo esempio: qual è il secondo nome di Frank? Non ne ha uno (null). Qual è il secondo nome di Shirley? Lei non ne ha uno (null). Frank e Shirley hanno lo stesso secondo nome? Sì? No? Non lo so? Riesco a vedere un argomento per "no", e posso vedere un argomento per "non so", ma non esiste un vero argomento per "sì" a meno che tu non sia troppo letterale.
Richiban,

2
@richiban Non sono d'accordo. La mancanza di esistenza di una riga significa "nessun dato"
Neil McGuigan,

1
@NeilMcGuigan Questo è vero se per i dati che hanno una propria tabella, ma che dire dei dati rappresentati in una colonna? Non useresti "null" per rappresentare il fatto che i dati non esistono? "Non noto" è un motivo molto specifico per l'assenza dei dati.
Richiban

3
Ma null = nullcede FALSE, no NULL.
slartidan

1
@slartidan Sono d'accordo con te, tuttavia non è corretto
Neil McGuigan

28

Spero di chiarire qui la mia posizione.

Quello NULL = NULL valutare FALSEè sbagliato. Hacker e Mister hanno risposto correttamente NULL. Ecco perché. Dewayne Christensen mi ha scritto, in un commento a Scott Ivey :

Dato che è dicembre, usiamo un esempio stagionale. Ho due regali sotto l'albero. Ora, dimmi se ne ho due o meno della stessa cosa.

Possono essere diversi o possono essere uguali, non si sa fino a quando non si aprono entrambi i regali. Chissà? Hai invitato due persone che non si conoscono ed entrambe ti hanno fatto lo stesso dono - raro, ma non impossibile § .

Quindi la domanda: questi due UNKNOWN presentano gli stessi (uguale, =)? La risposta corretta è: SCONOSCIUTO (cioè NULL).

Questo esempio aveva lo scopo di dimostrare che ".. ( falseo null, a seconda del sistema) .." è una risposta corretta - non lo è, è corretto solo NULL in 3VL (o è accettabile accettare un sistema che fornisce risposte sbagliate? )

Una risposta corretta a questa domanda deve sottolineare questi due punti:

  • la logica a tre valori (3VL) è controintuitiva (vedere innumerevoli altre domande su questo argomento su Stackoverflow e in altri forum per essere sicuri);
  • I DBMS basati su SQL spesso non rispettano nemmeno i 3VL, a volte danno risposte errate (come afferma il poster originale, in questo caso SQL Server fa).

Quindi ribadisco: SQL non serve a nulla forzare l'interpretazione della proprietà riflessiva dell'uguaglianza, che afferma che:

for any x, x = x §§ (in parole povere : qualunque sia l'universo del discorso, una "cosa" è sempre uguale a se stessa ).

.. in un 3VL ( TRUE, FALSE, NULL). L'aspettativa delle persone sarebbe conforme a 2VL ( TRUE, FALSEche anche in SQL è valido per tutti gli altri valori), vale a dire x = x sempre valutare TRUE , per ogni possibile valore di x - nessuna eccezione.

Si noti inoltre che i NULL sono " non valori " validi (come i loro apologeti fingono di essere) che si possono assegnare come valori di attributo (??) come parte delle variabili di relazione. Quindi sono valori accettabili di ogni tipo (dominio), non solo del tipo di espressioni logiche.

E questo era il mio punto :, NULLcome valore, è una "strana bestia". Senza eufemismo, preferisco dire: sciocchezze .

Penso che questa formulazione sia molto più chiara e meno discutibile - mi dispiace per la mia scarsa conoscenza della lingua inglese.

Questo è solo uno dei problemi dei NULL. Meglio evitarli del tutto, quando possibile.

§ siamo preoccupati per i valori qui, quindi il fatto che i due presenti siano sempre due diversi oggetti fisici non è un'obiezione valida; se non sei convinto mi dispiace, non è questo il posto per spiegare la differenza tra valore e semantica "oggetto" (Algebra relazionale ha semantica valore dall'inizio - vedi il principio informativo di Codd; penso che alcuni implementatori di SQL DBMS don ti interessa anche una semantica comune).

§§ a mia conoscenza, questo è un assioma accettato (in una forma o nell'altra, ma sempre interpretato in un 2VL) fin dall'antichità e esattamente perché è così intuitivo. 3VLs (in realtà è una famiglia di logiche) è uno sviluppo molto più recente (ma non sono sicuro di quando sia stato sviluppato per la prima volta).

Nota a margine: se qualcuno introdurrà i tipi Bottom , Unit e Option come tentativi di giustificare i NULL SQL, sarò convinto solo dopo un esame abbastanza dettagliato che mostrerà come le implementazioni SQL con i NULL abbiano un sistema di tipi sonori e chiarirà, infine, cosa sono realmente i NULL (questi "valori-non-piuttosto-valori").


Di seguito citerò alcuni autori. Qualsiasi errore o omissione è probabilmente mio e non degli autori originali.

Joe Celko su SQL NULLs

Vedo Joe Celko spesso citato su questo forum. Apparentemente è un autore molto rispettato qui. Quindi, mi sono detto: "che cosa ha scritto sui NULL SQL? Come spiega i numerosi problemi dei NULL?". Uno dei miei amici ha una versione ebook dell'SQL di Joe Celko per gli smarties: programmazione SQL avanzata, 3a edizione . Vediamo.

Innanzitutto, il sommario. La cosa che mi colpisce di più è il numero di volte in cui viene menzionato NULL e nei contesti più svariati:

3.4 Aritmetica e NULL 109
3.5 Conversione di valori da e verso NULL 110
3.5.1 Funzione NULLIF () 110
6 NULL: dati mancanti in SQL 185
6.4 Confronto di NULL 190
6.5 NULL e logica 190
6.5.1 NULL nei predicati di sottoquery 191
6.5.2 Standard SQL Solutions 193
6.6 Math e NULL 193
6.7 Funzioni e NULL 193
6.8 NULL e lingue host 194
6.9 Consigli di progettazione per NULL 195
6.9.1 Evitare NULL dai programmi host 197
6.10 Una nota su più valori NULL 198
10.1 Predicato IS NULL 241
10.1. 1 Fonti di NULL 242
...

e così via. Mi suona "un brutto caso speciale".

Esaminerò alcuni di questi casi con estratti di questo libro, cercando di limitarmi all'essenziale, per motivi di copyright. Penso che queste citazioni rientrino nella dottrina del "fair use" e possano persino stimolare l'acquisto del libro - quindi spero che nessuno si lamenterà (altrimenti dovrò cancellarne la maggior parte, se non tutte). Inoltre, mi asterrò dal segnalare frammenti di codice per lo stesso motivo. Mi dispiace per quello. Acquista il libro per leggere il ragionamento basato sui dati.

I numeri di pagina tra parentesi in quanto segue.

Vincolo NOT NULL (11)

Il vincolo di colonna più importante è NOT NULL, che proibisce l'uso di NULL in una colonna. Usa questo vincolo di routine e rimuovilo solo quando hai buone ragioni. Ti aiuterà a evitare le complicazioni dei valori NULL quando esegui query sui dati.

Non è un valore ; è un marcatore che detiene un posto dove potrebbe andare un valore.

Ancora una volta questa assurdità "di valore ma non proprio di valore". Il resto mi sembra abbastanza sensato.

(12)

In breve, i NULL causano molte funzionalità irregolari in SQL, di cui parleremo più avanti. La tua scommessa migliore è solo quella di memorizzare le situazioni e le regole per i NULL quando non puoi evitarli.

A proposito di SQL, NULL e infinito:

(104) CAPITOLO 3: DATI NUMERICI IN SQL

SQL non ha accettato il modello IEEE per la matematica per diversi motivi.

...

Se le regole IEEE per la matematica fossero consentite in SQL, avremmo bisogno di digitare le regole di conversione per infinito e un modo per rappresentare un valore numerico esatto infinito dopo la conversione. Le persone hanno abbastanza problemi con i NULL, quindi non andiamo lì.

Implementazioni SQL indecise su cosa significhi davvero NULL in contesti particolari:

3.6.2 Funzioni esponenziali (116)

Il problema è che i logaritmi non sono definiti quando (x <= 0). Alcune implementazioni SQL restituiscono un messaggio di errore, alcune restituiscono un NULL e DB2 / 400; la versione 3 rilascio 1 ha restituito * NEGINF (abbreviazione di "infinito negativo") come risultato.

Joe Celko cita David McGoveran e CJ Date:

6 NULL: dati mancanti in SQL (185)

Nel loro libro A Guide to Sybase e SQL Server , David McGoveran e CJ Date hanno dichiarato: “È opinione di questo scrittore che i NULL, almeno come attualmente definiti e implementati in SQL, siano molto più problematici di quanto valgono e dovrebbero essere evitati; mostrano un comportamento molto strano e incoerente e possono essere una ricca fonte di errore e confusione. (Si noti che questi commenti e critiche si applicano a qualsiasi sistema che supporti NULL in stile SQL, non solo a SQL Server in particolare.) "

NULL come tossicodipendenza :

(186/187)

Nel resto di questo libro, ti esorto a non usarli , il che può sembrare contraddittorio, ma non lo è. Pensa a un NULL come a una droga; usalo correttamente e funziona per te, ma abusalo e può rovinare tutto. La tua migliore politica è di evitare i NULL quando puoi e di usarli correttamente quando devi.

La mia unica obiezione qui è "usarli correttamente", che interagisce male con comportamenti di implementazione specifici.

6.5.1 NULL nei predicati della sottoquery (191/192)

Le persone dimenticano che una sottoquery spesso nasconde un confronto con un NULL. Considera queste due tabelle:

...

Il risultato sarà vuoto. Questo è controintuitivo , ma corretto.

(separatore)

6.5.2 Soluzioni SQL standard (193)

SQL-92 ha risolto alcuni dei problemi di 3VL (logica a tre valori) aggiungendo un nuovo predicato del modulo:

<condizione di ricerca> È [NON] VERO | FALSO | SCONOSCIUTO

Ma SCONOSCIUTO è una fonte di problemi in sé, quindi CJ Date, nel suo libro citato di seguito, lo consiglio nel capitolo 4.5. Evitare i null in SQL :

  • Non utilizzare la parola chiave SCONOSCIUTA in nessun contesto.

Leggi "DA PARTE" su SCONOSCIUTO, anch'esso collegato di seguito.

6.8 NULL e lingue host (194)

Tuttavia, è necessario sapere come vengono gestiti i NULL quando devono essere passati a un programma host. Nessuna lingua host standard per la quale è definito un incorporamento supporta i NULL, che è un'altra buona ragione per evitare di usarli nello schema del database.

(separatore)

6.9 Consigli di progettazione per NULL (195)

È consigliabile dichiarare tutte le tabelle di base con vincoli NOT NULL su tutte le colonne quando possibile. I NULL confondono le persone che non conoscono SQL e i NULL sono costosi.

Obiezione: i NULL confondono anche le persone che conoscono bene SQL, vedi sotto.

(195)

I NULL dovrebbero essere evitati nei TASTI ESTERI. SQL consente questa relazione "beneficio del dubbio", ma può causare una perdita di informazioni nelle query che coinvolgono join. Ad esempio, dato un codice del numero di parte nell'inventario a cui viene fatto riferimento come CHIAVE ESTERA da una tabella Ordini, si verificheranno problemi nell'ottenere un elenco delle parti che hanno un valore NULL. Questa è una relazione obbligatoria; non è possibile ordinare una parte che non esiste.

(separatore)

6.9.1 Evitare NULL dai programmi host (197)

È possibile evitare di inserire NULL nel database dai programmi host con una certa disciplina di programmazione.

...

  1. Determinare l'impatto dei dati mancanti sulla programmazione e sul reporting: le colonne numeriche con NULL rappresentano un problema, poiché le query che utilizzano funzioni aggregate possono fornire risultati fuorvianti.

(separatore)

(227)

SUM () di un set vuoto è sempre NULL. Uno degli errori di programmazione più comuni commessi durante l'utilizzo di questo trucco è quello di scrivere una query che potrebbe restituire più di una riga. Se non ci pensassi, potresti aver scritto l'ultimo esempio come: ...

(separatore)

10.1.1 Fonti di NULL (242)

È importante ricordare dove possono verificarsi NULL. Sono più di un semplice valore in una colonna . Le funzioni aggregate su insiemi vuoti, OUTER JOIN, espressioni aritmetiche con NULL e operatori OLAP restituiscono tutti NULL. Questi costrutti si presentano spesso come colonne in VISUALIZZAZIONI.

(separatore)

(301)

Un altro problema con i NULL si trova quando si tenta di convertire i predicati IN in predicati EXISTS.

(separatore)

16.3 Le funzioni ALL Predicate ed Extrema (313)

All'inizio è controintuitivo che questi due predicati non siano gli stessi in SQL:

...

Ma devi ricordare le regole per le funzioni extrema: eliminano tutti i NULL prima di restituire i valori maggiori o minimi. Il predicato ALL non elimina i NULL, quindi è possibile ottenerli nei risultati.

(separatore)

(315)

Tuttavia, la definizione nello standard è formulata in negativo, in modo che i NULL ottengano il beneficio del dubbio. ...

Come puoi vedere, è una buona idea evitare NULL nei vincoli UNIQUE.

Discussing GROUP BY:

I NULL vengono considerati come se fossero tutti uguali tra loro e formano il proprio gruppo. Ogni gruppo viene quindi ridotto a una singola riga in una nuova tabella dei risultati che sostituisce quella precedente.

Ciò significa che per la clausola GROUP BY NULL = NULL non viene valutato come NULL, come in 3VL, ma viene valutato come TRUE.

Lo standard SQL è confuso:

The ORDER BY e NULLs (329)

Se un valore chiave di ordinamento NULL è considerato maggiore o minore di un valore non NULL è definito dall'implementazione, ma ...

... Ci sono prodotti SQL che lo fanno in entrambi i modi.

Nel marzo 1999, Chris Farrar ha sollevato una domanda di uno dei suoi sviluppatori che gli ha fatto esaminare una parte dello standard SQL che pensavo di aver capito . Chris ha riscontrato alcune differenze tra la comprensione generale e la formulazione effettiva delle specifiche .

E così via. Penso che sia abbastanza per Celko.

Data CJ su NULL SQL

CJ Date è più radicale sui NULL: evitare i NULL in SQL, punto. In effetti, il capitolo 4 della sua teoria SQL e relazionale: come scrivere un codice SQL accurato si intitola "NO DUPLICATES, NO NULLS", con i sottocapitoli "4.4 Cosa c'è di sbagliato in Nulls?" e "4.5 Come evitare i null in SQL" (segui il link: grazie a Google Libri, puoi leggere alcune pagine online).

Fabian Pascal su SQL NULLs

Dai suoi problemi pratici nella gestione del database - Un riferimento per il professionista del pensiero (nessun estratto online, mi dispiace):

10.3 Implicazioni pratiche

10.3.1 NULL SQL

... SQL soffre dei problemi inerenti a 3VL, nonché di molte stranezze, complicazioni, controintuitività ed errori reali [10, 11]; tra questi ci sono i seguenti:

  • Le funzioni aggregate (ad es. SUM (), AVG ()) ignorano i NULL (tranne COUNT ()).
  • Un'espressione scalare su una tabella senza righe viene erroneamente valutata su NULL, anziché su 0.
  • L'espressione "NULL = NULL" restituisce NULL, ma in realtà non è valida in SQL; tuttavia ORDER BY considera NULL uguali (qualunque cosa precedano o seguano valori "normali" è lasciato al fornitore DBMS).
  • L'espressione "x IS NOT NULL" non è uguale a "NOT (x IS NULL)", come nel caso di 2VL.

...

Tutti i dialetti SQL implementati commercialmente seguono questo approccio 3VL e, quindi, non solo presentano questi problemi, ma hanno anche problemi di implementazione specifici, che variano tra i prodotti .


4
"E questo era il mio punto: NULL, come valore, è una" strana bestia "." - questo perché NULLnon è un valore.
Pavel Minaev

1
Inoltre, SQL Server non fornisce (NULL = NULL) -> FALSE. Per citare la documentazione per ANSI_NULLS: "Quando si specifica ON, vengono valutati tutti i confronti con un valore nullo SCONOSCIUTI . Se si specifica OFF, i confronti di valori non UNICODE con un valore null vengono valutati in VERO se entrambi i valori sono NULL."
Pavel Minaev

@Pavel Minaev: a) e come VERO è meglio di FALSO? b) Se non è un valore, perché viene assegnato come parte di valori variabili?
MaD70,

1
>> Dato che è dicembre, usiamo un esempio stagionale. Ho due regali sotto l'albero. Ora, dimmi se ne ho due o meno della stessa cosa. ..... sì, hai fatto in quanto hai ottenuto due cose e per quanto ti riguarda in questo momento , nella misura delle tue attuali conoscenze, sono esattamente le stesse per te
Brad Thomas,

3
null = null dovrebbe essere vero. null è un valore ben definito che può rappresentare un valore sconosciuto , ma può anche rappresentare l' assenza di un valore. Spetta allo sviluppatore decidere cosa rappresenta null, ma null stesso è assolutamente un valore e null è null = null. Qualsiasi altra implementazione è destinata al disastro, perché stai interponendo la logica ternaria in predicati fondamentalmente booleani. Sono APPROVATO che questo sta diventando permanente nell'impostazione in SQL Server. OFF OFF OFF con esso.
Triynko,


9

Solo perché non sai cosa sono due cose, non significa che siano uguali. Se quando pensi di NULLpensare a "NULL" (stringa), allora probabilmente vuoi un diverso test di uguaglianza come IS DISTINCT FROMAND di PostgresqlIS NOT DISTINCT FROM

Dai documenti PostgreSQL su "Funzioni e operatori di confronto"

espressione IS DISTINCT FROMespressione

espressione IS NOT DISTINCT FROMespressione

Per input non nulli, IS DISTINCT FROMè uguale <>all'operatore. Tuttavia, se entrambi gli input sono null, restituisce false e se solo un input è null, restituisce true. Allo stesso modo, IS NOT DISTINCT FROMè identico a =per gli input non null, ma restituisce true quando entrambi gli input sono null e false quando un solo input è null. Pertanto, questi costrutti agiscono effettivamente come se null fosse un normale valore di dati, piuttosto che "sconosciuto".


5

Il concetto di NULL è discutibile, per non dire altro. Codd ha introdotto il modello relazionale e il concetto di NULL nel contesto (e ha continuato a proporre più di un tipo di NULL!) Tuttavia, la teoria relazionale si è evoluta dagli scritti originali di Codd: alcune delle sue proposte sono state abbandonate (ad esempio chiave primaria) e altri non hanno mai preso piede (ad es. operatori theta). Nella moderna teoria relazionale (in verità teoria relazionale, dovrei sottolineare) NULL semplicemente non esiste. Vedi il terzo manifesto. http://www.thethirdmanifesto.com/

Il linguaggio SQL presenta il problema della compatibilità con le versioni precedenti. NULL ha trovato la sua strada in SQL e ne siamo bloccati. Probabilmente, l'implementazione di NULLin SQL è imperfetta (l'implementazione di SQL Server rende le cose ancora più complicate a causa della suaANSI_NULLS opzione).

Consiglio di evitare l'uso di colonne NULLable nelle tabelle di base.


Anche se forse non dovrei essere tentato, volevo solo affermare una mia correzione su come NULLfunziona in SQL:

NULL= NULLvaluta UNKNOWN.

UNKNOWN è un valore logico.

NULL è un valore di dati.

Questo è facile da provare ad es

SELECT NULL = NULL

genera correttamente un errore in SQL Server. Se il risultato fosse un valore di dati, ci aspetteremmo di vedere NULL, come alcune risposte qui (erroneamente) suggeriscono che lo faremmo.

Il valore logico UNKNOWNviene trattato in modo diverso rispettivamente in SQL DML e SQL DDL.

In SQL DML, le UNKNOWNrighe vengono rimosse dal gruppo di risultati.

Per esempio:

CREATE TABLE MyTable
(
 key_col INTEGER NOT NULL UNIQUE, 
 data_col INTEGER
 CHECK (data_col = 55)
);

INSERT INTO MyTable (key_col, data_col)
   VALUES (1, NULL);

L' INSERTesito positivo per questa riga, anche se la CHECKcondizione si risolve NULL = NULL. Ciò è dovuto nella norma SQL-92 ("ANSI"):

11.6 definizione del vincolo della tabella

3)

Se il vincolo della tabella è una definizione del vincolo del controllo, allora lascia che SC sia la condizione di ricerca immediatamente contenuta nella definizione del vincolo del controllo e lascia che T sia il nome della tabella incluso nel descrittore del vincolo della tabella corrispondente; il vincolo della tabella non è soddisfatto se e solo se

ESISTE (SELEZIONA * DA T DOVE NON (SC))

è vero.

Leggi di nuovo attentamente, seguendo la logica.

In parole povere, alla nostra nuova riga sopra viene dato il "beneficio del dubbio" sull'essere UNKNOWN e il permesso di passare.

In SQL DML, la regola per la WHEREclausola è molto più semplice da seguire:

La condizione di ricerca viene applicata a ciascuna riga di T. Il risultato della clausola where è una tabella di quelle righe di T per le quali il risultato della condizione di ricerca è vero.

In parole povere, le righe che valutano UNKNOWNvengono rimosse dal gruppo di risultati.


5

Su technet c'è una buona spiegazione di come funzionano i valori null.

Null significa sconosciuto.

Pertanto l'espressione booleana

value = null

non restituisce false, restituisce null, ma se questo è il risultato finale di una clausola where, non viene restituito nulla. Questo è un modo pratico per farlo, poiché tornare a null sarebbe difficile da concepire.

È interessante e molto importante comprendere quanto segue:

Se in una query abbiamo

where (value=@param Or @param is null) And id=@anotherParam

e

  • Valore = 1
  • @param è null
  • id = 123
  • @ AnotherParam = 123

poi

"value = @ param" restituisce null
"@param is null"
restituisce true "id = @ anotherParam" restituisce true

Così diventa l'espressione da valutare

(null O true) E true

Potremmo essere tentati di pensare che qui "null Or true" verrà valutato come null e quindi l'intera espressione diventa null e la riga non verrà restituita.

Non è così. Perché?

Poiché "null Or true" viene valutato su true, il che è molto logico, poiché se un operando è true con l'operatore Or, quindi, indipendentemente dal valore dell'altro operando, l'operazione restituirà true. Pertanto, non importa che l'altro operando sia sconosciuto (null).

Quindi finalmente abbiamo true = true e quindi la riga verrà restituita.

Nota: con la stessa logica cristallina che "null O true" restituisce true, "null And true" restituisce null.

Aggiornamento:
Ok, solo per completarlo voglio aggiungere anche qui il resto, il che risulta abbastanza divertente in relazione a quanto sopra.

"null Or false" restituisce null, "null And false" restituisce false. :)

La logica è ovviamente ancora evidente come prima.


4

Perché NULLsignifica "valore sconosciuto" e due valori sconosciuti non possono essere uguali.

Quindi, se per la nostra logica NULLN ° 1 è uguale a NULLN ° 2, allora dobbiamo dire che in qualche modo:

SELECT 1
WHERE ISNULL(nullParam1, -1) = ISNULL(nullParam2, -1)

dove il valore noto -1N ° 1 è uguale a -1N ° 2


nullParam1 = -1e l' nullParam2 =NULLincidente aereo dovrebbe essereISNULL(NULLIF(@nullParam1, @nullParam2), NULLIF(@nullParam2, nullParam1)) IS NULL
Selvin,

4

Le risposte qui sembrano provenire da una prospettiva CS, quindi voglio aggiungerne una dal punto di vista degli sviluppatori.

Per uno sviluppatore NULL è molto utile. Le risposte qui dicono che NULL significa sconosciuto, e forse nella teoria CS è vero, non ricordo, è passato un po 'di tempo. Nello sviluppo reale, tuttavia, almeno nella mia esperienza, ciò accade circa l'1% delle volte. L'altro 99% è usato nei casi in cui il valore non è SCONOSCIUTO ma È CONOSCIUTO PER ESSERE ASSENTE.

Per esempio:

  • Client.LastPurchase, per un nuovo cliente. Non è sconosciuto, si sa che non ha ancora effettuato un acquisto.

  • Quando si utilizza un ORM con una mappatura della gerarchia di tabelle per classe , alcuni valori non vengono mappati per determinate classi.

  • Quando si mappa una struttura ad albero di solito avrà una radiceParent = NULL

  • E molti altri...

Sono sicuro che la maggior parte degli sviluppatori ad un certo punto ha scritto WHERE value = NULL, non ha ottenuto alcun risultato, ed è così che hanno imparatoIS NULL sintassi. Guarda quanti voti ha questa domanda e quelli collegati.

I database SQL sono uno strumento e dovrebbero essere progettati nel modo più semplice da comprendere per i loro utenti.


1
Tutti sembrano gridare "NULL is unknown" e quindi giustificare il comportamento. Sì, se questa è una premessa, allora 3VL potrebbe essere la risposta. Ma in quasi tutti i DB su cui lavoro, NULL significa assente. Mi dispiace che la tua voce sia persa nel deserto @AlexDev
John Rees il

3

NULL non è uguale a niente, nemmeno a se stesso. La mia soluzione personale per comprendere il comportamento di NULL è evitare di usarlo il più possibile :).


1
potrebbe anche essere uguale a tutto, come nel caso dei join sinistro / destro / esterno ...
Miguel Ventura,

5
Che stupida risposta improduttiva. Lo stesso potrebbe dirsi ai bambini elementari sull'algebra, ma senza riconoscere effettivamente ciò che sta cercando di risolverlo sarebbe semplicemente sciocco, cosa che ha fatto.
Evan Carroll,

2
@Evan: in realtà, evitare NULL è una soluzione valida. La logica a 3 valori non è controversa e molte persone pensano che SQL sarebbe migliore senza NULL e tutta la complessità (necessaria) che comporta.
sleske,

3
"Molte persone" è una parola da donnola, e "non controverso" è un modo per mascherare il più semplice "controverso" di cui 3VL non lo è.
Evan Carroll,

"NULL non è uguale a niente, nemmeno a se stesso." seguendo questa logica, <somevalue>! = NULL dovrebbe restituire true. Nello strano universo di SQL, tuttavia, è falso.
Tom Lint,

3

La domanda:
uno sconosciuto equivale a un altro sconosciuto?
(NULL = NULL)
Quella domanda è qualcosa a cui nessuno può rispondere, quindi il valore predefinito è true o false in base all'impostazione di ansi_nulls.

Tuttavia la domanda:
questa variabile sconosciuta è sconosciuta?
Questa domanda è abbastanza diversa e si può rispondere con vero.

nullVariable = null sta confrontando i valori
nullVariable è null sta confrontando lo stato della variabile


3

La confusione deriva dal livello di riferimento indiretto (astrazione) che deriva dall'utilizzo di NULL .

Tornando all'analogia "Cosa c'è sotto l'albero di Natale", "Sconosciuto" descrive lo stato di conoscenza di ciò che è contenuto nel riquadro A.

Quindi, se non sai cosa c'è nella casella A, dici che è "Sconosciuto", ma ciò non significa che "Sconosciuto" sia all'interno della scatola . Qualcosa di diverso da sconosciuto è nella scatola, forse una sorta di oggetto, o forse nulla è nella scatola.

Allo stesso modo, se non sai cosa c'è nel riquadro B, puoi etichettare il tuo stato di conoscenza del contenuto come "Sconosciuto".

Quindi, ecco il kicker: il tuo stato di conoscenza sulla casella A è uguale al tuo stato di conoscenza sulla casella B. . (Il tuo stato di conoscenza in entrambi i casi è "Sconosciuto" o "Non so cosa c'è nella confezione".) Ma il contenuto delle caselle può essere o non essere uguale.

Tornando a SQL, idealmente dovresti essere in grado di confrontare i valori solo quando sai quali sono. Sfortunatamente, l'etichetta che descrive una mancanza di conoscenza è memorizzata nella cella stessa , quindi siamo tentati di usarlo come valore. Ma non dovremmo usarlo come valore, perché porterebbe a "il contenuto del riquadro A è uguale al contenuto del riquadro B quando non sappiamo cosa c'è nel riquadro A e / o non sappiamo cosa c'è nel riquadro B. (Logicamente, l'implicazione "se non so cosa c'è nella casella A e se non so cosa c'è nella casella B, allora cosa c'è nella casella A = Cosa c'è nella casella B" è falso.)

Yay, cavallo morto.


3

MSDN ha un bell'articolo descrittivo sui null e sulla logica dei tre stati che generano.

In breve, la specifica SQL92 definisce NULL come sconosciuto e NULL utilizzato nei seguenti operatori provoca risultati imprevisti per i non iniziati:

= operator NULL   true   false 
NULL       NULL   NULL   NULL
true       NULL   true   false
false      NULL   false  true

and op     NULL   true   false 
NULL       NULL   NULL   false
true       NULL   true   false
false      false  false  false

or op      NULL   true   false 
NULL       NULL   true   NULL
true       true   true   true
false      NULL   true   false

Ma la domanda non riguarda 3VL (logica a tre valori) riguarda la proprietà riflessiva dell'uguaglianza.
MaD70,

Per essere più precisi, come ho finalmente dettagliato nella mia risposta, sorgono problemi quando l'uguaglianza viene interpretata in un 3VL in modo che la proprietà riflessiva dell'uguaglianza non sempre valuti come vera.
MaD70,

1

null è sconosciuto in sql, quindi non possiamo aspettarci che due incognite siano uguali.

Tuttavia puoi ottenere quel comportamento impostando ANSI_NULLS su Off (è On di default) Sarai in grado di usare = operatore per null

SET ANSI_NULLS off
if null=null
print 1
else 
print 2
set ansi_nulls on
if null=null
print 1
else 
print 2

2
Questo è ogni tipo di no . Il mondo ha una definizione di null, impara a capirlo o semplicemente modifica la tabella per avere tipi int e aggiornare le colonne.
Evan Carroll,

3
In realtà non ho raccomandato di disattivare SET ANSI_NULLS. Ho scoperto ANSI_NULLS nel modo più duro. Ma è sempre bene conoscere tutte le opzioni disponibili specialmente quando ti imbatti in una linea che dice Where SomeId = null Come potresti dare un senso a quella linea senza conoscere ANSI_NULLS. Per come la vedo io, il mio post è stato utile .. :)
ps.

1

Lavori per il governo registrando informazioni sui cittadini. Ciò include l'ID nazionale per ogni persona nel paese. Un bambino è stato lasciato alla porta di una chiesa circa 40 anni fa, nessuno sa chi siano i loro genitori. L'ID padre di questa persona è NULL. Esistono due di queste persone. Conta le persone che condividono lo stesso ID padre con almeno un'altra persona (persone che sono fratelli). Conti anche quei due?

La risposta è no, tu no, perché non sappiamo se sono fratelli o no.

Supponi di non avere NULLun'opzione e di utilizzare invece un valore predeterminato per rappresentare "l'ignoto", forse una stringa vuota o il numero 0 o un carattere *, ecc. Quindi avresti nelle tue query che * = * , 0 = 0 e “” = “”, ecc. Questo non è ciò che desideri (come nell'esempio sopra), e come spesso potresti dimenticare di questi casi (l'esempio sopra è un chiaro caso marginale al di fuori del normale pensiero quotidiano ), quindi per te è necessario ricordare la lingua che NULL = NULLnon è vera.

Necessità è la madre dell'invenzione.


0

Solo un'aggiunta ad altre meravigliose risposte:

AND: The result of true and unknown is unknown, false and unknown is false,
while unknown and unknown is unknown.

OR: The result of true or unknown is true, false or unknown is unknown, while unknown or unknown is unknown.

NOT: The result of not unknown is unknown

0

Se stai cercando un'espressione che ritorna vera per due NULL puoi usare:

SELECT 1 
WHERE EXISTS (
    SELECT NULL
    INTERSECT
    SELECT NULL
)

È utile se si desidera replicare i dati da una tabella all'altra.


0

Il test di uguaglianza, ad esempio, in un'istruzione case in caso di clausola, può essere modificato da

XYZ = NULL 

per

XYZ IS NULL

Se voglio trattare spazi vuoti e stringhe vuote come uguali a NULL, spesso uso anche un test di uguaglianza come:

(NULLIF(ltrim( XYZ ),'') IS NULL)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.