Explizite Cursor werden in plpgsql selten benötigt. Verwenden Sie den einfacheren und schnelleren impliziten Cursor einer FOR
Schleife:
Hinweis: Da Tabellennamen pro Datenbank nicht eindeutig sind, müssen Sie Tabellennamen schemaqualifizieren, um sicherzugehen. Außerdem beschränke ich die Funktion auf das Standardschema 'public'. Passen Sie sich Ihren Anforderungen an, schließen Sie jedoch die Systemschemata pg_*
und aus information_schema
.
Seien Sie sehr vorsichtig mit diesen Funktionen. Sie zerstören Ihre Datenbank. Ich habe eine Kindersicherung hinzugefügt. Kommentieren Sie die RAISE NOTICE
Linie und kommentieren Sie, EXECUTE
um die Bombe zu zünden ...
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()
erfordert Postgres 9.1 oder höher. In älteren Versionen verketten Sie die Abfragezeichenfolge wie folgt:
'TRUNCATE TABLE ' || quote_ident(_sch) || '.' || quote_ident(_tbl) || ' CASCADE';
Einzelbefehl, keine Schleife
Da wir TRUNCATE
mehrere Tabellen gleichzeitig erstellen können, benötigen wir überhaupt keinen Cursor oder keine Schleife:
Aggregieren Sie alle Tabellennamen und führen Sie eine einzelne Anweisung aus. Einfacher, schneller:
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;
Anruf:
SELECT truncate_tables('postgres');
Verfeinerte Abfrage
Sie brauchen nicht einmal eine Funktion. In Postgres 9.0+ können Sie dynamische Befehle in einer DO
Anweisung ausführen . Und in Postgres 9.5+ kann die Syntax noch einfacher sein:
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$;
Über den Unterschied zwischen pg_class
, pg_tables
und information_schema.tables
:
Über regclass
und zitierte Tabellennamen:
Für den wiederholten Gebrauch
Erstellen Sie eine "Vorlagendatenbank" (nennen wir es my_template
) mit Ihrer Vanillestruktur und allen leeren Tabellen. Dann gehen Sie durch einen DROP
/CREATE DATABASE
Zyklus:
DROP DATABASE mydb;
CREATE DATABASE mydb TEMPLATE my_template;
Das geht extrem schnell , da Postgres die gesamte Struktur auf Dateiebene kopiert. Keine Parallelitätsprobleme oder anderer Overhead, der Sie verlangsamt.
Wenn gleichzeitige Verbindungen Sie davon abhalten, die Datenbank zu löschen, beachten Sie Folgendes: