Moderne BI- und CRM-Systeme erfordern häufig die Implementierung benutzerdefinierter Filter: Es ist wichtig, beliebige Bedingungen (nach Datum, Geschlecht, Status, Tags) flexibel zu kombinieren und sie korrekt in SQL zu kreuzen und zu vereinen. Der resultierende Code sollte lesbar, leicht änderbar und gibt das erwartete Ergebnis zurück.
Entwickler bilden oft „on the fly“ die WHERE-Klausel mit vielen AND/OR aus benutzerdefinierten Filtern, was zu logischen Fehlern und schwer wartbaren Abfragen führt. Das Problem verschärft sich, wenn Filterwerte fehlen oder mit IN/EXISTS/LIKE kombiniert werden.
Für dynamische Filter ist das Muster „Bedingung mit OR immer TRUE, wenn der Wert nicht angegeben ist“ nützlich:
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);
Oder mit dynamischem SQL:
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;
Wichtige Merkmale:
Kann man WHERE 1=1 überall anstelle der Überprüfung auf Vorhandensein von Bedingungen verwenden?
Nein, 1=1 ist lediglich eine Ausgangsbedingung für die Verkettung von WHERE – es ersetzt keine Filter, sondern wird ausschließlich zur Bequemlichkeit der Abfragegenerierung verwendet.
Welche Probleme können auftreten, wenn eine leere Liste in IN () gelangt?
IN (NULL) oder IN () gibt immer false zurück und liefert ein leeres Set, selbst wenn der Filter fehlt. Für korrektes Funktionieren sollte die Leere der Liste separat überprüft und die Bedingung gar nicht aufgenommen werden.
Wie wirken sich solche Konstrukte auf die Verwendung von Indizes und die Leistung aus?
Wenn Filter mit OR oder NULL-Prüfungen umgesetzt werden, hören viele DBMS auf, Indizes effektiv zu nutzen, oder es wird ein vollständiger Tabellen-Scan ausgeführt. Es sollte auf dynamisches SQL oder Filter mit parametrisierten Abfragen zurückgegriffen werden, damit der Planer einen Index auswählen kann.
Ein klassischer Bericht mit 10 Filtern, der Code bildet WHERE mit vielen OR – bei Fehlen mehrerer Filter wird ein leeres Set zurückgegeben oder der Scan ist zu groß, die Serverlast steigt erheblich.
Vorteile:
Eine separate Funktion bildet die Filter nur für die festgelegten Parameter, und nur für jede Gruppe von Bedingungen wird ein separater JOIN/FILTER eingeschaltet. Where enthält kein OR und keine überflüssigen NULL-Prüfungen.
Vorteile: