Con trỏ rõ ràng hiếm khi cần thiết trong plpgsql. Sử dụng con trỏ ngầm đơn giản hơn và nhanh hơn của mộtFOR
vòng lặp:
Lưu ý: Vì tên bảng không phải là duy nhất cho mỗi cơ sở dữ liệu, bạn phải đảm bảo tên bảng đủ điều kiện lược đồ. Ngoài ra, tôi giới hạn hàm ở lược đồ mặc định 'công khai'. Thích ứng với nhu cầu của bạn, nhưng hãy chắc chắn loại trừ các lược đồ hệ thống pg_*
và information_schema
.
Hãy rất cẩn thận với các chức năng này. Họ nuke cơ sở dữ liệu của bạn. Tôi đã thêm một thiết bị an toàn cho trẻ em. Nhận xét RAISE NOTICE
dòng và không chú EXECUTE
ý đến nguyên tố bom ...
CREATE OR REPLACE FUNCTION f_truncate_tables(_username text)
RETURNS void AS
$func$
DECLARE
_tbl text;
_sch text;
BEGIN
FOR _sch, _tbl IN
SELECT schemaname, tablename
FROM pg_tables
WHERE tableowner = _username
AND schemaname = 'public'
LOOP
RAISE NOTICE '%',
-- EXECUTE -- dangerous, test before you execute!
format('TRUNCATE TABLE %I.%I CASCADE', _sch, _tbl);
END LOOP;
END
$func$ LANGUAGE plpgsql;
format()
yêu cầu Postgres 9.1 trở lên. Trong các phiên bản cũ hơn nối chuỗi truy vấn như thế này:
'TRUNCATE TABLE ' || quote_ident(_sch) || '.' || quote_ident(_tbl) || ' CASCADE';
Lệnh đơn, không lặp
Vì chúng ta có thể TRUNCATE
nhiều bảng cùng một lúc, chúng ta không cần bất kỳ con trỏ hoặc vòng lặp nào cả:
Tổng hợp tất cả các tên bảng và thực hiện một câu lệnh. Đơn giản hơn, nhanh hơn:
CREATE OR REPLACE FUNCTION f_truncate_tables(_username text)
RETURNS void AS
$func$
BEGIN
RAISE NOTICE '%',
-- EXECUTE -- dangerous, test before you execute!
(SELECT 'TRUNCATE TABLE '
|| string_agg(format('%I.%I', schemaname, tablename), ', ')
|| ' CASCADE'
FROM pg_tables
WHERE tableowner = _username
AND schemaname = 'public'
);
END
$func$ LANGUAGE plpgsql;
Gọi:
SELECT truncate_tables('postgres');
Truy vấn tinh chỉnh
Bạn thậm chí không cần một chức năng. Trong Postgres 9.0+, bạn có thể thực thi các lệnh động trong một DO
câu lệnh. Và trong Postgres 9.5+, cú pháp có thể đơn giản hơn nữa:
DO
$func$
BEGIN
RAISE NOTICE '%',
-- EXECUTE
(SELECT 'TRUNCATE TABLE ' || string_agg(oid::regclass::text, ', ') || ' CASCADE'
FROM pg_class
WHERE relkind = 'r' -- only tables
AND relnamespace = 'public'::regnamespace
);
END
$func$;
Về sự khác biệt giữa pg_class
, pg_tables
và information_schema.tables
:
Giới thiệu regclass
và trích dẫn tên bảng:
Để sử dụng nhiều lần
Tạo cơ sở dữ liệu "mẫu" (đặt tên cho nó my_template
) với cấu trúc vanilla của bạn và tất cả các bảng trống. Sau đó trải qua một DROP
/CREATE DATABASE
chu kỳ:
DROP DATABASE mydb;
CREATE DATABASE mydb TEMPLATE my_template;
Cái này cực nhanh , bởi vì Postgres sao chép toàn bộ cấu trúc ở cấp độ tệp. Không có vấn đề tương tranh hoặc chi phí khác làm chậm bạn.
Nếu các kết nối đồng thời ngăn bạn bỏ DB, hãy xem xét: