Создать базу данных, используя хранимую функцию - PullRequest
5 голосов
/ 08 декабря 2010

Я новичок в 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 в хранимых функциях?

Ответы [ 4 ]

9 голосов
/ 13 марта 2014

Этот вопрос старый, но ради полноты ...

Как было указано в других ответах, это не просто возможно, потому что (за документацию) :

CREATE DATABASE невозможно выполнить внутри блока транзакции.

Также сообщалось, что ограничение можно обойти с помощью dblink.
Как использовать (установить) dblink в PostgreSQL?

Чего пока не хватало, так это правильной функции:

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-инъекцию.

2 голосов
/ 04 сентября 2012

Я нашел хитрое решение этой проблемы, но возможно.После поиска и чтения почти везде я попробовал что-то, и это сработало.

Если ошибка «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');

В моем случае используются различные типы шаблонов.

Привет

1 голос
/ 08 декабря 2010
postgres=> create or replace function mt_test(dbname text) 
                                      returns void language plpgsql as $$
postgres$> begin
postgres$>   execute 'create database '||$1;
postgres$> 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 cannot be executed from a function or multi-command string

, поэтому ответ на вопрос:

Поддерживает ли postgresql создание оператора в хранимой функции

означает «нет» (по крайней мере, в 8.4 - вы не указываете свою версию)

1 голос
/ 08 декабря 2010

Вы не можете создать базу данных внутри функции, потому что невозможно создать базу данных внутри транзакции .

Но, скорее всего, вы не хотите создавать базы данных, но схемы , которые больше похожи на базы данных MySQL.

...