Você precisa de SQL dinâmico para isso. Portanto, você deve estar preparado para lidar com uma possível injeção de SQL.
Consulta básica
A consulta básica para gerar o comando DML necessário pode ser assim:
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_%';
Devoluções:
UPDATE tbl SET (foo_a, foo_b, foo_c) = (NULL, NULL, NULL);
-
Eu uso a "sintaxe de lista de colunas " deUPDATE
para encurtar o código e simplificar a tarefa.
-
Eu consulto os catálogos do sistema em vez de esquema de informações porque o último, embora seja padronizado e garantido para ser portátil nas principais versões, também é notoriamente lento e às vezes difícil de manejar. Existem prós e contras, já discutimos isso várias vezes aqui no SO. Pesquise as palavras-chave para obter mais informações.
-
quote_ident()
para os nomes das colunas impede a injeção de SQL e também é necessário para qualquer nomes de colunas não padrão.
-
Você esqueceu de mencionar sua versão do Postgres. A função agregadastring_agg()
requer 9.0+.
Automação total com função 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.';
Ligar:
SELECT * FROM f_update_cols('myschema.tbl', 'foo%');
-
Para tornar a função mais prática, ela retorna as informações conforme descrito no comentário. Mais sobre como obter o status do resultado em plpgsql no manual.
-
Eu uso a variável_sql
para manter a string de consulta, para que eu possa coletar o número de colunas encontradas (col_ct
) na mesma consulta.
-
O tipo de identificador de objetoregclass
é a maneira mais eficiente de evitar automaticamente a injeção de SQL (e limpar nomes não padrão) para o nome da tabela também. Você pode usar nomes de tabela qualificados por esquema para evitar ambiguidades. Eu aconselharia fazer isso se você tiver vários esquemas em seu banco de dados! Mais detalhes nesta pergunta relacionada:
Nome da tabela como parâmetro de função do PostgreSQL
-> Demonstração do SQLfiddle .