Fejlmeddelelsen er kun en s tydelig som manualen på dette:
En plgpsql-funktion omgives automatisk af en transaktionsblok. Det lange og det korte af det:det kan du ikke - direkte. Er der en særlig grund til, at du ikke bare kan kalde DDL-kommandoen?
DROP database $mydb;
Du kan omgå disse begrænsninger med det ekstra modul dblink
som @Igor foreslået. Du skal installere det én gang pr. database - den, hvor du kalder dblink-funktioner, ikke den (anden) du udfører kommandoer i.
Giver dig mulighed for at skrive en funktion ved hjælp af dblink_exec()
sådan her:
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()
forhindrer mulig SQL-injektion.
Ring til:
SELECT f_drop_db('mydb');
Ved succes ser du:
Forbindelsesstrengen kunne endda pege på den samme db, som din session kører i. Kommandoen kører uden for en transaktionsblok, hvilket har to konsekvenser:
- Den kan ikke rulles tilbage.
- Det giver dig mulighed for at ringe til
DROP DATABASE
"ved hjælp af en proxy" fra en funktion.
Du kan oprette en FOREIGN DATA WRAPPER
og en FOREIGN SERVER
for at gemme en forbindelse og forenkle opkaldet:
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');
Bruger standard vedligeholdelse db postgres
, hvilket ville være oplagt valg. Men enhver db er mulig.
Forenklet funktion, der gør brug af 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$;