Guida pratica al NULL in SQL (con esempi)

Un NULL in SQL non è un valore, non è zero, non è una stringa vuota, e non è neanche uno spazio. È letteralmente l’assenza di un valore. Immagina una casella di un modulo i cui risultati vengano salvati in un database: se è vuota, e non hai scritto nulla, dentro, quella casella sarà plausibilmente NULL. Non è “zero”, non è “vuoto”, è proprio non compilata. Ma certamente molto dipende da come il programmatore ha “deciso” implicitamente di farne uso.

Questa particolare condizione di “non esistenza” rende i NULL un po’ particolari – e spesso fonte di confusione, specialmente nelle operazioni e durante confronti fra campi. Vediamo qualche esempio per capirci meglio.

Esempio 1: La Differenza con Zero, Stringa Vuota e Spazio

Capire che NULL non è nessun altro valore è il primo passo fondamentale.

SQL

SELECT
    NULL AS ValoreNull,        -- Assenza di valore
    0 AS ValoreZero,           -- Un numero: zero
    '' AS StringaVuota,        -- Una stringa che non contiene caratteri
    ' ' AS StringaSpazio;      -- Una stringa che contiene un solo carattere (lo spazio)

Cosa imparare: Sono tutti concetti diversi. NULL rappresenta, in effetti, l’ “assenza di un valore”.

Esempio 2: NULL nelle Tabelle (Campi Opzionali)

Quando crei una tabella, puoi specificare se una colonna può contenere NULL (NULL) o meno (NOT NULL). Se una colonna può essere NULL, significa che non sei obbligato a inserire un valore per quella colonna.

SQL

-- Creo una tabella di esempio
CREATE TABLE Dipendenti (
    ID INT PRIMARY KEY,
    Nome VARCHAR(50) NOT NULL,       -- Il nome deve sempre esserci
    Cognome VARCHAR(50) NOT NULL,    -- Il cognome deve sempre esserci
    Email VARCHAR(100) NULL,         -- L'email è opzionale
    Telefono VARCHAR(20) NULL        -- Il telefono è opzionale
);

-- Inserisco dati:
-- Primo dipendente: tutti i campi compilati
INSERT INTO Dipendenti (ID, Nome, Cognome, Email, Telefono) VALUES
(1, 'Mario', 'Rossi', 'm.rossi@azienda.com', '3331234567');

-- Secondo dipendente: email e telefono sono NULL (non specificati)
INSERT INTO Dipendenti (ID, Nome, Cognome, Email, Telefono) VALUES
(2, 'Anna', 'Verdi', NULL, NULL);

-- Terzo dipendente: solo l'email è NULL
INSERT INTO Dipendenti (ID, Nome, Cognome, Email, Telefono) VALUES
(3, 'Luigi', 'Bianchi', NULL, '3459876543');

-- Visualizzo i dati
SELECT * FROM Dipendenti;

Cosa imparare: NULL viene usato per indicare che un dato non è disponibile o non applicabile per quella riga specifica.


Esempio 3: Confrontare con NULL (La Logica a Tre Valori)

Questo è uno dei punti più critici. Non puoi usare gli operatori di confronto standard (=, !=, <, >) per controllare se un valore è NULL. Questo perché NULL non è un valore, quindi non può essere “uguale a” o “diverso da” qualcos’altro, nemmeno un altro NULL!

SQL usa una logica a tre valori per le condizioni: TRUE, FALSE, e UNKNOWN (sconosciuto). Qualsiasi confronto con NULL restituisce UNKNOWN.

SQL

-- Questi non funzionano come ti aspetteresti per trovare i NULL
SELECT 1 WHERE NULL = NULL;   -- Restituisce 0 righe, perché (NULL = NULL) è UNKNOWN
SELECT 1 WHERE 5 = NULL;      -- Restituisce 0 righe, perché (5 = NULL) è UNKNOWN
SELECT 1 WHERE NULL != NULL;  -- Restituisce 0 righe, perché (NULL != NULL) è UNKNOWN

-- Il modo corretto per controllare i NULL
SELECT 1 WHERE NULL IS NULL;      -- Restituisce 1 riga, perché (NULL IS NULL) è TRUE
SELECT 1 WHERE 5 IS NOT NULL;     -- Restituisce 1 riga, perché (5 IS NOT NULL) è TRUE

Cosa imparare: Usa sempre IS NULL o IS NOT NULL per controllare la presenza o l’assenza di NULL.


Esempio 4: NULL nelle Condizioni WHERE

A causa della logica a tre valori, le righe con NULL in una colonna che usi nella clausola WHERE possono essere escluse inaspettatamente.

SQL

-- Voglio i dipendenti con un'email
SELECT Nome, Cognome, Email FROM Dipendenti WHERE Email IS NOT NULL;
-- Risultato: Mario Rossi (ha un'email)

-- Voglio i dipendenti senza un'email
SELECT Nome, Cognome, Email FROM Dipendenti WHERE Email IS NULL;
-- Risultato: Anna Verdi, Luigi Bianchi (non hanno un'email)

-- Cosa succede se uso '=' o '!='?
SELECT Nome, Cognome, Email FROM Dipendenti WHERE Email = 'm.rossi@azienda.com';
-- Risultato: Mario Rossi (corretto)

SELECT Nome, Cognome, Email FROM Dipendenti WHERE Email != 'm.rossi@azienda.com';
-- Risultato: 0 righe! Anna e Luigi non vengono restituiti perché (NULL != '...') è UNKNOWN, non TRUE.

Cosa imparare: Se filtri per un valore specifico e ci sono NULL nella colonna, devi gestire esplicitamente i NULL nella tua condizione WHERE se vuoi includerli o escluderli in modo specifico.

Esempio 5: Funzioni per la Gestione dei NULL

SQL Server offre funzioni per trasformare o gestire i NULL, utili quando vuoi evitare che un NULL “contagi” un’intera operazione o per dare un valore di default.

  1. ISNULL(espressione, valore_sostitutivo): Sostituisce NULL con un valore specificato. Il tipo di dato del valore sostitutivo deve essere compatibile con espressione.
  2. COALESCE(espressione1, espressione2, ..., espressioneN): Restituisce il primo valore non NULL nella lista di espressioni. Più flessibile di ISNULL perché accetta più argomenti.

SQL

SELECT
    ID,
    Nome,
    Cognome,
    ISNULL(Email, 'Nessuna Email') AS EmailOTelefonoDefault,
    COALESCE(Email, Telefono, 'Nessun Contatto') AS ContattoPreferito
FROM Dipendenti;

Cosa imparare: ISNULL e COALESCE sono i tuoi migliori amici quando devi presentare dati senza buchi visibili o vuoi usare un valore predefinito quando il dato originale è mancante.

Esempio 6: NULL nelle Funzioni Aggregazione

Le funzioni di aggregazione (SUM, AVG, COUNT, MAX, MIN) ignorano i valori NULL per impostazione predefinita. Questo è un comportamento cruciale da ricordare.

SQL

-- Creo una tabella di esempio per i voti
CREATE TABLE VotiEsami (
    StudenteID INT,
    Voto INT NULL -- Un voto può essere NULL se lo studente non si è presentato
);

INSERT INTO VotiEsami (StudenteID, Voto) VALUES
(1, 8),
(1, 7),
(2, 9),
(2, NULL), -- Studente 2 non si è presentato a un esame
(3, 6),
(3, 8);

-- Calcolo la media dei voti (ignorando i NULL)
SELECT AVG(Voto) AS MediaVoti FROM VotiEsami;
-- (8+7+9+6+8) / 5 = 38 / 5 = 7.6. Il NULL è ignorato dal conteggio.

-- Conto i voti NON NULL
SELECT COUNT(Voto) AS NumeroVotiRegistrati FROM VotiEsami;
-- Risultato: 5 (il NULL viene ignorato)

-- Conto tutte le righe, inclusi i NULL
SELECT COUNT(*) AS NumeroEsamiTotali FROM VotiEsami;
-- Risultato: 6 (conta tutte le righe, indipendentemente dai NULL)

Cosa imparare: NULL non contribuiscono ai calcoli di aggregazione (tranne COUNT(*) che conta le righe). Se vuoi che i NULL vengano trattati come zero (o un altro valore) nelle aggregazioni, devi usare ISNULL o COALESCE prima della funzione di aggregazione.

Riepilogo

  • NULL non è zero, non è stringa vuota, non è spazio. È proprio nulla.
  • Non puoi fare confronti diretti con =, !=, <, >. Usa IS NULL o IS NOT NULL. Non scherziamo su questo, è la causa di metà dei bug sui dati mancanti!
  • Attento al + operator! Se c’è un NULL, tutta la stringa diventa NULL.
  • CONCAT() e CONCAT_WS() sono i tuoi amici moderni per la concatenazione, gestiscono i NULL in modo intelligente (convertendo a '' o ignorandoli).
  • Le funzioni di aggregazione generalmente ignorano i NULL. Se vuoi includerli (es. come zero), usa ISNULL() o COALESCE() prima.

Capire e gestire correttamente i NULL è una delle pietre angolari per scrivere query SQL robuste e affidabili. Ignorali a tuo rischio e pericolo!

Hai qualche caso specifico o un’altra domanda su come i NULL si comportano?