使用存储函数创建数据库

发布于 2024-10-06 07:00:12 字数 292 浏览 7 评论 0原文

我是 PostgreSQL 新手,想使用存储函数创建数据库。
例如:

CREATE OR REPLACE FUNCTION mt_test(dbname character varying)
  RETURNS integer AS
$BODY$

Create Database $1;

Select 1;

$BODY$
  LANGUAGE sql;

当我尝试执行此函数时,出现语法错误。

Postgres 是否支持存储函数中的 CREATE DATABASE 语句?

I am new to PostgreSQL and want to create a database using a stored function.
For ex:

CREATE OR REPLACE FUNCTION mt_test(dbname character varying)
  RETURNS integer AS
$BODY$

Create Database $1;

Select 1;

$BODY$
  LANGUAGE sql;

When I am trying to execute this function I get a syntax error.

Does Postgres support the CREATE DATABASE statement in stored functions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

誰ツ都不明白 2024-10-13 07:00:12

这个问题已经很老了,但是为了完整起见......

正如其他答案中指出的那样,这不仅仅是可能的,因为 (根据文档)

CREATE DATABASE 无法在事务块内执行。

另据报道,可以使用 dblink 绕过该限制。
如何在 PostgreSQL 中使用(安装)dblink?

到目前为止,缺少的是实际执行此操作的正确函数:

CREATE OR REPLACE FUNCTION f_create_db(dbname text)
  RETURNS integer AS
$func$
BEGIN

IF EXISTS (SELECT 1 FROM pg_database WHERE datname = dbname) THEN
   RAISE NOTICE 'Database already exists'; 
ELSE
   PERFORM dblink_exec('dbname=' || current_database()   -- current db
                     , 'CREATE DATABASE ' || quote_ident(dbname));
END IF;

END
$func$ LANGUAGE plpgsql;

检查数据库是否已存在于本地集群中。如果没有,请继续创建它 - 使用经过清理的标识符。我们不想邀请 SQL 注入。

This question is old, but for the sake of completeness ...

As has been pointed out in other answers, that's not simply possible because (per documentation):

CREATE DATABASE cannot be executed inside a transaction block.

It has also been reported that the restriction can be bypassed with dblink.
How to use (install) dblink in PostgreSQL?

What was missing so far is a proper function actually doing it:

CREATE OR REPLACE FUNCTION f_create_db(dbname text)
  RETURNS integer AS
$func$
BEGIN

IF EXISTS (SELECT 1 FROM pg_database WHERE datname = dbname) THEN
   RAISE NOTICE 'Database already exists'; 
ELSE
   PERFORM dblink_exec('dbname=' || current_database()   -- current db
                     , 'CREATE DATABASE ' || quote_ident(dbname));
END IF;

END
$func$ LANGUAGE plpgsql;

Checks if the db already exists in the local cluster. If not, proceed to create it - with a sanitized identifier. We would not want to invite SQL injection.

海之角 2024-10-13 07:00:12

您无法在函数内部创建数据库,因为无法创建数据库 在交易内

但很可能您并不打算创建数据库,而是创建 模式 ,它更类似于 MySQL 的数据库。

You can't create a database inside of a function because it's not possible to create a database inside a transaction.

But most probably you don't mean to create databases but schemas, which more closely resemble the MySQL's databases.

星星的軌跡 2024-10-13 07:00:12

我找到了解决这个问题的棘手方法,但也是可能的。在几乎到处查看和阅读之后,我尝试了一些东西并且它起作用了。

如果错误是“无法从函数或多命令字符串执行 CREATE DATABASE”,我们可以使用 dblink 强制使用单个命令字符串。并使其连接到自身。

检查 dblink 安装说明 dblink

PERFORM replication.dblink_connect('myconn','host=127.0.0.1 port=5432 dbname=mydb user=username password=secret');
PERFORM replication.dblink_exec('myconn', 'CREATE DATABASE "DBFROMUSER'||id||'" TEMPLATE "TEMPL'||type||'";',false);
PERFORM replication.dblink_disconnect('myconn');

在我的例子中使用不同类型的模板。

问候

I found a tricky solution to this problem, but possible. After looking and reading almost in everywhere I tried something and it worked.

if the error is "CREATE DATABASE cannot be executed from a function or multi-command string" we can force a single command string using dblink. And make it to connect to itself.

Check for dblink installation instructions at dblink

PERFORM replication.dblink_connect('myconn','host=127.0.0.1 port=5432 dbname=mydb user=username password=secret');
PERFORM replication.dblink_exec('myconn', 'CREATE DATABASE "DBFROMUSER'||id||'" TEMPLATE "TEMPL'||type||'";',false);
PERFORM replication.dblink_disconnect('myconn');

In my case using different kinds of template.

Greetings

月野兔 2024-10-13 07:00:12
postgres=> create or replace function mt_test(dbname text) 
                                      returns void language plpgsql as $
postgres
gt; begin
postgres
gt;   execute 'create database '||$1;
postgres
gt; end;$;
CREATE FUNCTION
postgres=> select work.mt_test('dummy_db');
ERROR:  CREATE DATABASE cannot be executed from a function or multi-command string
CONTEXT:  SQL statement "create database dummy_db"
PL/pgSQL function "mt_test" line 2 at EXECUTE statement
postgres=>

请注意错误消息:无法从函数或多命令字符串执行 CREATE DATABASE

因此问题的答案:

postgresql是否支持在存储函数中创建语句

是“否”(至少在 8.4 上 - 你没有指定你的版本)

postgres=> create or replace function mt_test(dbname text) 
                                      returns void language plpgsql as $
postgres
gt; begin
postgres
gt;   execute 'create database '||$1;
postgres
gt; end;$;
CREATE FUNCTION
postgres=> select work.mt_test('dummy_db');
ERROR:  CREATE DATABASE cannot be executed from a function or multi-command string
CONTEXT:  SQL statement "create database dummy_db"
PL/pgSQL function "mt_test" line 2 at EXECUTE statement
postgres=>

note the error message: CREATE DATABASE cannot be executed from a function or multi-command string

so the answer to the question:

Does postgresql support creating statement in stored function

is "no" (at least on 8.4 - you don't specify your version)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文