Regex e pattern matching per la data quality

La data quality parte spesso dalla validazione dei formati: email, partite IVA, codici fiscali, numeri di telefono. Storicamente in T-SQL si usavano LIKE (con i wildcard %, _, [ ], [^ ]) e PATINDEX, che coprono pattern semplici ma non gestiscono quantificatori, alternanze o gruppi di cattura. Le nuove funzioni regex — REGEXP_LIKE, REGEXP_REPLACE, REGEXP_SUBSTR, REGEXP_INSTR, REGEXP_COUNT — colmano il gap sul motore SQL più recente e in Azure SQL.

Il criterio di scelta è per intento:

  • REGEXP_LIKE è un predicato (vero/falso): ideale in una CHECK constraint per bloccare all’origine i dati non conformi, o in WHERE per isolare le righe sporche.
  • REGEXP_REPLACE normalizza e pulisce (rimuove spazi, uniforma separatori).
  • REGEXP_SUBSTR / REGEXP_INSTR estraggono o localizzano una porzione.
  • REGEXP_COUNT conta le occorrenze.

Trade-off chiave: le funzioni regex in WHERE sono tipicamente non-SARGable, quindi non sfruttano gli indici e forzano uno scan. Su grandi volumi conviene restringere prima il set con un predicato SARGable (es. LIKE 'prefisso%', senza wildcard iniziale) e applicare la regex solo sul residuo, oppure materializzare un flag di validità con una computed column persistita.

Fuzzy matching ed edit distance

Il fuzzy matching serve quando i valori dovrebbero coincidere ma differiscono per errori di battitura, abbreviazioni o varianti fonetiche — tipico nella deduplica delle anagrafiche. Due famiglie distinte:

  • Fonetico: SOUNDEX genera un codice basato sul suono, DIFFERENCE confronta due SOUNDEX restituendo un valore 0–4. Riconosce “Smith” ≈ “Smyth”, ma è tarato sull’inglese e ignora le trasposizioni.
  • Edit distance (Levenshtein): conta inserimenti, cancellazioni e sostituzioni necessarie a trasformare una stringa nell’altra. Cattura i typo (“Rossi” vs “Rosi”) meglio del fonetico. Attenzione: la distanza di Levenshtein non è una funzione nativa di T-SQL; va implementata con una UDF (scalare o CLR) oppure gestita a monte.

Per il matching massivo e la deduplica strutturata, SSIS offre le trasformazioni Fuzzy Lookup e Fuzzy Grouping (con soglia di similarità), mentre Data Quality Services fornisce knowledge base e matching policy. Sul piano del significato — non della stringa — la ricerca si appoggia oggi agli embeddings e al vector type con la vector search: utile per trovare record concettualmente simili, complementare e non sostitutivo del fuzzy testuale.

Full-text search per la ricerca testuale

Quando la ricerca è su testo lungo (descrizioni, documenti, note) e per parole o frasi, LIKE '%parola%' è lento e non-SARGable. La full-text search costruisce un full-text index su un full-text catalog e offre due predicati:

  • CONTAINS / CONTAINSTABLE: preciso, supporta operatori booleani, ricerca di prefisso, prossimità (NEAR), forme flesse (inflectional) e thesaurus.
  • FREETEXT / FREETEXTTABLE: linguaggio naturale, più permissivo, cerca per senso delle parole.

Le varianti *TABLE restituiscono un RANK di rilevanza, utile per ordinare i risultati. Per la data quality, la full-text search aiuta a individuare e classificare valori testuali non normalizzati; per la similarità concettuale, di nuovo, gli embeddings con la vector search coprono ciò che le sole parole chiave non catturano.

Trappole tipiche d’esame

  • Validare il formato all’inserimento → soluzione: usa REGEXP_LIKE in una CHECK constraint, non un trigger complesso né la sola validazione applicativa; la constraint garantisce l’integrità a livello di dato.
  • Query regex lenta su tabella grande → soluzione: ricorda che le funzioni regex non sono SARGable; pre-filtra con un predicato indicizzabile o una computed column persistita, non aggiungere un indice sperando che acceleri la regex.
  • “Trova nomi che suonano uguali” → soluzione: SOUNDEX/DIFFERENCE (fonetico); per i typo carattere-per-carattere serve invece l’edit distance.
  • Levenshtein “nativo” in T-SQL → soluzione: trappola classica: non esiste una funzione built-in; va scritta come UDF/CLR o gestita con SSIS Fuzzy Lookup.
  • Ricerca di frase o prossimità su testo lungo → soluzione: CONTAINS con NEAR, non LIKE '%...%'; per ordinare per rilevanza usa CONTAINSTABLE/FREETEXTTABLE con il RANK.
  • “Trova record simili per significato” → soluzione: è similarità semantica → embeddings e vector search, non full-text né fuzzy testuale, che lavorano su parole e caratteri.