Komunikat o błędzie jest tak jasny, jak instrukcja w tej sprawie:
Funkcja plgpsql jest automatycznie otoczona blokiem transakcji. Długie i krótkie:nie można tego zrobić – bezpośrednio. Czy jest jakiś szczególny powód, dla którego nie możesz po prostu wywołać polecenia DDL?
DROP database $mydb;
możesz obejść te ograniczenia za pomocą dodatkowego modułu dblink
jako @Igor zasugerował. Musisz zainstalować go raz na bazę danych - tę, w której wywołujesz funkcje dblink, a nie (inną), w której wykonujesz polecenia.
Pozwala na napisanie funkcji przy użyciu dblink_exec()
tak:
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()
zapobiega możliwemu wstrzyknięciu SQL.
Zadzwoń:
SELECT f_drop_db('mydb');
Po sukcesie widzisz:
Ciąg połączenia może nawet wskazywać na tę samą bazę danych, w której działa Twoja sesja. Polecenie działa poza blokiem transakcji, co ma dwie konsekwencje:
- Nie można go cofnąć.
- Pozwala na wywołanie
DROP DATABASE
"za pośrednictwem proxy" z poziomu funkcji.
Możesz utworzyć FOREIGN DATA WRAPPER
i FOREIGN SERVER
aby zapisać połączenie i uprościć połączenie:
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');
Korzystanie z domyślnej bazy danych konserwacji postgres
, co byłoby oczywistym wyborem. Ale każdy db jest możliwy.
Uproszczona funkcja wykorzystująca to:
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$;