Cách hiệu quả nhất để đạt được điều này:
- Chạy một
UPDATE
duy nhất mỗi bảng. - Chỉ cập nhật các cột có thể rỗng (không được xác định
NOT NULL
) với bất kỳ chuỗi trống thực tế nào. - Chỉ cập nhật các hàng có bất kỳ chuỗi trống thực sự nào.
- Giữ nguyên các giá trị khác.
Câu trả lời liên quan này có một hàm plpgsql xây dựng và chạy UPDATE
lệnh sử dụng danh mục hệ thống pg_attribute
tự động và an toàn cho bất kỳ bảng nhất định nào:
- Thay thế các chuỗi trống bằng các giá trị rỗng
Sử dụng hàm f_empty2null()
từ câu trả lời này, bạn có thể lặp qua các bảng đã chọn như sau:
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$;
Cẩn thận! Điều này cập nhật tất cả các chuỗi trống trong tất cả các cột của tất cả các bảng người dùng trong DB. Hãy chắc chắn rằng đó là những gì bạn muốn nếu không nó có thể làm hỏng cơ sở dữ liệu của bạn.
Bạn cần UPDATE
tất nhiên là các đặc quyền trên tất cả các bảng đã chọn.
Với tư cách là một thiết bị an toàn cho trẻ em, tôi đã nhận xét là tải trọng.
Bạn có thể lưu ý rằng tôi sử dụng danh mục hệ thống trực tiếp, không phải giản đồ thông tin (cũng sẽ hoạt động). Về điều này:
- Cách kiểm tra xem một bảng có tồn tại trong một lược đồ nhất định không
- Truy vấn để trả về tên cột đầu ra và kiểu dữ liệu của một truy vấn, bảng hoặc chế độ xem
Để sử dụng nhiều lần
Đây là một giải pháp tích hợp để sử dụng nhiều lần. Không có thiết bị an toàn:
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;
Gọi:
SELECT * FROM pg_temp.f_all_empty2null();
Lợi nhuận:
_tables | _rows
---------+---------
23 | 123456
Lưu ý làm cách nào để tôi thoát khỏi cả tên bảng và cột một cách chính xác!
c.oid::regclass AS tbl, quote_ident(attname) AS col
Cân nhắc:
- Tên bảng dưới dạng tham số hàm PostgreSQL
Cẩn thận! Cảnh báo tương tự như trên.
Cũng xem xét giải thích cơ bản trong câu trả lời mà tôi đã liên kết ở trên:
- Thay thế các chuỗi trống bằng các giá trị rỗng