De foutmelding is net zo duidelijk als de handleiding hierover:
Een plgpsql-functie wordt automatisch omgeven door een transactieblok. Lang en kort:dat kun je niet - rechtstreeks. Is er een bepaalde reden waarom je het DDL-commando niet gewoon kunt aanroepen?
DROP database $mydb;
Je kunt omzeil deze beperkingen met de extra module dblink
as @Igor suggereerde. U moet het eenmaal per database installeren - degene waarin u dblink-functies aanroept, niet de (andere) waarin u opdrachten uitvoert.
Hiermee kunt u een functie schrijven met behulp van dblink_exec()
zoals dit:
CREATE OR REPLACE FUNCTION f_drop_db(text)
RETURNS text LANGUAGE sql AS
$func$
SELECT dblink_exec('port=5432 dbname=postgres'
,'DROP DATABASE ' || quote_ident($1))
$func$;
quote_ident()
voorkomt mogelijke SQL-injectie.
Bel:
SELECT f_drop_db('mydb');
Bij succes zie je:
De verbindingsreeks kan zelfs verwijzen naar dezelfde db waarin uw sessie wordt uitgevoerd. De opdracht wordt buiten een transactieblok uitgevoerd, wat twee gevolgen heeft:
- Het kan niet worden teruggedraaid.
- Hiermee kunt u
DROP DATABASE
. aanroepen "via een proxy" vanuit een functie.
Je zou een FOREIGN DATA WRAPPER
. kunnen maken en een FOREIGN SERVER
om een verbinding op te slaan en de oproep te vereenvoudigen:
CREATE FOREIGN DATA WRAPPER postgresql VALIDATOR postgresql_fdw_validator;
CREATE SERVER your_fdw_name_here FOREIGN DATA WRAPPER postgresql
OPTIONS (hostaddr '12.34.56.78', port '5432', dbname 'postgres');
Standaard onderhoud db postgres
gebruiken , wat een voor de hand liggende keuze zou zijn. Maar elke db is mogelijk.
Vereenvoudigde functie die daar gebruik van maakt:
CREATE OR REPLACE FUNCTION f_drop_db(text)
RETURNS text LANGUAGE sql AS
$func$
SELECT dblink_exec('your_fdw_name_here', 'DROP DATABASE ' || quote_ident($1))
$func$;