K tomu potřebujete dynamické SQL. Takže musíte být připraveni vypořádat se s možným SQL injection.
Základní dotaz
Základní dotaz pro vygenerování potřebného příkazu DML může vypadat takto:
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_%';
Vrátí:
UPDATE tbl SET (foo_a, foo_b, foo_c) = (NULL, NULL, NULL);
-
Používám "syntaxi seznamu sloupců silný> " z
UPDATE
zkrátit kód a zjednodušit úlohu. -
Dotazuji se na systémové katalogy místo informační schéma protože ten druhý, ačkoli je standardizovaný a zaručeně přenosný napříč hlavními verzemi, je také notoricky pomalý a někdy nepraktický. Existují pro a proti, několikrát jsme to zde na SO probírali. Pro více informací vyhledejte klíčová slova.
-
quote_ident()
pro názvy sloupců zabraňuje vkládání SQL a je také nezbytný pro libovolné nestandardní názvy sloupců. -
Zapomněl jste zmínit svou verzi Postgres. Agregační funkce
string_agg()
vyžaduje 9.0+.
Plná automatizace s funkcí PL/pgSQL
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.';
Volejte:
SELECT * FROM f_update_cols('myschema.tbl', 'foo%');
-
Aby byla funkce praktičtější, vrací informace popsané v komentáři. Další informace o získání stavu výsledku v plpgsql v příručce.
-
Používám proměnnou
_sql
podržet řetězec dotazu, abych mohl shromáždit počet nalezených sloupců (col_ct
) ve stejném dotazu. -
Typ identifikátoru objektu
regclass
je nejúčinnějším způsobem, jak se automaticky vyhnout vkládání SQL (a dezinfikovat nestandardní názvy) i pro název tabulky. Můžete použít názvy tabulek s kvalifikací pro schéma aby se předešlo nejasnostem. Doporučil bych to udělat, pokud máte ve své databázi více schémat! Další podrobnosti v této související otázce:
Název tabulky jako parametr funkce PostgreSQL