Case / Accent insensitive suchen

Die Datenbank nimmt es bei der Suche nach Daten immer ziemlich genau. Möchte man es mit der Groß-/Kleinschreibung oder den Akzentzeichen nicht so eng sehen, stellt sich die Frage nach dem "Wie?".

Das "Standard"-Statement

SELECT Name FROM Adressbuch WHERE Name = 'Müller';

sucht alle Datensätze, in denen der Nachname genau Müller ist.

Case insensitive suchen

Einigermaßen einfach ist noch die Suche, die sich für die Groß-/Kleinschreibung nicht interessiert. Das lässt sich bei Firebird noch mit der "üblichen" Variante umsetzen, alles in Groß- oder Kleinbuchstaben umzuwandeln.

SELECT Name FROM Adressbuch WHERE UPPER(Name) = 'MÜLLER';
SELECT Name FROM Adressbuch WHERE LOWER(Name) = 'müller';

Wenn die Datenbank mit dem Unicode-Zeichensatz UTF8 läuft, gibt's noch eine weitere Variante:

SELECT Name FROM Adressbuch 
  WHERE Name COLLATE UNICODE_CI = 'Müller';

Accent insensitive suchen

Manchmal ist aber eine gewisse Unschärfe gewünscht, die über ein "LIKE" hinaus geht, da "LIKE" zu weitläufig wäre.
Das Statement

SELECT Name FROM Adressbuch WHERE Name LIKE 'M_ller'

würde sowohl Müller, als auch Möller finden. Wenn man sich nur für die Namen mit "U-Derivaten" (u, ü, ű, ú, ù) interessiert, dann würde die obige LIKE-Abfrage zu viele bzw. schlicht auch falsche Ergebnisse liefern. Die Lösung liefert (bei Unicode-Datenbanken) hier ebenfalls das Stichwort COLLATE mit dem Zusatz UNICODE_CI_AI:

SELECT Name FROM Adressbuch 
  WHERE Name COLLATE UNICODE_CI_AS = 'Muller';

Zu beachten: Die Accent-insensitive Suche gibt es bei Firebird nur in Kombination mit der Case-insensitiven Suche! Ein UNICODE_CS_AI oder UNICODE_AI gibt es nicht.

Indizes

Egal welche Variante genutzt wird, es müssen Indizes angelegt werden, die die entsprechende Funktion unterstützen. Ein einfacher INDEX auf die Spalte "Name" würde nur durch die normale (exakte) Suche oder die LIKE-Suche genutzt werden. Für die Case-insensitive bzw. die Accent-insensitive Suche sollten entsprechende Indizes angelegt werden (je nachdem, welche Variante genutzt wird):

CREATE INDEX AdrIdxUpper ON Adressbuch 
  COMPUTED BY (UPPER(Name));
CREATE INDEX AdrIdxLower ON Adressbuch 
  COMPUTED BY (LOWER(Name));
CREATE INDEX AdrIdxUniCI ON Adressbuch 
  COMPUTED BY (Name COLLATE UNICODE_CI);
CREATE INDEX AdrIdxUniCIAI ON Adressbuch 
  COMPUTED BY (Name COLLATE UNICODE_CI_AI);

Zu beachten: Die Indizes ziehen nur, wenn in der WHERE-Klausel genau diese Funktion verwendet wird. Bei UPPER/LOWER ist dies ggf. gleich offensichtlich. Aber insbesondere bei der Nutzung von COLLATE ist dies auch so. Wurde der Index mit COLLATE UNICODE_CI angelegt, wird er bei einer Suche über COLLATE UNICODE_CI_AI nicht genutzt und andersrum ist dies auch so. Sprich der Index auf COLLATE UNICODE_CI_AI wird nicht genutzt, wenn nur nach COLLATE UNICODE_CI gesucht wird.