PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Zaktualizuj wiele kolumn, które zaczynają się od określonego ciągu

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

-> Demo 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. knex:jaki jest właściwy sposób tworzenia tablicy z wyników?

  2. PG::Błąd:SELECT DISTINCT, ORDER BY wyrażenia muszą pojawić się na liście wyboru

  3. PostgreSQL a wersje jądra Linux

  4. Częściowy unikalny indeks PostgreSQL i upsert

  5. Uwierzytelnianie bazy danych CAS nie działa