ranet
написал 19 сентября 2008 года в 19:37 (4726 просмотров)
Ведет себя
неопределенно; открыл 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
Последние комментарии
- OlegL, 17 декабря в 15:00 → Перекличка 21
- REDkiy, 8 июня 2023 года в 9:09 → Как «замокать» файл для юниттеста в Python? 2
- fhunter, 29 ноября 2022 года в 2:09 → Проблема с NO_PUBKEY: как получить GPG-ключ и добавить его в базу apt? 6
- Иванн, 9 апреля 2022 года в 8:31 → Ассоциация РАСПО провела первое учредительное собрание 1
- Kiri11.ADV1, 7 марта 2021 года в 12:01 → Логи catalina.out в TomCat 9 в формате JSON 1
ecobeing.ru
Экология и вегетарианство на благо всем живым существам Планеты.
Ты процитировал скрипт, но не команду, которой запускал sql-оператор.
Команды как таковой нет — использовался «исполнятель» SQL-запросов из состава pgAdmin III, пользователь — postgres. Кстати, такую штуку пробовал — в строку CREATE TABLE name_of_new_table добавлял символ, чтобы имя создаваемой таблицы отличалось от имени переменной, например так: CREATE TABLE name_of_new_tableW — и все успешно выполняется, но такая функция не нужна:) Может я и не прав, но что-то именно с синтаксисом не так..
pgadmin3 какой версии на какой платформе?
По-хорошему (если ничего своими шаловливыми ручками не правил) — надо сообщать об ошибке мэйнтейнеру пакета (и далее по цепочке).
именно так, в лоб, не получится.
Если ты хочешь создавать таблицу с заранее не определенным именем, то придется динамически конструировать запрос.
см. http://www.postgresql.org/docs/8.3/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN
Почему ты думаешь, что банальная подстановка значения переменной SHELL’а не прокатит?
Меня тут заинтересовало вот что:
1. Что из себя представляет этот «исполнятель запросов"?
2. Определена ли переменная, содержащая имя таблицы ($ set | grep VAR)?
3. Ну и не теряется ли это значение в процессе вызова «исполнятеля запросов».
ЗЫ: Очередная иллюстрация того факта, что разного рода гуи (используемые без понимания) — суть безусловное зло.
Я установил готовый пакет, который скачал с www.postgresql.org. Никакие действия шаловливыми ручками вручную :) пока не производились, поставил «как есть». Версия для Linux (ставил на Mandriva 2008 spring). pgAdmin сейчас входит в состав пакета с самим postgresql, он тоже «родной», версия 1.8.4 (rev 7358), устанавливается одновременно с сервером. Вроде как штатное средство, недоверия у меня не вызвал..
На счет зла и гуи — готов попробовать что-нибудь консольное, но это успеем..
По существу заданных вопросов:
1)«исполнятель» встроен в GUI pgAdmin’а, прозволяет выполнить набранный вручную или сохраненный в файле запрос. От консоли в этом смысле ничем не отличается.
2) Переменная определяется в самом тексте запроса:
обьявление: name_of_new_table text;
присвоение значения: name_of_new_table:=«blin_table»;
Это упрощенный тестовый вариант, на самом деле предполагается брать из существующей таблицы значения текстовых полей, и из них конструировать имя. Сохранять его в текстовую переменную, и создавать таблицу с таким именем.
Может так почему-нибудь вообще нельзя делать?
На этот момент «исполнятель» уже запущен.. В нем я могу набрать руками или открыть текст запроса, что и делаю. Если не связываться с переменными, то функция нормально создается и триггер на её основе — тоже. И даже работает.
Дело тут не в «исполнятеле запросов». У него сама процедура не компилилась. тут хоть psql юзай, один хрен так будет.
переменная среды — это ты загнул :) тут не это требовалось.
поясняю для не прочитавших то, что сказано по ссылке, такие вот финты ушами в plpgsql не поддерживаются, только через динамический запрос. Если слегка подумать, то причина этому вполне очевидна.
автору топика рекомендую повнимательнее ознакомиться с http://www.postgresql.org/docs/8.3/ для лучшего понимания plpgsql
причина на самом деле та же, что и в примере на С:
char* str = «somefunc»;
void *str(args){ return; }
т.е. хочется во время компиляции создать функцию с неизвестным на момент написания именем.
З.Ы. если окажется, что на С такое провернуть можно в показанном формате, буду очень сильно удивлен :)
Динамический запрос — то есть запрос, сконструированный во внешнем клиентском приложении и из него запущеный, например так:
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);
}
Угу?
Вариант, который заработал:
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
Триггер тоже работает, СПАСИБО ОГРОМНОЕ!!!
Осталось спросить, не будет ли такое решение ересью и извратом? В смысле чтобы триггер новые таблицы в БД создавал? Мне это вот зачем:
БД в числе прочего электроэнергию считать должна. Счетчиков много, данные раз в неделю снимаем. Хочется, чтобы данные каждого из них в своей отдельной таблице хранились. То есть добавил я в табл с перечнем счетчиков новый — и для его показаний таблицу сервер сам нарисовал, а имя для нее слепил из номера счетчика и места его установки.. А потом и для других девайсов что-то подобное хочу сделать (ИБП, щиты и т.п.)
Или лучше как в предыдущем посте сделать, из клиентского приложения?
Еще есть вариант одну общую табл для всех счетчиков сделать, и отбирать из неё нужное запросами, например по номеру счетчика.. Мне это кажется неудобным, но я не профессионал..
Что правильнее?
Как по мне, так извратный вариант. Делать объектное хранение данных в реляционной БД — глупость. Делаешь одну таблицу на данные, в ней добавляешь одно поле — counter_id. И делаешь таблицу counter = [ id | ... ] с метаданными счётчиков. И не надо париться и извращаться.
myst, +1
Да по мне тоже. К тому же я не думаю, что разработчики PostgreSQL думали о таком варианте использования, при большом количестве таблиц могут и грабли вылезти. Как минимум это надо протестировать.
По умолчанию в PostgreSQL есть ограничение на количество таблиц — 1000 шт.
Достаточно много, вобщем можно и сделать так, как я собирался.. Заодно посмотрю, как сервер себя поведет.. БД сделать для своих нужд собираюсь, так что можно и рискнуть