Съобщението за грешка е просто s ясно като ръководството на това:
Функция plgpsql автоматично се заобикаля от транзакционен блок. Кратко и дълго:не можете да направите това - директно. Има ли конкретна причина да не можете просто да извикате командата DDL?
DROP database $mydb;
Вие можете заобиколете тези ограничения с допълнителния модул dblink
като @Игор предложи. Трябва да го инсталирате веднъж за база данни - тази, в която извиквате dblink функции, а не (другата), в която изпълнявате команди.
Позволява ви да напишете функция, използвайки dblink_exec()
като това:
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()
предотвратява възможно инжектиране на SQL.
Обаждане:
SELECT f_drop_db('mydb');
При успех виждате:
Низът за свързване може дори да сочи към същата база данни, в която се изпълнява вашата сесия. Командата се изпълнява извън транзакционен блок, което има две последствия:
- Не може да се върне назад.
- Позволява ви да извикате
DROP DATABASE
"чрез прокси" от функция.
Можете да създадете FOREIGN DATA WRAPPER
и FOREIGN SERVER
за да съхраните връзка и да опростите повикването:
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');
Използване на поддръжка по подразбиране db postgres
, което би било очевиден избор. Но всеки db е възможен.
Опростена функция, използваща това:
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$;