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