Se c’è un’operazione che ogni sviluppatore SQL compie centinaia di volte al giorno, è la concatenazione di stringhe. Che tu debba unire nome e cognome, costruire un indirizzo completo da vari campi o generare un messaggio di log, prima o poi ti imbatti nella necessità di mettere insieme pezzi di testo. Sembra banale, vero? Ebbene, in SQL Server ci sono diversi modi per farlo, e ognuno ha le sue piccole (grandi) peculiarità. Ignorarle? Un errore che ti costa tempo e mal di testa.
Prepariamoci a fare chiarezza e a capire quando usare cosa, evitando le trappole più comuni, specialmente quelle legate ai valori NULL!
1. L’Operatore +(…ma occhio ai NULL!)
Questo è il metodo più antico e forse il più istintivo. È lì da sempre, semplice da usare, e per unire due stringhe al volo fa il suo sporco lavoro.
SELECT 'Hello' + ' ' + 'World' AS Messaggio;
-- Risultato: Hello World
La Trappola dei NULL: Ed è qui che arriva il bello (o il brutto). L’operatore + ha un comportamento che devi stamparti in testa: se uno qualsiasi degli operandi concatenati è NULL, l’intero risultato della concatenazione sarà NULL. Punto.
Vediamo l’esempio più classico:
SELECT 'Nome:' + 'Mario' + ' Cognome:' + NULL AS DatiUtente;
-- Risultato: NULL
SELECT 'Articolo: ' + 'Libro' + ' - Autore: ' + NULL + ' - Prezzo: ' + '19.99' AS DettaglioProdotto;
-- Risultato: NULL (Perché "Autore" era NULL, ha rovinato tutto!)
Questa è la causa numero uno di query che restituiscono NULL inaspettati quando ti aspetti una stringa parziale. Devi gestirli esplicitamente con ISNULL() o COALESCE() se vuoi usare il +.
2. La Funzione CONCAT(): L’Amico dei NULL (Finalmente!)
Introdotta con SQL Server 2012, la funzione CONCAT() è stata una manna dal cielo proprio per la gestione dei NULL. Finalmente, un modo per concatenare senza che un singolo NULL ti mandasse a monte tutta la stringa!
La sua “killer feature” è che CONCAT() tratta i NULL come stringhe vuote (''). Quindi, puoi passargli N argomenti, e se alcuni sono NULL, semplicemente li ignorerà (o meglio, li tratterà come stringhe vuote) e continuerà la concatenazione con gli altri valori.
SELECT CONCAT('Hello', ' ', 'World') AS Messaggio;
-- Risultato: Hello World
SELECT CONCAT('Nome:', 'Mario', ' Cognome:', NULL) AS DatiUtente;
-- Risultato: Nome:Mario Cognome:
SELECT CONCAT('Articolo: ', 'Libro', ' - Autore: ', NULL, ' - Prezzo: ', '19.99') AS DettaglioProdotto;
-- Risultato: Articolo: Libro - Autore: - Prezzo: 19.99 (Molto meglio!)
Quando usarla? Praticamente sempre quando non hai bisogno di un separatore fisso tra tutti gli elementi e vuoi la pace dei sensi con i NULL. È pulita, leggibile e meno propensa a errori.
3. La Funzione CONCAT_WS(): Con Separatore e Senza Problemi (dal 2017)
Per le vere gioie dello sviluppatore, in SQL Server 2017 è arrivata CONCAT_WS(). “WS” sta per “With Separator”, e il nome dice tutto. Questa funzione ti permette di specificare un separatore che verrà inserito tra ogni stringa che stai concatenando.
La sintassi è: CONCAT_WS(separatore, stringa1, stringa2, ...)
E la cosa migliore? Anche CONCAT_WS() è intelligente con i NULL: li ignora completamente! Non li trasforma in stringhe vuote come CONCAT(), semplicemente non li considera per la concatenazione, né per aggiungere il separatore.
SELECT CONCAT_WS('-', 'Rossi', 'Mario', 'Via Roma', '10', 'Roma', '00100') AS IndirizzoCompleto;
-- Risultato: Rossi-Mario-Via Roma-10-Roma-00100
SELECT CONCAT_WS(', ', 'Rossi', 'Mario', NULL, 'Roma', NULL, '00100') AS DatiUtenteConVirgola;
-- Risultato: Rossi, Mario, Roma, 00100 (Il NULL è stato ignorato, nessun doppio separatore!)
Quando usarla? Ogni volta che devi costruire una stringa complessa da più campi e vuoi che un determinato separatore sia presente tra ogni pezzo, ma solo se quel pezzo esiste. Perfetta per indirizzi, liste di tag, nomi composti da più parti, ecc.
Esempi Pratici: Metti le Mani in Pasta!
Per capire davvero le differenze, non c’è niente di meglio che sporcarsi le mani. Esegui questi script nel tuo SQL Server Management Studio (SSMS) o Azure Data Studio. Useremo una semplice tabella temporanea per simulare un po’ di dati.
Setup per i Test:
-- Pulisco la tabella temporanea se esiste già
IF OBJECT_ID('tempdb..#TestStrings') IS NOT NULL DROP TABLE #TestStrings;
-- Creo una tabella temporanea con un po' di dati di esempio
CREATE TABLE #TestStrings (
ID INT IDENTITY(1,1) PRIMARY KEY,
FirstName NVARCHAR(50),
LastName NVARCHAR(50),
MiddleName NVARCHAR(50), -- Questo avrà dei NULL
City NVARCHAR(50),
ZipCode NVARCHAR(10)
);
-- Inserisco i dati
INSERT INTO #TestStrings (FirstName, LastName, MiddleName, City, ZipCode) VALUES
('Mario', 'Rossi', NULL, 'Roma', '00100'),
('Luigi', 'Verdi', 'Carlo', 'Milano', '20100'),
('Anna', 'Bianchi', NULL, 'Napoli', NULL), -- Qui anche il CAP è NULL
('Giuseppe', 'Neri', 'Maria', NULL, '50100'); -- Qui la città è NULL
Test dell’Operatore +:
SELECT
ID,
FirstName,
MiddleName,
LastName,
'Nome Completo (+) : ' + FirstName + ' ' + MiddleName + ' ' + LastName AS FullNamePlus,
'Indirizzo (+) : ' + City + ', ' + ZipCode AS FullAddressPlus
FROM #TestStrings;
Cosa noterai: Molti NULL nei risultati finali, anche se solo una parte della stringa è NULL. Il record di Anna avrà NULL per l’indirizzo a causa del ZipCode a NULL, e il record di Mario e Anna avranno NULL nel nome completo a causa di MiddleName a NULL.
Test della Funzione CONCAT():
SELECT
ID,
FirstName,
MiddleName,
LastName,
'Nome Completo (CONCAT) : ' + CONCAT(FirstName, ' ', MiddleName, ' ', LastName) AS FullNameConcat,
'Indirizzo (CONCAT) : ' + CONCAT(City, ', ', ZipCode) AS FullAddressConcat
FROM #TestStrings;
Cosa noterai: I NULL ora sono stringhe vuote. Mario e Anna avranno un doppio spazio nel nome completo ('Mario Rossi') a causa del MiddleName NULL e dello spazio esplicito. Anna avrà 'Napoli, ' per l’indirizzo. Giuseppe avrà ', 50100' per l’indirizzo.
Test della Funzione CONCAT_WS():
SELECT
ID,
FirstName,
MiddleName,
LastName,
'Nome Completo (CONCAT_WS): ' + CONCAT_WS(' ', FirstName, MiddleName, LastName) AS FullNameConcatWS,
'Indirizzo (CONCAT_WS) : ' + CONCAT_WS(', ', City, ZipCode) AS FullAddressConcatWS
FROM #TestStrings;
Cosa noterai: Questo è il più elegante. Il separatore viene applicato solo tra i valori *non-NULL*. Mario e Anna avranno un singolo spazio nel nome completo. Anna avrà `Napoli` e Giuseppe avrà `50100` per l’indirizzo, senza virgole o spazi aggiuntivi dove il campo era `NULL`.
Pulizia:
-- Non dimenticarti di pulire la tabella temporanea!
DROP TABLE #TestStrings;
Quale Usare? Il Consiglio del Programmatore!
+Operatore: Usalo solo se sei assolutamente certo che nessuna delle stringhe coinvolte sarà maiNULL, o se gestisci iNULLesplicitamente conISNULL()oCOALESCE(). È più conciso per due stringhe semplici. Personalmente, lo evito quasi sempre a meno che non stia facendo una concatenazione banale e controllata.CONCAT(): La tua scelta predefinita quando devi unire più stringhe e non vuoi che unNULLin mezzo ti rovini tutto. La sua gestione deiNULLè robusta. Tieni a mente che aggiungerà uno spazio se lo metti tu come separatore e un elemento èNULL.CONCAT_WS(): Il re della concatenazione strutturata. Se devi unire una serie di campi con un separatore consistente (es. nome, cognome, città, via) e vuoi che i campiNULLvengano semplicemente ignorati senza lasciare separatori “appesi”, questa è la funzione che fa per te. È la più “intelligente” con iNULLe produce output puliti.
Spero che questa carrellata ti abbia chiarito le idee. La prossima volta che concateni una stringa in SQL Server, pensa ai NULL e scegli lo strumento giusto per il lavoro. Ti risparmierai un sacco di debugging notturno!
Tag: sql server concat string
