Hallo zusammen,
ich habe häufig die Anforderung, dass alle TEXT Felder einer Tabelle getrimmt werden sollen - z. B. wenn es um den Abgleich von Matchcodes mit anderen Systemen, oder die Sortierreihenfolge geht.
Dazu habe ich mir einen Trigger gebastelt, welcher dynamisch alle Felder der auslösenden Relation trimmt. Mit diesem Post möchte ich euch, solltet ihr vor der gleichen Herausforderung stehen, diesen Trigger zur Verfügung stellen: einfach als Backend-Funktion mit dem Kennzeichen "Trigger" importieren, und für die gewünschten Tabellen als AFTER (!) INSERT/UPDATE Trigger aktivieren.
$BODY$
DECLARE
field_name TEXT;
field_value TEXT;
trimmed_value TEXT;
set_clauses TEXT := '';
first BOOLEAN := true;
BEGIN
-- Trigger gegen Rekursion absichern
IF pg_trigger_depth() > 1 THEN
RETURN NULL;
END IF;
-- Felder der Tabelle ermitteln
FOR field_name IN
SELECT column_name
FROM information_schema.columns
WHERE table_name = TG_TABLE_NAME
AND table_schema = TG_TABLE_SCHEMA
AND data_type IN ('text', 'character varying')
AND column_name != 'id'
LOOP
-- Feldwert ermitteln
EXECUTE format('SELECT ($1).%I', field_name)
INTO field_value
USING NEW;
-- Wenn nicht NULL, dann Feldwert trimmen
IF field_value IS NOT NULL THEN
trimmed_value := TRIM(BOTH FROM field_value);
-- Wenn TRIM zu einem geänderten Feldwert führt, ...
IF trimmed_value IS DISTINCT FROM field_value THEN
-- ... dann SET-Klausel für UPDATE ergänzen
IF NOT first THEN
set_clauses := set_clauses || ', ';
END IF;
set_clauses := set_clauses || format('%I = %L', field_name, trimmed_value);
first := false;
END IF;
END IF;
END LOOP;
-- Alle Feldwerte mit einem einzigen UPDATE aktualisieren
IF set_clauses != '' THEN
EXECUTE format(
'UPDATE %I.%I SET %s WHERE id = %L',
TG_TABLE_SCHEMA,
TG_TABLE_NAME,
set_clauses,
NEW.id
);
END IF;
RETURN NULL; -- NULL (bei AFTER-Trigger kein NEW)
END;
$BODY$