Potrzebujesz do tego dynamicznego SQL. Musisz więc być przygotowany na radzenie sobie z możliwym wstrzyknięciem SQL.
Podstawowe zapytanie
Podstawowe zapytanie do wygenerowania potrzebnego polecenia DML może wyglądać tak:
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_%';
Zwroty:
UPDATE tbl SET (foo_a, foo_b, foo_c) = (NULL, NULL, NULL);
-
Używam "składni listy kolumn " z
UPDATE
aby skrócić kod i uprościć zadanie. -
Wysyłam zapytania do katalogów systemowych zamiast schematu informacji ponieważ ta ostatnia, mimo że jest znormalizowana i gwarantuje przenośność w głównych wersjach, jest również notorycznie powolna i czasami nieporęczna. Są plusy i minusy, omawialiśmy to kilka razy tutaj na SO. Wyszukaj słowa kluczowe, aby uzyskać więcej informacji.
-
quote_ident()
dla nazw kolumn zapobiega wstrzykiwaniu SQL i jest również niezbędny dla dowolnych niestandardowe nazwy kolumn. -
Nie wspomniałeś o swojej wersji Postgresa. Funkcja agregująca
string_agg()
wymaga 9.0+.
Pełna automatyzacja z funkcją 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.';
Zadzwoń:
SELECT * FROM f_update_cols('myschema.tbl', 'foo%');
-
Aby funkcja była bardziej praktyczna, zwraca informacje opisane w komentarzu. Więcej o uzyskiwaniu statusu wyniku w plpgsql w instrukcji.
-
Używam zmiennej
_sql
do przechowywania ciągu zapytania, abym mógł zebrać liczbę znalezionych kolumn (col_ct
) w tym samym zapytaniu. -
Typ identyfikatora obiektu
regclass
to najskuteczniejszy sposób automatycznego unikania wstrzykiwania SQL (i oczyszczania niestandardowych nazw) również dla nazwy tabeli. Możesz użyć nazw tabel kwalifikowanych schematem aby uniknąć niejasności. Radziłbym to zrobić, jeśli masz wiele schematów w swoim db! Więcej szczegółów w tym powiązanym pytaniu:
Nazwa tabeli jako parametr funkcji PostgreSQL