W plpgsql rzadko potrzebne są jawne kursory. Za pomocą prostsze i szybsze niejawny wskaźnik o FOR
pętli:
Uwaga: Ponieważ nazwy tabel nie są unikalne dla każdej bazy danych, dla pewności należy kwalifikować nazwy tabel według schematu. Ograniczam również funkcję do domyślnego schematu „public”. Dostosuj się do swoich potrzeb, ale pamiętaj o wykluczeniu schematów systemowych pg_*
i information_schema
.
Zachowaj ostrożność podczas korzystania z tych funkcji. Niszczą twoją bazę danych. Dodałem zabezpieczenie przed dziećmi. Skomentuj RAISE NOTICE
linię i usuń komentarz, EXECUTE
aby zalać bombę ...
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()
wymaga Postgres 9.1 lub nowszego. W starszych wersjach połącz ciąg zapytania w następujący sposób:
'TRUNCATE TABLE ' || quote_ident(_sch) || '.' || quote_ident(_tbl) || ' CASCADE';
Pojedyncze polecenie, bez pętli
Ponieważ możemy TRUNCATE
jednocześnie wiele tabel, nie potrzebujemy żadnego kursora ani pętli:
Zgromadź wszystkie nazwy tabel i wykonaj jedną instrukcję. Prostsze, szybsze:
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;
Połączenie:
SELECT truncate_tables('postgres');
Udoskonalone zapytanie
Nie potrzebujesz nawet funkcji. W Postgres 9.0+ możesz wykonywać dynamiczne polecenia w DO
instrukcji. A w Postgres 9.5+ składnia może być jeszcze prostsza:
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$;
O różnicy między pg_class
, pg_tables
oraz information_schema.tables
:
Informacje regclass
i cytowane nazwy tabel:
Do wielokrotnego użytku
Utwórz bazę danych „szablonu” (nazwijmy ją my_template
) ze swoją strukturą waniliową i wszystkimi pustymi tabelami. Następnie przejdź przez DROP
/CREATE DATABASE
cykl:
DROP DATABASE mydb;
CREATE DATABASE mydb TEMPLATE my_template;
Jest to niezwykle szybkie , ponieważ Postgres kopiuje całą strukturę na poziomie pliku. Żadnych problemów ze współbieżnością ani innych kosztów ogólnych, które spowalniają.
Jeśli równoczesne połączenia uniemożliwiają porzucenie bazy danych, rozważ: