Cara paling efisien untuk mencapai ini:
- Jalankan satu
UPDATE
per tabel. - Hanya perbarui kolom yang dapat dibatalkan (tidak ditentukan
NOT NULL
) dengan string kosong yang sebenarnya. - Hanya perbarui baris dengan string kosong yang sebenarnya.
- Biarkan nilai lain tidak berubah.
Jawaban terkait ini memiliki fungsi plpgsql yang membangun dan menjalankan UPDATE
perintah menggunakan katalog sistem pg_attribute
secara otomatis dan aman untuk tabel apa pun:
- Ganti string kosong dengan nilai null
Menggunakan fungsi f_empty2null()
dari jawaban ini, Anda dapat mengulang tabel yang dipilih seperti ini:
DO
$do$
DECLARE
_tbl regclass;
BEGIN
FOR _tbl IN
SELECT c.oid::regclass
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r' -- only regular tables
AND n.nspname NOT LIKE 'pg_%' -- exclude system schemas
LOOP
RAISE NOTICE $$PERFORM f_empty2null('%');$$, _tbl;
-- PERFORM f_empty2null(_tbl); -- uncomment to prime the bomb
END LOOP;
END
$do$;
Hati-hati! Ini memperbarui semua string kosong di semua kolom dari semua tabel pengguna di DB. Pastikan itu yang Anda inginkan atau database Anda akan rusak.
Anda perlu UPDATE
hak istimewa pada semua tabel yang dipilih, tentu saja.
Sebagai perangkat keselamatan anak, saya mengomentari muatannya.
Anda mungkin telah mencatat bahwa saya menggunakan katalog sistem secara langsung, bukan skema informasi (yang juga akan berfungsi). Tentang ini:
- Cara memeriksa apakah ada tabel dalam skema tertentu
- Kueri untuk mengembalikan nama kolom keluaran dan tipe data kueri, tabel, atau tampilan
Untuk penggunaan berulang
Berikut adalah solusi terintegrasi untuk penggunaan berulang. Tanpa perangkat keamanan:
CREATE OR REPLACE FUNCTION f_all_empty2null(OUT _tables int, OUT _rows int) AS
$func$
DECLARE
_typ CONSTANT regtype[] := '{text, bpchar, varchar, \"char\"}';
_sql text;
_row_ct int;
BEGIN
_tables := 0; _rows := 0;
FOR _sql IN
SELECT format('UPDATE %s SET %s WHERE %s'
, t.tbl
, string_agg(format($$%1$s = NULLIF(%1$s, '')$$, t.col), ', ')
, string_agg(t.col || $$ = ''$$, ' OR '))
FROM (
SELECT c.oid::regclass AS tbl, quote_ident(attname) AS col
FROM pg_namespace n
JOIN pg_class c ON c.relnamespace = n.oid
JOIN pg_attribute a ON a.attrelid = c.oid
WHERE n.nspname NOT LIKE 'pg_%' -- exclude system schemas
AND c.relkind = 'r' -- only regular tables
AND a.attnum >= 1 -- exclude tableoid & friends
AND NOT a.attisdropped -- exclude dropped columns
AND NOT a.attnotnull -- exclude columns defined NOT NULL!
AND a.atttypid = ANY(_typ) -- only character types
ORDER BY a.attnum
) t
GROUP BY t.tbl
LOOP
EXECUTE _sql;
GET DIAGNOSTICS _row_ct = ROW_COUNT; -- report nr. of affected rows
_tables := _tables + 1;
_rows := _rows + _row_ct;
END LOOP;
END
$func$ LANGUAGE plpgsql;
Telepon:
SELECT * FROM pg_temp.f_all_empty2null();
Pengembalian:
_tables | _rows
---------+---------
23 | 123456
Catatan bagaimana saya lolos dari nama tabel dan kolom dengan benar!
c.oid::regclass AS tbl, quote_ident(attname) AS col
Pertimbangkan:
- Nama tabel sebagai parameter fungsi PostgreSQL
Hati-hati! Peringatan yang sama seperti di atas.
Pertimbangkan juga penjelasan dasar dalam jawaban yang saya tautkan di atas:
- Ganti string kosong dengan nilai null