Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Lesedauer 7 Min.

Die Suche nach Texten

Suchen, bis die Server schwitzen? Wer versteht, wie der SQL Server denkt, wird bessere Ergebnisse und bessere Performance erzielen.
© EMGenie

Suchen in Datenbanken klingt zunächst banal – bis man es ernsthaft tut. Die meisten Entwickler schreiben in der ersten Euphorie etwas wie SELECT * FROM Customers WHERE LastName = 'Müller' und wundern sich dann über das Ergebnis: Zu viel, zu wenig oder gar nichts. Das liegt selten am SQL Server, sondern am Verständnis darüber, was Gleichheit, NULL, Zeichensätze und Collations wirklich bedeuten.

T‑SQL ist kein naives Vergleichswerkzeug – und der SQL Server eigentlich auch keine Suchmaschine. Die Suche folgt logischen Regeln, die auf den ersten Blick manchmal paradox erscheinen, aber enorme Ausdrucksstärke bieten, wenn man sie beherrscht. Dieser Artikel zeigt praxisnah, wie man sauber und performant sucht – ganz ohne externe Tools.

Vektor-Suche

Die sogenannte semantische Suche wird hier nicht behandelt. Der Umfang dieses Themas rechtfertig einen längeren Artikel, der für die Printausgabe 3/2026 der dotnetpro geplant ist.

Gleichheit und Ungleichheit

Die Operatoren = und <> (nicht ANSI, aber möglich ist auch !=) sind die Grundlage aller Vergleiche. Sie prüfen auf exakte Gleichheit beziehungsweise Ungleichheit. Doch sobald ein NULL auftaucht, versagt das einfache Denken: NULL = NULL und gleichzeitig NULL <> NULL ergeben immer False, niemals True. Das liegt daran, dass NULL „unbekannt“ oder „keine Angabe“ bedeutet – und zwei Unbekannte können nicht sinnvoll verglichen werden.

Dieses Verhalten folgt der dreiwertigen Logik (True, False, NULL), die SQL seit den 1980ern prägt. Viele Entwickler stolpern darüber, wenn sie scheinbar leere Werte vergleichen und keine Ergebnisse bekommen. Ein Filter wie WHERE City = 'Berlin' ignoriert alle Zeilen, in denen „City“ NULL ist. Das kann sinnvoll oder fatal sein – je nach Anwendung.

IS NULL – der blinde Fleck der Gleichheit

Um NULL korrekt zu prüfen, braucht man IS NULL oder IS NOT NULL. Diese Operatoren sind speziell dafür geschaffen, um NULL-Werte zu erkennen. Sie sind logisch sauber und meist auch indexfreundlich.

ISNULL()-Funktion 

IS NULL darf nicht mit der ISNULL()-Funktion verwechselt werden. Und auch Filter à la WHERE ISNULL(City, '') = '' sollten nicht zum Einsatz kommen.  Auf den ersten Blick funktioniert das zwar, es ist aber alles andere als gut für die Verwendung von Indizes und für die Performance der Abfrage. Außerdem lassen sich so keine Zeilen unterscheiden, in denen das Attribut NULL oder ein leere Zeichenkette ist.

 

SELECT * FROM dbo.Customers WHERE Phone IS NULL;
 SELECT * FROM dbo.Customers WHERE Phone IS NOT NULL;

 

Die genaue Aussagekraft von NULL hängt stark vom Kontext ab. In manchen Modellen bedeutet es „unbekannt“, in anderen „nicht zutreffend“. Ein konsistenter Umgang damit ist entscheidend, sonst werden Vergleiche unberechenbar und unlogisch.

IS DISTINCT FROM – die logische Evolution

SQL Server 2022 führt mit IS DISTINCT FROM endlich einen Operator ein, der sichere Vergleiche erlaubt, egal ob für NULL oder gewöhnliche Werte. Damit lassen sich zwei Werte direkt vergleichen – auch wenn einer oder beide NULL sind. IS DISTINCT FROM liefert True, wenn Werte unterschiedlich sind, und False, wenn sie gleich oder beide NULL sind. IS NOT DISTINCT FROM ist das Gegenstück: Es liefert True, wenn die Werte identisch sind, einschließlich des Falls, dass beide NULL sind.

Diese beiden Abfragen liefern Zeilen aus einer fiktiven Tabelle:

 

SELECT * FROM [<Tabelle>] WHERE 0 IS NOT DISTINCT FROM 0;
 SELECT * FROM [<Tabelle>] WHERE NULL IS NOT DISTINCT FROM NULL;

 

Diese beiden Abfragen liefern hingegen keine Zeilen:

 

SELECT * FROM [<Tabelle>] WHERE 0 IS NOT DISTINCT FROM 1;
 SELECT * FROM [<Tabelle>] WHERE 0 IS NOT DISTINCT FROM NULL;

 

IS DISTINCT FROM und IS NOT DISTINCT FROM entsprechen den folgenden doch recht komplexen Ausdrücken. Solche Ausdrücke möchte eigentlich niemand schreiben – und schon gar nicht mehrfach in einer Abfrage.

 

A IS DISTINCT FROM B => ((A <> B OR A IS NULL OR B IS NULL) AND NOT (A IS NULL AND B IS NULL))
 
 A IS NOT DISTINCT FROM B => (NOT (A <> B OR A IS NULL OR B IS NULL) OR (A IS NULL AND B IS NULL))

 

Dieser Operator vereinfacht Abfragen, ETL-Prozesse, Change Tracking oder Data Matching enorm. Was sonst aus verschachtelten Bedingungen bestand, wird nun eine einzige, saubere Klausel. Zudem versteht der Optimizer diese Syntax vollständig, sodass keine unnötigen Performance-Einbußen entstehen.

LIKE

Mit LIKE verlassen wir die Welt der exakten Vergleiche. Der Operator erlaubt Wildcards (% für beliebige Zeichen, _ für exakt eines). Damit lassen sich Muster finden, zum Beispiel alle Kunden, deren Nachname mit „M“ beginnt und auf „er“ endet.

 

SELECT * FROM Person.Person WHERE LastName LIKE 'M%er';

 

Doch LIKE hat seine Grenzen: Eine führende Wildcard macht jeden Index für die Abfrage unbrauchbar. Das bedeutet, der Index wird ignoriert und der gesamte Datensatz gescannt. Bei Millionen von Zeilen ist das teuer. Eine Alternative sind persistierte, normalisierte Spalten mit Index.

LIKE kann noch ein paar weitere „Kunststücke“ wie ein Zeichen aus einer Reihe (LIKE '[A-M]%er'), diese kommen allerdings eher sporadisch zum Einsatz. Bei mehrsprachigen Daten empfiehlt sich eine Collation wie Latin1_General_CI_AI, die Akzente und Groß‑/Kleinschreibung ignoriert. Damit sähe ein Filter so aus: 

 

WHERE LastName COLLATE Latin1_General_CI_AI LIKE '%mueller%';

 

Der Operator ist daher sehr oft ein idealer Kompromiss zwischen Einfachheit und Flexibilität, kann aber auch der Todesstoß für die Performance sein.

SOUNDEX() und DIFFERENCE() – Klang statt Schrift

Manchmal sollen ähnliche Wörter als gleich gelten – etwa Müller, Mueller oder Möller. Hier helfen SOUNDEX() und DIFFERENCE(). Sie wandeln Wörter in phonetische Codes um, sodass Schreibvarianten denselben Klangcode erhalten. DIFFERENCE() liefert einen Wert zwischen 0 und 4; je höher, desto ähnlicher.

 

SELECT LastName, SOUNDEX(LastName) AS Code, DIFFERENCE(LastName,'Mueller') AS Score
 FROM Person.Person
 WHERE DIFFERENCE(LastName,'Mueller') >= 3;

 

Für schnelle Suche nach Dubletten sind diese Funktionen oft ausreichend.

Reguläre Ausdrücke

SQL Server 2025 bringt endlich das, was sich viele Entwickler seit Jahren wünschen: echte reguläre Ausdrücke direkt in T-SQL. Mit den neuen Funktionen wie zum Beispiel REGEXP_LIKE() können Zeichenkettenmuster serverseitig geprüft werden – ohne CLR-Umwege oder externe Skripte.

Die Syntax orientiert sich an den bekannten .NET-Regeln, da auch hier Version 2 (RE2) implementiert wurde: 

 

SELECT * 
 FROM Person.Person
 WHERE REGEXP_LIKE(EmailAddress, '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$');

 

Damit wird T-SQL endlich textanalytisch erwachsen. Auch Varianten wie REGEXP_REPLACE() und REGEXP_SUBSTR() stehen bereit und machen es möglich, Text direkt in Abfragen zu validieren, zu extrahieren oder zu transformieren.

Gerade für Datenqualitätsprüfungen, Log-Analysen oder ETL-Pipelines eröffnet das neue Feature einen enormen Mehrwert – alles ohne den SQL Server zu verlassen. Aber auch hier ein warnendes Wort zur Performance: Reguläre Ausdrücke sollten definitiv nur dort eingesetzt werden, wo es anders nicht sinnvoll geht.

Fuzzy String Matching – wenn Gleichheit zu genau ist

Mit SQL Server 2025 zieht endlich moderne Textähnlichkeit direkt in T-SQL ein. Microsoft führt vier neue Funktionen ein, die auf bewährten Algorithmen des Fuzzy String Matching basieren: EDIT_DISTANCE(), EDIT_DISTANCE_SIMILARITY(), JARO_WINKLER_DISTANCE() und JARO_WINKLER_SIMILARITY().

Damit lassen sich Zeichenketten vergleichen, ohne sie vorher zu normalisieren oder über CLR-Code an externe Logik auszulagern. EDIT_DISTANCE() liefert die klassische Levenshtein-Distanz – also die minimale Anzahl von Einfüge-, Lösch- oder Ersetzen-Operationen, um aus einem String den anderen zu machen:

 

SELECT EDIT_DISTANCE('Mueller', 'Muller'); -- Ergebnis: 1

 

EDIT_DISTANCE_SIMILARITY() gibt statt der Anzahl der Änderungen einen Wert zwischen 0 und 1 zurück, in dem die Länge der Zeichenketten berücksichtig wird – perfekt für Filter oder Ranking nach Ähnlichkeit:

 

SELECT EDIT_DISTANCE_SIMILARITY('Mueller', 'Müller'); -- Ergebnis: 0.83

 

Noch feiner wird es mit Jaro-Winkler: Dieser Algorithmus gewichtet übereinstimmende Präfixe stärker – besonders nützlich bei Namen, die sich nur leicht unterscheiden:

 

SELECT JARO_WINKLER_DISTANCE('Miller', 'Mueller'); -- Ergebnis: 0.18
 
 SELECT JARO_WINKLER_SIMILARITY('Miller', 'Mueller'); -- Ergebnis: 0.82

 

Alle vier Funktionen sind deterministisch und können in Joins, WHERE-Klauseln und sogar ORDER BY verwendet werden. So lassen sich unscharfe Vergleiche endlich direkt im SQL-Server durchführen – ohne Funktionsaufrufe außerhalb der Engine. Ob Dublettenprüfung, ETL-Vergleiche oder die Suche nach „fast gleichen“ Kundennamen: Diese Funktionen machen Fuzzy-Matching zu einem nativen Feature – präzise, performant und endlich offiziell unterstützt.

Preview-Feature

Auch im SQL Server 2025 Release GA (General Availability) ist dies ein Preview-Feature und muss daher (noch) via ALTER DATABASE SCOPED CONFIGURATION SET PREVIEW_FEATURES = ON; aktiviert werden.

Fazit

SQL ist keine Textsuche, sondern Logik. Wer versteht, wie der Server denkt, wird bessere Ergebnisse und bessere Performance erzielen. IS NULL schützt vor Denkfehlern, IS DISTINCT FROM vereinfacht Code, Fuzzy String Matching bringt Praxisnähe, und LIKE bleibt die universelle Waffe. Letzteres gilt auch für Reguläre Ausdrücke.

Die Vektor-Suche im Zusammenspiel mit KI (semantische Suche) könnte hier in der Zukunft noch ein „Gamechanger“ werden – wenn man die (meist externe) KI hier einsetzten möchte.

Neueste Beiträge

Vektorfunktionen mit pgvector in PostgreSQL - Indizes & Co. in PostgreSQL, Teil 6
Bei der Vektorsuche legt PostgreSQL mit pgvector den Schwerpunkt auf Kombinierbarkeit: Vektoren werden zu sortierbaren Werten, <-> wird zu einem erstklassigen Ordnungsoperator und HNSW wird zu einer weiteren Indexzugriffsmethode, die der Planer berücksichtigen kann.
6 Minuten
Batterie-Management mit SignalRC - Der DDC-Truck, Teil 4
Das Batterie-Management-System (BMS) von RC-Modellen benötigt verlässliche Telemetrie.
6 Minuten
12. Feb 2026
Common Table Expressions (CTEs) - Acht Kostbarkeiten in T-SQL, Teil 6
Sind CTEs elegante Zwischentabellen oder nur temporäre Illusionen?
7 Minuten

Das könnte Dich auch interessieren

BRIN-Indizes in PostgreSQL - Indizes & Co. in PostgreSQL, Teil 4
PostgreSQL mit BRIN vertritt die Idee, dass ein Index unvollkommen sein kann, solange er kostengünstig und in großem Maßstab effektiv ist. So entsteht eine pragmatische Optimierung, die Präzision gegen Einfachheit eintauscht – und dabei gewinnt.
6 Minuten
Partitionierung - Acht Kostbarkeiten in T-SQL, Teil 4
Daten häppchenweise oder: Was ist Partitionierung und warum?
7 Minuten
26. Jan 2026
Row Level Security - Acht Kostbarkeiten in T-SQL, Teil 3
Zugang nur für geladene Gäste: Mit RLS wacht der Türsteher direkt im SQL Server.
7 Minuten
19. Jan 2026
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige