PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Актуализирайте няколко колони, които започват с конкретен низ

За това ви трябва динамичен 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 .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Linux файлови системи и контролни точки на PostgreSQL

  2. Как мога да генерирам поредица от повтарящи се числа в PostgreSQL?

  3. Hibernate и Postgresql - клас генератор във файл за картографиране на хибернация

  4. Как да използвам ANY вместо IN в клауза WHERE с Rails?

  5. Проблем със Sqlalchemy и вмъкване на масив от jsonb в postgresql