For this you need dynamic SQL. Therefore, you should be prepared to deal with a possible SQL injection.
Main request
The basic request for creating the required DML command might look like this:
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_%';
Return:
UPDATE tbl SET (foo_a, foo_b, foo_c) = (NULL, NULL, NULL);
I use UPDATE " column-column syntax " to shorten the code and simplify the task.
I request system catalogs instead of an information scheme , since the latter, being standardized and guaranteed for portability over major versions, is also known as slow and sometimes cumbersome. There are pros and cons, we discussed this several times here on SO. Search for keywords for more information.
quote_ident() for column names prevents SQL injection and is also necessary for any non-standard column names.
You neglected to mention your version of Postgres. The aggregate function string_agg() requires 9.0 +.
Full automation with PL / pgSQL function
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
Call:
SELECT * FROM f_update_cols('myschema.tbl', 'foo%');
To make the function more practical, it returns information as described in the comment. Read more about getting result status in plpgsql in the manual.
I use the _sql variable to store the query string, so I can collect the number of columns found ( col_ct ) in the same query.
The regclass object identifier type is the most efficient way to automatically exclude SQL injections (and disinfect non-standard names) for a table name. You can use table names with a table to avoid ambiguities. I would advise doing this if you have multiple circuits in your db! More details in this question:
Table name as parameter of PostgreSQL function
β SQLfiddle demo .
Erwin Brandstetter May 02 '13 at 23:00 2013-05-02 23:00
source share