从PostgreSQL中的存储过程中删除或创建数据库

时间:2013-03-06 19:57:41

标签: postgresql stored-procedures plpgsql ddl dblink

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

BEGIN
  DROP DATABASE IF EXISTS db_1;
END;

我收到以下错误:

  

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

是否无法从PostgreSQL中的存储过程中删除数据库?我正在使用plpgsql。

2 个答案:

答案 0 :(得分:3)

此错误信息只有the manual

  

DROP DATABASE无法在事务块中执行。

plgpsql函数自动被事务块包围。它的长短:你不能直接做到这一点。有没有特别的原因你不能只调用DDL命令?

DROP database $mydb;

可以通过建议的dblink附加模块@Igor来规避这些限制。您需要为每个数据库安装一次 - 您调用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

连接字符串甚至可以指向会话运行的同一个db。该命令在事务块之外运行,这有两个结果:

  • 无法回滚。
  • 它允许您通过代理“从函数内”调用DROP DATABASE“。

您可以创建FOREIGN DATA WRAPPERFOREIGN 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$;

答案 1 :(得分:1)

您无法从过程中执行此操作,因为drop database无法在事务内执行,并且存储过程本身被视为事务。 (见reference

dropdb怎么样?