Kursor eksplisit jarang dibutuhkan dalam plpgsql. Gunakan kursor implisit yang lebih sederhana dan lebih cepat dari sebuah FOR
loop:
Catatan: Karena nama tabel tidak unik untuk setiap basis data, Anda harus memastikan skema-kualifikasi nama tabel untuk memastikan. Juga, saya membatasi fungsi ke skema 'publik' default. Sesuaikan dengan kebutuhan Anda, tetapi pastikan untuk mengecualikan skema sistem pg_*
dan information_schema
.
Berhati -hatilah dengan fungsi-fungsi ini. Mereka mengabaikan database Anda. Saya menambahkan perangkat keamanan anak. Komentari RAISE NOTICE
garis dan batalkan komentar EXECUTE
untuk meledakkan 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()
membutuhkan Postgres 9.1 atau lebih baru. Di versi yang lebih lama, gabungkan string kueri seperti ini:
'TRUNCATE TABLE ' || quote_ident(_sch) || '.' || quote_ident(_tbl) || ' CASCADE';
Perintah tunggal, tanpa loop
Karena kita dapat TRUNCATE
beberapa tabel sekaligus, kita tidak memerlukan kursor atau loop sama sekali:
Gabungkan semua nama tabel dan jalankan satu pernyataan. Lebih sederhana, lebih cepat:
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;
Panggilan:
SELECT truncate_tables('postgres');
Kueri yang disempurnakan
Anda bahkan tidak memerlukan fungsi. Di Postgres 9.0+ Anda dapat menjalankan perintah dinamis dalam sebuah DO
pernyataan. Dan dalam Postgres 9.5+ sintaksanya bisa lebih sederhana:
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$;
Tentang perbedaan antara pg_class
, pg_tables
dan information_schema.tables
:
Tentang regclass
dan mengutip nama tabel:
Untuk penggunaan berulang
Buat database "templat" (sebut saja my_template
) dengan struktur vanilla Anda dan semua tabel kosong. Kemudian, lewati a DROP
/CREATE DATABASE
cycle:
DROP DATABASE mydb;
CREATE DATABASE mydb TEMPLATE my_template;
Ini sangat cepat , karena Postgres menyalin seluruh struktur pada level file. Tidak ada masalah konkurensi atau overhead lainnya yang memperlambat Anda.
Jika koneksi bersamaan membuat Anda tidak menjatuhkan DB, pertimbangkan: