【问题标题】:Drop or create database from stored procedure in PostgreSQL从 PostgreSQL 中的存储过程删除或创建数据库
【发布时间】:2013-02-21 19:14:12
【问题描述】:

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

BEGIN
  DROP DATABASE IF EXISTS db_1;
END;

我收到以下错误:

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

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

【问题讨论】:

  • 你可以从另一个数据库中完成
  • 您可以尝试dblink 到此集群上的任何数据库(除了您要删除的数据库)并从dblink 执行DROP DATABASE IF EXISTS db_1;
  • 我相信错误信息很清楚。

标签: postgresql stored-procedures plpgsql ddl dblink


【解决方案1】:

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

dropdb 呢?

【讨论】:

  • 我从另一个数据库做。 sp 在 db_2 中,我从那里运行它。我会从 postgres 尝试
  • 这显然不是这里的主要问题。你读过错误信息吗?
【解决方案2】:

错误信息与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 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');

使用默认维护数据库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$;

【讨论】:

    猜你喜欢
    • 2011-03-18
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-17
    相关资源
    最近更新 更多