nixp.ru v3.0

22 января 2017,
воскресенье,
06:47:19 MSK

DevOps с компанией «Флант»
ranet написал 19 сентября 2008 года в 19:37 (2252 просмотра) Ведет себя неопределенно; открыл 4 темы в форуме, оставил 11 комментариев на сайте.

Если в переменной типа «text» хранится имя для новой таблицы, как правильно эту переменную подставить в CREATE TABLE, чтобы была создана таблица?

пробовал вот так:

CREATE OR REPLACE FUNCTION create_new_counter_table()

RETURNS trigger AS

$BODY$DECLARE

name_of_new_table text;

BEGIN

name_of_new_table:=«blin_table»;

CREATE TABLE name_of_new_table

(

vv integer,

bb integer,

dd integer

);

RETURN NULL;

END$BODY$

LANGUAGE 'plpgsql' VOLATILE

COST 100;

ALTER FUNCTION create_new_counter_table() OWNER TO postgres;

Получаю ошибку:

ERROR: syntax error at or near «$1»

SQL state: 42601

Anarchist
ranet
пробовал вот так:

Ты процитировал скрипт, но не команду, которой запускал sql-оператор.

ranet

Команды как таковой нет — использовался «исполнятель» SQL-запросов из состава pgAdmin III, пользователь — postgres. Кстати, такую штуку пробовал — в строку CREATE TABLE name_of_new_table добавлял символ, чтобы имя создаваемой таблицы отличалось от имени переменной, например так: CREATE TABLE name_of_new_tableW — и все успешно выполняется, но такая функция не нужна:) Может я и не прав, но что-то именно с синтаксисом не так..

Anarchist

pgadmin3 какой версии на какой платформе?

По-хорошему (если ничего своими шаловливыми ручками не правил) — надо сообщать об ошибке мэйнтейнеру пакета (и далее по цепочке).

Code Monkey

именно так, в лоб, не получится.

Если ты хочешь создавать таблицу с заранее не определенным именем, то придется динамически конструировать запрос.

см. http://www.postgresql.org/docs/8.3/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN

Anarchist
Code Monkey
именно так, в лоб, не получится.

Если ты хочешь создавать таблицу с заранее не определенным именем, то придется динамически конструировать запрос.

Почему ты думаешь, что банальная подстановка значения переменной SHELL’а не прокатит?

Меня тут заинтересовало вот что:

1. Что из себя представляет этот «исполнятель запросов"?

2. Определена ли переменная, содержащая имя таблицы ($ set | grep VAR)?

3. Ну и не теряется ли это значение в процессе вызова «исполнятеля запросов».

ЗЫ: Очередная иллюстрация того факта, что разного рода гуи (используемые без понимания) — суть безусловное зло.

ranet
Anarchist
pgadmin3 какой версии на какой платформе?

По-хорошему (если ничего своими шаловливыми ручками не правил) — надо сообщать об ошибке мэйнтейнеру пакета (и далее по цепочке).

Я установил готовый пакет, который скачал с www.postgresql.org. Никакие действия шаловливыми ручками вручную :) пока не производились, поставил «как есть». Версия для Linux (ставил на Mandriva 2008 spring). pgAdmin сейчас входит в состав пакета с самим postgresql, он тоже «родной», версия 1.8.4 (rev 7358), устанавливается одновременно с сервером. Вроде как штатное средство, недоверия у меня не вызвал..

ranet
Anarchist
Почему ты думаешь, что банальная подстановка значения переменной SHELL’а не прокатит?

Меня тут заинтересовало вот что:

1. Что из себя представляет этот «исполнятель запросов"?

2. Определена ли переменная, содержащая имя таблицы ($ set | grep VAR)?

3. Ну и не теряется ли это значение в процессе вызова «исполнятеля запросов».

ЗЫ: Очередная иллюстрация того факта, что разного рода гуи (используемые без понимания) — суть безусловное зло.

На счет зла и гуи — готов попробовать что-нибудь консольное, но это успеем..

По существу заданных вопросов:

1)«исполнятель» встроен в GUI pgAdmin’а, прозволяет выполнить набранный вручную или сохраненный в файле запрос. От консоли в этом смысле ничем не отличается.

2) Переменная определяется в самом тексте запроса:

обьявление: name_of_new_table text;

присвоение значения: name_of_new_table:=«blin_table»;

Это упрощенный тестовый вариант, на самом деле предполагается брать из существующей таблицы значения текстовых полей, и из них конструировать имя. Сохранять его в текстовую переменную, и создавать таблицу с таким именем.

Может так почему-нибудь вообще нельзя делать?

ranet
Anarchist
3. Ну и не теряется ли это значение в процессе вызова «исполнятеля запросов».

На этот момент «исполнятель» уже запущен.. В нем я могу набрать руками или открыть текст запроса, что и делаю. Если не связываться с переменными, то функция нормально создается и триггер на её основе — тоже. И даже работает.

Code Monkey
«исполнятеля запросов».

Дело тут не в «исполнятеле запросов». У него сама процедура не компилилась. тут хоть psql юзай, один хрен так будет.

переменная среды — это ты загнул :) тут не это требовалось.

Может так почему-нибудь вообще нельзя делать?

поясняю для не прочитавших то, что сказано по ссылке, такие вот финты ушами в plpgsql не поддерживаются, только через динамический запрос. Если слегка подумать, то причина этому вполне очевидна.

автору топика рекомендую повнимательнее ознакомиться с http://www.postgresql.org/docs/8.3/ для лучшего понимания plpgsql

причина на самом деле та же, что и в примере на С:

char* str = «somefunc»;

void *str(args){ return; }

т.е. хочется во время компиляции создать функцию с неизвестным на момент написания именем.

З.Ы. если окажется, что на С такое провернуть можно в показанном формате, буду очень сильно удивлен :)

ranet
Code Monkey
поясняю для не прочитавших то, что сказано по ссылке, такие вот финты ушами в plpgsql не поддерживаются, только через динамический запрос.

Динамический запрос — то есть запрос, сконструированный во внешнем клиентском приложении и из него запущеный, например так:

void blin_nafig(QString table_name)

{

QString sql_q="CREATE TABLE «+table_name+» (vv integer, bb integer, dd integer)»;

QSqlQuery query;

query.exec(sql_q);

}

Угу?

ranet

Вариант, который заработал:

DECLARE

name_of_new_table text;

sql_q text;

BEGIN

name_of_new_table:=’blin_table’;

sql_q:=’CREATE TABLE '||name_of_new_table||' (vv integer, bb integer, dd integer)’;

EXECUTE sql_q;

RETURN NULL;

END

Триггер тоже работает, СПАСИБО ОГРОМНОЕ!!!

Осталось спросить, не будет ли такое решение ересью и извратом? В смысле чтобы триггер новые таблицы в БД создавал? Мне это вот зачем:

БД в числе прочего электроэнергию считать должна. Счетчиков много, данные раз в неделю снимаем. Хочется, чтобы данные каждого из них в своей отдельной таблице хранились. То есть добавил я в табл с перечнем счетчиков новый — и для его показаний таблицу сервер сам нарисовал, а имя для нее слепил из номера счетчика и места его установки.. А потом и для других девайсов что-то подобное хочу сделать (ИБП, щиты и т.п.)

Или лучше как в предыдущем посте сделать, из клиентского приложения?

Еще есть вариант одну общую табл для всех счетчиков сделать, и отбирать из неё нужное запросами, например по номеру счетчика.. Мне это кажется неудобным, но я не профессионал..

Что правильнее?

myst

Как по мне, так извратный вариант. Делать объектное хранение данных в реляционной БД — глупость. Делаешь одну таблицу на данные, в ней добавляешь одно поле — counter_id. И делаешь таблицу counter = [ id | ... ] с метаданными счётчиков. И не надо париться и извращаться.

Code Monkey

myst, +1

metal

Да по мне тоже. К тому же я не думаю, что разработчики PostgreSQL думали о таком варианте использования, при большом количестве таблиц могут и грабли вылезти. Как минимум это надо протестировать.

myst

По умолчанию в PostgreSQL есть ограничение на количество таблиц — 1000 шт.

ranet
myst
По умолчанию в PostgreSQL есть ограничение на количество таблиц — 1000 шт.

Достаточно много, вобщем можно и сделать так, как я собирался.. Заодно посмотрю, как сервер себя поведет.. БД сделать для своих нужд собираюсь, так что можно и рискнуть

ecobeingecobeing.ru
Экология и вегетарианство на благо всем живым существам Планеты.