Le message d'erreur est juste un s clair comme le manuel sur ceci :
Une fonction plgpsql est automatiquement entourée d'un bloc de transaction. Le long et le court:vous ne pouvez pas le faire - directement. Y a-t-il une raison particulière pour laquelle vous ne pouvez pas simplement appeler la commande DDL ?
DROP database $mydb;
Vous pouvez contourner ces restrictions avec le module supplémentaire dblink
comme @Igor suggéré. Vous devez l'installer une fois par base de données - celle où vous appelez les fonctions dblink, pas celle dans laquelle vous exécutez des commandes.
Vous permet d'écrire une fonction en utilisant dblink_exec()
comme ceci :
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()
empêche une éventuelle injection SQL.
Appel :
SELECT f_drop_db('mydb');
En cas de succès, vous voyez :
La chaîne de connexion peut même pointer vers la même base de données dans laquelle votre session s'exécute. La commande s'exécute en dehors d'un bloc de transaction, ce qui a deux conséquences :
- Il ne peut pas être annulé.
- Il vous permet d'appeler
DROP DATABASE
"au moyen d'un proxy" à partir d'une fonction.
Vous pouvez créer un FOREIGN DATA WRAPPER
et un FOREIGN SERVER
pour mémoriser une connexion et simplifier l'appel :
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');
Utilisation de la base de données de maintenance par défaut postgres
, ce qui serait un choix évident. Mais n'importe quelle base de données est possible.
Fonction simplifiée utilisant cela :
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$;