错误信息与the manual 一样清楚:
DROP DATABASE 不能在事务块内执行。
plgpsql 函数自动被事务块包围。长与短:你不能直接这样做。有什么特殊原因不能只调用 DDL 命令吗?
DROP database $mydb;
您可以使用@Igor 建议的附加模块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');
使用默认维护数据库postgres,这是显而易见的选择。但是任何数据库都是可能的。
利用它的简化函数:
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$;