Felmeddelandet är bara ett s tydligt som handboken på detta:
En plgpsql-funktion omges automatiskt av ett transaktionsblock. Det långa och det korta av det:du kan inte göra det - direkt. Finns det någon speciell anledning till att du inte bara kan anropa DDL-kommandot?
DROP database $mydb;
Du kan kringgå dessa begränsningar med tilläggsmodulen dblink
som @Igor föreslog. Du måste installera den en gång per databas - den där du anropar dblink-funktioner, inte den (andra) du kör kommandon i.
Låter dig skriva en funktion med dblink_exec()
så här:
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()
förhindrar eventuell SQL-injektion.
Ring:
SELECT f_drop_db('mydb');
Om framgång ser du:
Anslutningssträngen kan till och med peka på samma db som din session körs i. Kommandot körs utanför ett transaktionsblock, vilket har två konsekvenser:
- Den kan inte återställas.
- Det låter dig ringa
DROP DATABASE
"genom en proxy" från en funktion.
Du kan skapa en FOREIGN DATA WRAPPER
och en FOREIGN SERVER
för att lagra en anslutning och förenkla samtalet:
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');
Använder standardunderhåll db postgres
, vilket vore ett självklart val. Men vilken db som helst är möjlig.
Förenklad funktion som använder det:
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$;