За това ви трябва динамичен SQL. Така че трябва да сте подготвени да се справите с възможно SQL инжектиране.
Основна заявка
Основната заявка за генериране на необходимата DML команда може да изглежда така:
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_%';
Връща:
UPDATE tbl SET (foo_a, foo_b, foo_c) = (NULL, NULL, NULL);
-
Използвам "синтаксис списък-колонасилен> “ от
UPDATE
за да съкратите кода и да опростите задачата. -
Отправям запитване към системните каталози вместо информационна схема тъй като последното, въпреки че е стандартизирано и гарантирано преносимо в основните версии, също е известно бавно и понякога тромаво. Има плюсове и минуси, обсъждали сме това няколко пъти тук в SO. Потърсете ключовите думи за повече информация.
-
quote_ident()
за имената на колоните предотвратява SQL-инжектиране и също така е необходимо за any нестандартни имена на колони. -
Пропуснахте да споменете вашата версия на Postgres. Агрегираната функция
string_agg()
изисква 9.0+.
Пълна автоматизация с 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.';
Обаждане:
SELECT * FROM f_update_cols('myschema.tbl', 'foo%');
-
За да направи функцията по-практична, тя връща информация, както е описано в коментара. Повече за получаване на състоянието на резултата в plpgsql в ръководството.
-
Използвам променливата
_sql
за задържане на низа на заявката, за да мога да събера броя на намерените колони (col_ct
) в същата заявка. -
Типът идентификатор на обект
regclass
е най-ефективният начин за автоматично избягване на SQL инжектиране (и дезинфекция на нестандартни имена) и за името на таблицата. Можете да използвате имена на таблици, подходящи за схема за избягване на неясноти. Бих посъветвал да го направите, ако имате няколко схеми във вашата база данни! Повече подробности в този свързан въпрос:
Име на таблица като параметър на функция на PostgreSQL
-> Демонстрация на SQLfiddle .