21st Jul 2022 Tempo di lettura: 10 minuti Come utilizzare gli operatori di confronto con i NULL in SQL James Wondrasek sql imparare sql null Indice SQL NULL - L'ignoto conosciuto Cos'è la logica ternaria e come funziona in SQL? Operazioni di confronto SQL e valori NULL Gli altri operatori di confronto di SQL NULL e l'operatore < NULL e l'operatore > NULL e l'operatore <= NULL e l'operatore >= Operatori di confronto SQL che funzionano con i NULL SQL NULL e Outer Joins Per saperne di più sui NULL in SQL Il valore SQL NULL ha una funzione speciale. Ha anche dei comportamenti controintuitivi che possono mettere in crisi i principianti di SQL o anche i programmatori più esperti. Scoprite come evitare questi problemi quando usate NULL con gli operatori di confronto. Questo articolo vi aiuterà a padroneggiare le migliori pratiche per la creazione di query SQL che funzionano con i valori NULL e utilizzano gli operatori di confronto ( =, <>, <, > ) - che, se avete già scritto query SQL, sapete che sono praticamente tutte le query che scriverete! Si tratta di nozioni essenziali e la loro padronanza renderà l'SQL più semplice. Faremo una breve panoramica sui NULL in SQL, sul perché esistono e su come la loro stranezza influisce sui risultati delle query. Seguiranno alcune query SQL che dimostrano la stranezza. Verranno poi discusse le tecniche standard per scrivere query che gestiscano correttamente i NULL e gli operatori di confronto. Infine, verrà fatto un rapido riepilogo di tutti gli operatori di confronto di SQL e di come ciascuno di essi interagisce con i NULL. Non preoccupatevi. Non è così difficile come sembra. Cominciamo a esaminare i valori NULL in SQL. SQL NULL - L'ignoto conosciuto I database sono destinati a essere un'unica fonte di verità. Ciò che viene registrato nei campi di ogni riga rappresenta ciò che è noto. Osservate la tabella seguente, adattata da What Is a NULL in SQL (un'ottima risorsa per approfondire i NULL in SQL). Questa potrebbe essere una parte di un database creato da un superfan dei Simpson. namesocial_sec_nostatusspouse Homer Simpson000-00-5000marriedMarjorie Bouvier Nedward Flanders000-00-4000marriedMaude Flanders Waylon Smithers000-00-8000singleNULL Dr Nick Riviera000-00-7000NULLNULL Il NULL rappresenta due cose diverse. Waylon Smithers è noto per essere single, quindi il NULL in questa riga nella colonna coniuge rappresenta un valore inesistente. Ma sappiamo così poco del Dr. Nick che i valori NULL nelle colonne coniuge e status rappresentano un valore sconosciuto. Per mantenere l'integrità di un database, sono necessarie entrambe le interpretazioni di NULL. Per aiutare i programmatori a mantenere l'integrità nonostante i valori mancanti e sconosciuti, SQL incorpora i NULL nella sua logica ternaria. Cos'è la logica ternaria e come funziona in SQL? La logica binaria utilizza due valori: Vero e Falso, 0 e 1, ecc. La logica ternaria utilizza tre valori. In SQL, questi tre valori sono Vero, Falso e Sconosciuto. Nella logica ternaria SQL, NULL equivale al valore sconosciuto. Ecco come i tre valori della logica ternaria funzionano con gli operatori logici di SQL NOT, OR e AND: NOT TRUEFALSE FALSETRUE UNKNOWNUNKNOWN ORTRUEFALSEUNKNOWN TRUETRUETRUETRUE FALSETRUEFALSEUNKNOWN UNKNOWNTRUEUNKNOWNUNKNOWN ANDTRUEFALSEUNKNOWN TRUETRUEFALSEUNKNOWN FALSEFALSEFALSEFALSE UNKNOWNUNKNOWNFALSEUNKNOWN Il risultato: Qualsiasi operazione logica che coinvolga un NULL dà come risultato un valore sconosciuto , ad eccezione di TRUE OR NULL e FALSE AND NULL. Interessante, ma non è necessario memorizzarlo. Come vedrete, l'SQL ci aiuta ad aggirare questa logica complicata. Il che è comodo, perché le operazioni di confronto in SQL utilizzano la stessa logica ternaria. Operazioni di confronto SQL e valori NULL Ecco una query che utilizza gli operatori di confronto e logici. Indovinate quante righe restituisce: SELECT spouse FROM simpsons WHERE spouse = NULL OR NOT (spouse = NULL) Cominciamo con la prima operazione di confronto: WHERE spouse = NULL Qualunque cosa contenga la colonna di confronto (stipendi, nomi di animali domestici, ecc.), se verifichiamo che è uguale a NULL, il risultato è sconosciuto. Questo vale anche se il valore della colonna è NULL. È questo che confonde i programmatori esperti di altri linguaggi. Ad esempio, in Python il valore None sembra simile al NULL di SQL e può essere confrontato con se stesso: >>> None == None True Ma la prima riga della clausola WHERE restituirà unknown. Quindi, quando la nostra query viene valutata, avrà l'aspetto seguente: SELECT spouse FROM simpsons WHERE unknown OR NOT (spouse = NULL) Osserviamo la seconda riga della condizione WHERE: OR NOT (spouse = NULL) Anche questo confronto restituirà unknown. Dalla tabella di verità precedente si evince che NOT unknown restituirà unknown. Quindi ora la nostra query è diventata: SELECT spouse FROM simpsons WHERE unknown OR unknown La tabella di verità OR di cui sopra ci dice che il risultato sarà sconosciuto. Una clausola WHERE richiede condizioni vere. Il fatto che il risultato non sia falso non è sufficiente. Quindi, nonostante la query sembri restituire tutte le righe, la logica ternaria di SQL e la natura di SQL NULL fanno sì che vengano restituite zero righe. Gli altri operatori di confronto di SQL Per questi esempi, utilizzeremo una tabella diversa, pet_owners: namepet_count Bob5 Cate2 AliceNULL Steve22 NULL e l'operatore < Utilizzando la tabellapet_owners , vediamo chi ha meno di 5 animali domestici. Il risultato: name Cate Perché? Alice, che non ha compilato il modulo di indagine sugli animali domestici, ha NULL per la sua pet_count. Il valore di ogni NULL è sconosciuto. NULL è < 5? È sconosciuto, quindi Alice non può essere inclusa nei risultati. NULL e l'operatore > Ora vedremo chi ha più di 3 animali domestici. SELECT p.name FROM pet_owners p WHERE pet_count > 3 Il risultato: name Bob Steve Perché? Ancora una volta è il valore sconosciuto di NULL. Così come non si sa se NULL 3 < 5, it is unknown if NULL >. Alice è esclusa dai risultati.5,> NULL e l'operatore <= Con un sottile cambiamento, ora otterremo un elenco di tutti coloro che non hanno più di 5 animali domestici. SELECT p.name FROM pet_owners p WHERE pet_count <= 5 Il risultato: name Bob Cate Cambiando la prima query dall'operatore < all'operatore <=, Bob viene aggiunto all'insieme dei risultati, ma non Alice. Nella prima query, il numero di animali domestici di Bob (5) non è inferiore a 5. Ma è inferiore o uguale a Alice. Ma è minore o uguale a 5, quindi ora è incluso nel risultato della query. Alice continua a non comparire. Quando si esamina la riga di Alice, si può pensare a <= come abbreviazione di "NULL < 5 O NULL = 5". Sappiamo che "NULL < QUALSIASI COSA" restituirà sconosciuto; sappiamo anche che "NULL = QUALSIASI COSA" restituirà sconosciuto. Ancora una volta, Alice viene esclusa dai risultati. NULL e l'operatore >= Vediamo ora chi ha almeno 3 animali domestici. SELECT p.name FROM pet_owners p WHERE pet_count >= 3 Il risultato: name Bob Steve Come <=, possiamo pensare a >= come a una combinazione logica di due operazioni di confronto. Quindi, per Alice, il confronto è equivalente a "NULL > 3 OPPURE NULL = 3". Dovrebbe essere chiaro che il risultato può essere solo un valore sconosciuto. Operatori di confronto SQL che funzionano con i NULL Per gestire correttamente i NULL, SQL mette a disposizione due operatori di confronto speciali: IS NULL e IS NOT NULL. Questi operatori restituiscono solo vero o falso e rappresentano la migliore pratica per incorporare i valori NULL nelle query. Per ottenere il risultato atteso, possiamo riscrivere la query dei Simpson in questo modo: SELECT spouse FROM simpsons WHERE spouse IS NULL OR spouse IS NOT NULL Ora la query restituirà ogni riga, come ci aspettavamo. SQL NULL e Outer Joins Questo è un argomento più avanzato. Se non conoscete il sito SQL JOINs, probabilmente dovreste leggere prima 7 esempi di JOIN SQL con spiegazioni dettagliate. È comune utilizzare una clausola WHERE insieme all'operatore IS NOT NULL per eliminare le righe con valori NULL. Ma a volte questo può essere un modo inefficiente per ottenere un risultato. Ecco perché. I join esterni ( LEFT, RIGHT o FULL JOIN ) possono essere considerati come un INNER JOIN (che restituisce le righe corrispondenti) più le righe non corrispondenti con le colonne riempite di NULL. Un LEFT JOIN restituisce tutte le righe della tabella di sinistra della join con le righe corrispondenti della tabella di destra (o valori NULL se non c'è corrispondenza). Una RIGHT JOIN restituisce tutte le righe della tabella destra con le righe corrispondenti (o i valori NULL) della tabella sinistra. Una FULL JOIN è come una INNER JOIN che restituisce anche tutte le righe non corrispondenti delle tabelle destra e sinistra estese da NULL. Se la clausola WHERE della query filtra le righe che sono state estese da NULL, in pratica si annulla la join esterna. Si dovrebbe riscrivere la query utilizzando una clausola INNER JOIN. In altri casi, i NULL interagiscono con la clausola WHERE e causano risultati errati. Vediamo un esempio che lo dimostra. Potete eseguirlo voi stessi utilizzando questo SQL Fiddle(qui trovate una guida ad altri siti da utilizzare per esercitarvi con l'SQL). Per questo esempio, utilizzeremo due tabelle, una per i valori customers e una per orders. idnameemail 1Alicealice@gmail.com 2Bobbob@hmail.com 3Catecate@imail.com Tabella customers idorder_datecust_emailamount 12021-02-04bob@hmail.com50 22021-02-05cate@imail.com20 32021-02-06cate@imail.com40 42021-02-06bob@hmail.com15 Tabella orders Vogliamo vedere l'importo speso da tutti i nostri clienti registrati dal 4 febbraio 2021 ("2021-02-04"). Iniziamo con una INNER JOIN. In questa query ci sono alcune funzioni SQL aggiuntive che potrebbero essere nuove per voi, ma LearnSQL vi copre. Abbiamo articoli su COALESCE, sulle funzioni aggregate come SUM e sulla clausola GROUP BY. Non è necessario preoccuparsi di cosa fanno queste funzioni in questo momento. Concentratevi su ciò che ogni query restituisce, a partire da questa: SELECT c.name, COALESCE(SUM(o.amount),0) as 'Total' FROM customers c INNER JOIN orders o ON c.email = o.cust_email WHERE o.order_date > '2021-02-04' GROUP BY c.name; La query produce questo risultato: nameTotal Bob15 Cate60 Sembra buono, ma abbiamo 3 clienti. Se vogliamo vedere tutti i clienti, dobbiamo usare LEFT OUTER JOIN (in breve LEFT JOIN ). Questa includerà tutte le righe della tabella di sinistra dell'istruzione FROM, anche se non ci sono dati corrispondenti nella tabella di destra. Questo ci permette di ottenere la nostra prossima query: SELECT c.name, COALESCE(SUM(o.amount),0) as 'Total' FROM customers c LEFT JOIN orders o ON c.email = o.cust_email WHERE o.order_date > '2021-02-04' GROUP BY c.name; I risultati potrebbero sorprendervi: nameTotal Bob15 Cate60 Perché succede questo? Perché Alice è ancora assente? Una query più semplice ci darà un indizio: SELECT c.name, COALESCE(SUM(o.amount),0) as 'Total' FROM customers c LEFT JOIN orders o ON c.email = o.cust_email WHERE o.order_date > '2021-02-04' GROUP BY c.name; Il risultato: nameorder_date Bob2021-02-04 Cate2021-02-05 Cate2021-02-06 Bob2021-02-06 Alice(null) Come già detto, LEFT JOIN include tutte le righe della tabella di sinistra. Se non ci sono righe corrispondenti nella tabella di destra, le colonne vengono riempite con NULL. La clausola WHERE esegue il filtraggio dopo JOIN, quindi tutte le righe per Alice saranno rimosse perché il confronto con NULL, ad esempio con un order_date inesistente, restituisce un'informazione sconosciuta. WHERE restituisce solo una riga in cui le condizioni sono valutate come VERE. Il modo per risolvere questo problema è spostare l'espressione condizionale, qui o.order_date > '2021-02-04', all'interno di JOIN includendola nella clausola ON: SELECT c.name, COALESCE(SUM(o.amount),0) as 'Total' FROM customers c LEFT JOIN orders o ON c.email = o.cust_email WHERE o.order_date > '2021-02-04' GROUP BY c.name; Poiché stiamo utilizzando una clausola LEFT JOIN, Alice rimane nell'insieme dei risultati nonostante la condizione aggiuntiva della data. Il suo NULL viene trasformato in uno "0" più pulito dalla funzione COALESCE(). Il risultato della query è ora quello atteso: nameTotal Alice0 Bob15 Cate60 Per saperne di più sui NULL in SQL Ora dovreste aver capito come SQL tratta i valori NULL e le migliori pratiche per lavorarci. Conoscete gli operatori IS NULL e IS NOT NULL e come la logica ternaria di SQL restituisca sempre unknown quando qualcosa viene confrontato con un NULL , tranne in due casi speciali. Avete anche visto come riscrivere le query in modo da non dover filtrare i fastidiosi NULL. Ma c'è ancora molto da sapere su come lavorare con i NULL in SQL. Vi suggerisco di continuare a imparare con gli articoli Come ORDER BY e NULL lavorano insieme in SQL e Valori NULL e la clausola GROUP BY. Se si desidera acquisire una vera padronanza di SQL, si consiglia di seguire la traccia SQL Practice Set o il percorsoSQL Practice . Offrono un'esperienza di apprendimento approfondita e facile da seguire che vi aiuterà a perfezionare il vostro mestiere. Tags: sql imparare sql null