Dazu benötigen Sie dynamisches SQL. Sie müssen also darauf vorbereitet sein, mit einer möglichen SQL-Injektion umzugehen.
Grundlegende Abfrage
Die grundlegende Abfrage zum Generieren des benötigten DML-Befehls kann wie folgt aussehen:
SELECT format('UPDATE tbl SET (%s) = (%s)'
,string_agg (quote_ident(attname), ', ')
,string_agg ('NULL', ', ')
)
FROM pg_attribute
WHERE attrelid = 'tbl'::regclass
AND NOT attisdropped
AND attnum > 0
AND attname ~~ 'foo_%';
Rückgabe:
UPDATE tbl SET (foo_a, foo_b, foo_c) = (NULL, NULL, NULL);
-
Ich verwende die "Spaltenlistensyntax " von
UPDATE
um den Code zu verkürzen und die Aufgabe zu vereinfachen. -
Ich frage die Systemkataloge ab anstelle von Informationsschema denn letzteres ist, obwohl es standardisiert und garantiert über Hauptversionen portierbar ist, auch notorisch langsam und manchmal unhandlich. Es gibt Vor- und Nachteile, wir haben das hier auf SO mehrfach diskutiert. Suchen Sie nach den Schlüsselwörtern, um weitere Informationen zu erhalten.
-
quote_ident()
für die Spaltennamen verhindert SQL-Injection und ist auch für any notwendig nicht standardmäßige Spaltennamen. -
Sie haben es versäumt, Ihre Postgres-Version zu erwähnen. Die Aggregatfunktion
string_agg()
erfordert 9.0+.
Vollständige Automatisierung mit PL/pgSQL-Funktion
CREATE OR REPLACE FUNCTION f_update_cols(_tbl regclass, _col_pattern text
, OUT row_ct int, OUT col_ct int)
RETURNS record AS
$func$
DECLARE
_sql text;
BEGIN
SELECT format('UPDATE tbl SET (%s) = (%s)'
,string_agg (quote_ident(attname), ', ')
,string_agg ('NULL', ', ')
)
,count(*)::int
INTO _sql, col_ct
FROM pg_attribute
WHERE attrelid = _tbl
AND NOT attisdropped -- no dropped columns
AND attnum > 0 -- no system columns
AND attname ~~ _col_pattern; -- only columns matching pattern
-- RAISE NOTICE '%', _sql; -- output generated SQL for debugging
EXECUTE _sql;
GET DIAGNOSTICS row_ct = ROW_COUNT;
END
$func$ LANGUAGE plpgsql;
COMMENT ON FUNCTION f_update_cols(regclass, text)
IS 'Updates all columns of table _tbl ($1)
that match _col_pattern ($2) in a LIKE expression.
Returns the count of columns (col_ct) and rows (row_ct) affected.';
Aufruf:
SELECT * FROM f_update_cols('myschema.tbl', 'foo%');
-
Um die Funktion praktischer zu gestalten, gibt sie Informationen wie im Kommentar beschrieben zurück. Mehr über Erhalten des Ergebnisstatus in plpgsql im Handbuch.
-
Ich verwende die Variable
_sql
um die Abfragezeichenfolge zu speichern, damit ich die Anzahl der gefundenen Spalten sammeln kann (col_ct
) in derselben Abfrage. -
Der Objektbezeichnertyp
regclass
ist der effizienteste Weg, um auch für den Tabellennamen automatisch eine SQL-Einschleusung zu vermeiden (und nicht standardmäßige Namen zu bereinigen). Sie können schemaqualifizierte Tabellennamen verwenden Unklarheiten zu vermeiden. Ich würde dazu raten, wenn Sie mehrere Schemas in Ihrer Datenbank haben! Weitere Details in dieser verwandten Frage:
Tabellenname als PostgreSQL-Funktionsparameter