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$;