5

我有一个看起来像这样的函数:

BEGIN
  DROP DATABASE IF EXISTS db_1;
END;

我收到以下错误:

错误:不能从函数或多命令字符串执行 DROP DATABASE。

不能从 PostgreSQL 的存储过程中删除数据库吗?我正在使用 plpgsql。

4

2 回答 2

4

错误消息与手册一样清楚:

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从函数中“通过代理”调用。

您可以创建 aFOREIGN DATA WRAPPER和 aFOREIGN 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,这将是显而易见的选择。但是任何数据库都是可能的。

使用它的简化功能:

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$;
于 2013-03-07T00:31:52.110 回答
1

您不能从过程中执行此操作,因为drop database不能在事务中执行,并且存储过程本身被视为事务。(见参考

那么dropdb呢?

于 2013-03-06T20:27:45.797 回答