PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Perbarui beberapa kolom yang dimulai dengan string tertentu

Anda memerlukan SQL dinamis untuk ini. Jadi, Anda harus siap menghadapi kemungkinan injeksi SQL.

Kueri dasar

Permintaan dasar untuk menghasilkan perintah DML yang diperlukan dapat terlihat seperti ini:

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

Pengembalian:

UPDATE tbl SET (foo_a, foo_b, foo_c) = (NULL, NULL, NULL);
  • Saya menggunakan "sintaks daftar kolom " dari UPDATE untuk mempersingkat kode dan menyederhanakan tugas.

  • Saya menanyakan katalog sistem alih-alih skema informasi karena yang terakhir, sementara distandarisasi dan dijamin portabel di seluruh versi utama, juga terkenal lambat dan terkadang berat. Ada pro dan kontra, kami telah membahas ini beberapa kali di sini di SO. Cari kata kunci untuk informasi lebih lanjut.

  • quote_ident() untuk nama kolom mencegah injeksi SQL dan juga diperlukan untuk apa saja nama kolom non-standar.

  • Anda lupa menyebutkan versi Postgres Anda. Fungsi agregat string_agg() membutuhkan 9.0+.

Otomasi penuh dengan fungsi 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.';

Telepon:

SELECT * FROM f_update_cols('myschema.tbl', 'foo%');
  • Untuk membuat fungsi lebih praktis, ia mengembalikan informasi seperti yang dijelaskan dalam komentar. Selengkapnya tentang mendapatkan status hasil di plpgsql di manual.

  • Saya menggunakan variabel _sql untuk menyimpan string kueri, sehingga saya dapat mengumpulkan jumlah kolom yang ditemukan (col_ct ) dalam kueri yang sama.

  • Jenis pengenal objek regclass adalah cara paling efisien untuk secara otomatis menghindari injeksi SQL (dan membersihkan nama non-standar) untuk nama tabel juga. Anda dapat menggunakan nama tabel yang memenuhi syarat skema untuk menghindari ambiguitas. Saya akan menyarankan untuk melakukannya jika Anda memiliki beberapa skema di db Anda! Detail lebih lanjut dalam pertanyaan terkait ini:
    Nama tabel sebagai parameter fungsi 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. Segarkan tampilan yang terwujud:Konkurensi, perilaku transaksional

  2. Mengubah Hasil Query PostgreSQL ke XML, menggunakan PHP DOM

  3. Kunci asing ke salah satu dari banyak tabel?

  4. Cara membuang PGresult untuk perintah non-SELECT

  5. Bagaimana Fungsi CONCAT() Bekerja di PostgreSQL