Le moderne sistematiche BI e CRM richiedono spesso di implementare filtri utente: è importante combinare in modo flessibile condizioni arbitrarie (per data, sesso, stato, tag) e anche attraversarle e unirle correttamente nel linguaggio SQL. Il codice risultante deve essere leggibile, facilmente modificabile e fornire il risultato atteso.
Spesso gli sviluppatori formano 'al volo' la clausola WHERE con numerosi AND/OR dai filtri utente, il che porta a errori logici e a query difficili da mantenere. Il problema è aggravato se i valori dei filtri possono essere assenti o combinarsi con IN/EXISTS/LIKE.
Per i filtri dinamici è comodo il pattern 'condizione con OR sempre TRUE se il valore non è impostato':
SELECT * FROM users WHERE (status = @status OR @status IS NULL) AND (gender = @gender OR @gender IS NULL) AND (created >= @from_date OR @from_date IS NULL) AND (city IN (@cities) OR @cities IS NULL);
Oppure usando SQL dinamico:
DECLARE @sql NVARCHAR(MAX) = N'SELECT * FROM users WHERE 1=1'; IF @status IS NOT NULL SET @sql += N' AND status = @status'; IF @gender IS NOT NULL SET @sql += N' AND gender = @gender'; -- ... EXEC sp_executesql @sql, N'@status NVARCHAR(10),@gender NVARCHAR(10)', @status, @gender;
Caratteristiche chiave:
Si può usare WHERE 1=1 ovunque invece di controllare la presenza delle condizioni?
No, 1=1 è solo una condizione iniziale per la concatenazione di WHERE — non sostituisce i filtri, ma è utilizzato esclusivamente per comodità nella generazione delle query.
Quali problemi possono sorgere se un elenco vuoto finisce in IN ()?
IN (NULL) o IN () restituiscono sempre false e producono un insieme vuoto, anche in assenza di filtro. Per un corretto funzionamento, è necessario controllare separatamente se l'elenco è vuoto e non includere la condizione affatto.
Come influenzano tali costrutti l'uso degli indici e le prestazioni?
Se i filtri sono implementati con OR o controlli NULL, molti DBMS smetteranno di utilizzare efficacemente gli indici, oppure verrà eseguita una scansione dell'intera tabella. È consigliabile applicare approcci con SQL dinamico o filtri tramite query parametrize, affinché il pianificatore possa scegliere l'indice.
Un classico report con 10 filtri, il codice genera WHERE con molteplici OR — in assenza di più filtri, il risultato restituisce un insieme vuoto o una scansione troppo grande, il carico sul server aumenta notevolmente
Vantaggi:
Una funzione separata genera filtri solo per i parametri specificati, e solo per ciascun gruppo di condizioni viene incluso un JOIN/FILTER separato. Where non contiene OR e controlli superflui su NULL.
Vantaggi: