Firebird: Soundex
2 - Berechnung
Die Berechnung des Soundex ist nach den Vorbereitungen dann fast schon trivial. Das Wort wird in der SP "prc_soundex" zerlegt und über einen LEFT JOIN mit der Tabelle "soundex_weights" verknüpft. Das LEFT ist nötig, um auch nicht in der Tabelle vorhandene Zeichen als erstes Zeichen verwenden zu können.Für diese Berechnung ist die SP "prc_soundex" zuständig. Anhand der ermittelten Gruppe jedes einzelnen Zeichens wird hier der Soundex aufgebaut. Als Besonderheit kann der SP noch die Länge des Soundex übergeben werden, um z.B. längere Soundex zu berechnen.
In der Beispieldatenbank wird die SP "prc_soundex" dazu verwendet, im Trigger "words_BIU0" die Spalten "wrd_soundex_eng" und "wrd_soundex_ger" mit dem englischen bzw. deutschen Soundex zu füllen.
CREATE OR ALTER PROCEDURE "prc_soundex" (
IN_WORD TYPE OF "dom_Word",
IN_LNG TYPE OF "dom_Lng_Token",
IN_SOUNDEX_LENGTH TYPE OF "dom_INT16" = 4)
RETURNS (
OUT_SOUNDEX "dom_Word")
AS
DECLARE VARIABLE L_CURRENT_CHAR TYPE OF "dom_SingleChar";
DECLARE VARIABLE L_LAST_CHAR TYPE OF "dom_SingleChar";
DECLARE VARIABLE L_LENGTH TYPE OF "dom_INT16";
DECLARE VARIABLE L_WEIGHT TYPE OF "dom_INT16";
BEGIN
OUT_SOUNDEX = '' ;
L_LENGTH = 0 ;
L_LAST_CHAR = ASCII_CHAR(0);
FOR
SELECT CASE
WHEN OUT_POSITION = 1
/* An erster Position den ersten Buchstaben ausgeben. */
THEN UPPER(OUT_CHAR)
/* Ansonsten die Gewichtung ausgeben. */
ELSE CAST(MAXVALUE("sxw_weight", 0) AS "dom_SingleChar")
END,
"sxw_weight"
FROM
(
SELECT OUT_POSITION,
OUT_CHAR,
COALESCE("sxw_weight", -1) AS "sxw_weight"
/* Wort in Buchstaben zerlegen */
FROM "prc_soundex_chars"(:IN_WORD)
/* Buchstabengewichtungen lesen */
LEFT JOIN "soundex_weights" ON "sxw_character" = OUT_CHAR
AND "sxw_language" = UPPER(:IN_LNG)
)
WHERE "sxw_weight" BETWEEN -1 AND 9 /* Nur Gewichtungen von -1 bis 9 lesen */
ORDER BY OUT_POSITION
INTO
:L_CURRENT_CHAR,
:L_WEIGHT
DO
BEGIN
/* Nur bis übergebene Soundex-Länge. */
IF (L_LENGTH < IN_SOUNDEX_LENGTH)
THEN
BEGIN
/* Nur hinzufügen, wenn sich das aktuelle Zeichen vom letzten Zeichen */
/* unterscheidet und Gewichtung ungleich -1 ist. Die erste Position */
/* aber immer übernehmen. */
IF ((L_LAST_CHAR <> L_CURRENT_CHAR AND L_WEIGHT >= 0) OR L_LENGTH = 0)
THEN
BEGIN
/* Das Zeichen '0' kennzeichnet ein Trennzeichen für gleiche */
/* Konsonanten (Vokale und Y). */
IF (L_CURRENT_CHAR <> '0' OR L_LENGTH = 0)
THEN
BEGIN
OUT_SOUNDEX = OUT_SOUNDEX || L_CURRENT_CHAR;
L_LENGTH = L_LENGTH + 1 ;
END
/* Aktuelles Zeichen für nächsten Vergleich merken */
L_LAST_CHAR = L_CURRENT_CHAR;
END
END
ELSE
BEGIN
/* Soundex-Länge erreicht */
EXIT;
END
END
/* auf Soundex-Länge auffüllen */
WHILE (L_LENGTH < IN_SOUNDEX_LENGTH)
DO
BEGIN
OUT_SOUNDEX = OUT_SOUNDEX || '0';
L_LENGTH = L_LENGTH + 1 ;
END
END
Suche nach Soundex Werten
Für die Suche wandelt die SP "prc_soundex_list" die Soundex Berechnung in eine selektierbare Abfrage um. Diese gibt genau einen Datensatz zurück und kann damit z.B. in einem JOIN einer Abfrage verwendet werden.CREATE OR ALTER PROCEDURE "prc_soundex_list" (
IN_WORD TYPE OF "dom_Word",
IN_LNG TYPE OF "dom_Lng_Token",
IN_SOUNDEX_LENGTH TYPE OF "dom_INT16" = 4)
RETURNS (
OUT_SOUNDEX "dom_Word")
AS
BEGIN
/* Soundex berechnen */
EXECUTE PROCEDURE "prc_soundex"(IN_WORD, IN_LNG, IN_SOUNDEX_LENGTH)
RETURNING_VALUES OUT_SOUNDEX;
/* als selektierbar ausgeben */
SUSPEND;
END