Der effizienteste Weg, dies zu erreichen:
- Führen Sie ein einzelnes
UPDATE
aus pro Tisch. - Nur Nullable-Spalten aktualisieren (nicht definiert
NOT NULL
) mit einem beliebigen leeren String. - Aktualisiere nur Zeilen mit tatsächlich leeren Zeichenfolgen.
- Lassen Sie andere Werte unverändert.
Diese verwandte Antwort hat eine plpgsql-Funktion, die UPDATE
erstellt und ausführt Befehl unter Verwendung des Systemkatalogs pg_attribute
automatisch und sicher für jede gegebene Tabelle:
- Leere Zeichenfolgen durch Nullwerte ersetzen
Verwenden der Funktion f_empty2null()
Von dieser Antwort aus können Sie ausgewählte Tabellen wie folgt durchlaufen:
DO
$do$
DECLARE
_tbl regclass;
BEGIN
FOR _tbl IN
SELECT c.oid::regclass
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r' -- only regular tables
AND n.nspname NOT LIKE 'pg_%' -- exclude system schemas
LOOP
RAISE NOTICE $$PERFORM f_empty2null('%');$$, _tbl;
-- PERFORM f_empty2null(_tbl); -- uncomment to prime the bomb
END LOOP;
END
$do$;
Vorsicht! Dadurch werden alle leeren Zeichenfolgen in allen Spalten aller Benutzertabellen in der DB aktualisiert. Stellen Sie sicher, dass Sie das wollen, oder es könnte Ihre Datenbank zerstören.
Sie benötigen UPDATE
Privilegien auf alle ausgewählten Tabellen natürlich.
Als Kindersicherung habe ich die Zuladung kommentiert.
Sie haben vielleicht bemerkt, dass ich direkt die Systemkataloge verwende, nicht das Informationsschema (was auch funktionieren würde). Dazu:
- Überprüfen, ob eine Tabelle in einem bestimmten Schema existiert
- Abfrage zur Rückgabe von Ausgabespaltennamen und Datentypen einer Abfrage, Tabelle oder Ansicht
Für wiederholten Gebrauch
Hier ist eine integrierte Lösung für die wiederholte Verwendung. Ohne Sicherheitseinrichtungen:
CREATE OR REPLACE FUNCTION f_all_empty2null(OUT _tables int, OUT _rows int) AS
$func$
DECLARE
_typ CONSTANT regtype[] := '{text, bpchar, varchar, \"char\"}';
_sql text;
_row_ct int;
BEGIN
_tables := 0; _rows := 0;
FOR _sql IN
SELECT format('UPDATE %s SET %s WHERE %s'
, t.tbl
, string_agg(format($$%1$s = NULLIF(%1$s, '')$$, t.col), ', ')
, string_agg(t.col || $$ = ''$$, ' OR '))
FROM (
SELECT c.oid::regclass AS tbl, quote_ident(attname) AS col
FROM pg_namespace n
JOIN pg_class c ON c.relnamespace = n.oid
JOIN pg_attribute a ON a.attrelid = c.oid
WHERE n.nspname NOT LIKE 'pg_%' -- exclude system schemas
AND c.relkind = 'r' -- only regular tables
AND a.attnum >= 1 -- exclude tableoid & friends
AND NOT a.attisdropped -- exclude dropped columns
AND NOT a.attnotnull -- exclude columns defined NOT NULL!
AND a.atttypid = ANY(_typ) -- only character types
ORDER BY a.attnum
) t
GROUP BY t.tbl
LOOP
EXECUTE _sql;
GET DIAGNOSTICS _row_ct = ROW_COUNT; -- report nr. of affected rows
_tables := _tables + 1;
_rows := _rows + _row_ct;
END LOOP;
END
$func$ LANGUAGE plpgsql;
Aufruf:
SELECT * FROM pg_temp.f_all_empty2null();
Rückgabe:
_tables | _rows
---------+---------
23 | 123456
Hinweis wie ich sowohl Tabellen- als auch Spaltennamen richtig maskiert habe!
c.oid::regclass AS tbl, quote_ident(attname) AS col
Bedenken Sie:
- Tabellenname als PostgreSQL-Funktionsparameter
Vorsicht! Dieselbe Warnung wie oben.
Beachten Sie auch die grundlegende Erklärung in der Antwort, die ich oben verlinkt habe:
- Leere Zeichenfolgen durch Nullwerte ersetzen