sql >> Databáze >  >> RDS >> PostgreSQL

Aktualizujte více sloupců, které začínají konkrétním řetězcem

K tomu potřebujete dynamické SQL. Takže musíte být připraveni vypořádat se s možným SQL injection.

Základní dotaz

Základní dotaz pro vygenerování potřebného příkazu DML může vypadat takto:

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_%';

Vrátí:

UPDATE tbl SET (foo_a, foo_b, foo_c) = (NULL, NULL, NULL);
  • Používám "syntaxi seznamu sloupců silný> " z UPDATE zkrátit kód a zjednodušit úlohu.

  • Dotazuji se na systémové katalogy místo informační schéma protože ten druhý, ačkoli je standardizovaný a zaručeně přenosný napříč hlavními verzemi, je také notoricky pomalý a někdy nepraktický. Existují pro a proti, několikrát jsme to zde na SO probírali. Pro více informací vyhledejte klíčová slova.

  • quote_ident() pro názvy sloupců zabraňuje vkládání SQL a je také nezbytný pro libovolné nestandardní názvy sloupců.

  • Zapomněl jste zmínit svou verzi Postgres. Agregační funkce string_agg() vyžaduje 9.0+.

Plná automatizace s funkcí 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.';

Volejte:

SELECT * FROM f_update_cols('myschema.tbl', 'foo%');
  • Aby byla funkce praktičtější, vrací informace popsané v komentáři. Další informace o získání stavu výsledku v plpgsql v příručce.

  • Používám proměnnou _sql podržet řetězec dotazu, abych mohl shromáždit počet nalezených sloupců (col_ct ) ve stejném dotazu.

  • Typ identifikátoru objektu regclass je nejúčinnějším způsobem, jak se automaticky vyhnout vkládání SQL (a dezinfikovat nestandardní názvy) i pro název tabulky. Můžete použít názvy tabulek s kvalifikací pro schéma aby se předešlo nejasnostem. Doporučil bych to udělat, pokud máte ve své databázi více schémat! Další podrobnosti v této související otázce:
    Název tabulky jako parametr funkce PostgreSQL

-> SQLfiddle demo .



  1. Jak aktualizovat sloupec identity na serveru SQL?

  2. Oracle:Načíst pomocí TZNAME Je to možné?

  3. Oracle Multiple Update Query

  4. Vytvořte proměnnou tabulky v MySQL