"This operation is not defined for system tables."

IBX, FIBPlus, UIB, ADO, .Net и прочее-прочее-прочее, в общем все, что относится к созданию приложений, работающих с InterBase, Firebird и Yaffil - клиент-серверных, трехзвенных, консольных и т.п.

Модератор: kdv

Ответить
HeadHunter
Сообщения: 19
Зарегистрирован: 30 ноя 2005, 17:48

"This operation is not defined for system tables."

Сообщение HeadHunter » 30 ноя 2005, 18:03

Разбираюсь с embedded firebird.
Да заодно и с sql - раньше писал только локальные БД paradox, access.
Использую компонет TpFIBDatabase для BCB6. (триальная версия, насколько понял)
ОС Windows2000.
gds32.dll и иже с ними скопировал в каталог программы.

Проблема при создании таблицы в созданной базе.



#define DB_PATH "C:\\TEST.fDB"

const char * pcCreateQuery =
"CREATE TABLE AbonList (" \
"iNumber INTEGER,\n"\
"strName VARCHAR(256));"
;

void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
if (FileExists(DB_PATH)) DeleteFile(DB_PATH);
Database1->DBParams->Clear();
Database1->DBParams->Add("USER 'SYSDBA' PASSWORD 'masterkey'");
Database1->DBParams->Add("PAGE_SIZE = 2048");
Database1->DBParams->Add("DEFAULT CHARACTER SET WIN1251");
Database1->DBName = DB_PATH;
Database1->SQLDialect = 3;
try
{ Database1->CreateDatabase(); }
catch (...)
{
}
// всё нормально - база создается
...
// пробуим создать табличку
Database1->Execute(pcCreateQuery);
Изображение
//ЗДЕСЬ возникает ошибка
//"This operation is not defined for system tables.unsuccessful metadata
// update."

ЕСЛИ СДЕЛАТЬ ТАК

const char * pcCreateQuery =
"CREATE TABLE AbonList (" \
"iNumber INTEGER,\n"\
"strName INTEGER);"
;
то таблица в базе создается, в неё можно добавлять элементы, производить выборку и т.д.
почему возникает ошибка при типе поля strName == CHAR(), VARCHAR()?

Не пинайте, если было

Klyk
Сообщения: 100
Зарегистрирован: 26 окт 2004, 23:28

Сообщение Klyk » 30 ноя 2005, 23:59

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

попробуй http://www.ibexpert.com/rus/ с ним проще будет.

HeadHunter
Сообщения: 19
Зарегистрирован: 30 ноя 2005, 17:48

Сообщение HeadHunter » 01 дек 2005, 13:20

Нет, не повторно. Перед созданием базы физически удаляю файл базы, если он присутствует на диске.
Иначе генерится другое исключение при создании базы.

Порылся в нете, нигде внятных ответов не нашел...

IB Expert при попытке подключения к созданной базе показывает курсор мыши в виде часов с надписью SQL и намертво виснет.

Я хочу программно (т.е.без всяких вспомогательных тулсов) создать базу, в ней-пару таблиц и заполнить (опять таки программно) эти таблицы данными. Неужели это так сложно?
Может, кто-нибудь подбросит ссылку на пример программного создания таблиц при помощи embedded firebird v1.5.2.4731? :)

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 01 дек 2005, 14:07

после создания БД ее надо ЗАКРЫТЬ. То есть, IBDatabase->Close (или как это там у вас в C++). Потом базу ОТКРЫТЬ, и уже дальше созавать там таблицы. Хотя зачем их создавать из приложения, если можно базу сделать заранее, или создать из скрипта, и т.п.
Перед созданием базы физически удаляю файл базы, если он присутствует на диске
это зачем?

p.s. т.е. какие то странные мучения - сначала спроектировать БД, оттестировать приложение, потом загнать создание всех объектов БД в код...

HeadHunter
Сообщения: 19
Зарегистрирован: 30 ноя 2005, 17:48

Сообщение HeadHunter » 01 дек 2005, 18:10

kdv писал(а):после создания БД ее надо ЗАКРЫТЬ. То есть, IBDatabase->Close (или как это там у вас в C++). Потом базу ОТКРЫТЬ, и уже дальше созавать там таблицы.
Делал и так и эдак. Закрывал, переоткрывал - не помогало.
Хотя зачем их создавать из приложения, если можно базу сделать заранее, или создать из скрипта, и т.п.
Не хочу. Хочу жать на кнопку в приложении и получать БД с набором таблиц + заполнить их автоматически. Сейчас данные лежат в зашифр. текстовике, по-любому придется писать вычитывание и преобразование, а затем сохранение в БД. Почему бы не писануть вначале пару строк для программного создания БД? Вместо того чтобы качать ibexpert(неплохая кстати прога), устанавливать, изучать интерфэйс, создавать и коннектиться к БД, искать на венике gds32 etc.
Перед созданием базы физически удаляю файл базы, если он присутствует на диске
это зачем?
чтобы избежать вот этого:
Изображение
p.s. т.е. какие то странные мучения - сначала спроектировать БД, оттестировать приложение, потом загнать создание всех объектов БД в код...
до приложения и ясной структуры БД еще как до марса
для начала конвертер из старого формата в новый писануть хочу
в качестве изучения вопроса


В общем вопрос не прояснился, обошел при помощи ibexpert - создал базу, создал таблицы, дальше все делаю программно...

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 01 дек 2005, 18:22

Делал и так и эдак. Закрывал, переоткрывал - не помогало.
не надо сказки рассказывать. Проблема с работой БД после ее создания и незакрытия известна чуть ли не со времен FreeIBComponents, которые стали основой для FIBPlus и IBX. И в которых это поведение сохранилось (собственно, это особенность InterBase API).
Хочу жать на кнопку в приложении и получать БД с набором таблиц + заполнить их автоматически. Сейчас данные лежат в зашифр. текстовике, по-любому придется писать вычитывание и преобразование, а затем сохранение в БД. Почему бы не писануть вначале пару строк для программного создания БД? Вместо того чтобы качать ibexpert(неплохая кстати прога), устанавливать, изучать интерфэйс, создавать и коннектиться к БД, искать на венике gds32 etc.
я чего то не понимаю. при чем тут IBExpert? И вообще - если базы еще как таковой нет - ну и разработай ее, создай скрипт, а потом скрипт в программе выполни через IBScript. ВСЕ. Вот тебе и создание БД из приложения. Скрипт можешь зашифровать, засунуть в exe как ресурс, и т.п.
до приложения и ясной структуры БД еще как до марса
для начала конвертер из старого формата в новый писануть хочу
в качестве изучения вопроса
дело хозяйское. если конвертер не одноразовый, то тогда конечно...

HeadHunter
Сообщения: 19
Зарегистрирован: 30 ноя 2005, 17:48

Сообщение HeadHunter » 01 дек 2005, 18:22

Так вот главный вопрос не раскрыт-почему не отрабатывает это
const char * pcCreateQuery =
"CREATE TABLE AbonList (" \
"iNumber INTEGER,\n"\
"strName VARCHAR(256));"
;

но отрабатывает это

const char * pcCreateQuery =
"CREATE TABLE AbonList (" \
"iNumber INTEGER,\n"\
"strName INTEGER);"
;

На королевстве дельфи нашел точно такой трабл - чел может создать табличку с integer, но не может с char()
http://www.delphikingdom.com/asp/answer ... swer=28510

HeadHunter
Сообщения: 19
Зарегистрирован: 30 ноя 2005, 17:48

Сообщение HeadHunter » 01 дек 2005, 18:42

kdv писал(а):
Делал и так и эдак. Закрывал, переоткрывал - не помогало.
не надо сказки рассказывать.
Зачем же так категорично, уважаемый. Предлагаете мне тут листинги моей писанины постить? Не думаю, что Вам или кому-нибудь будет интересно. Базу после создания закрывал, открывал, запросы пытался выполнять как через TpFIBDatabase так и через TpFIBQuery. Результат одинаков.

Проблема с работой БД после ее создания и незакрытия известна чуть ли не со времен FreeIBComponents, которые стали основой для FIBPlus и IBX. И в которых это поведение сохранилось (собственно, это особенность InterBase API).
Это Вам известно. Мне - не было известно. Я конечно проверю, но было бы любопытно увидеть грамотную реализацию этой задачки. У Вас листинга не найдется?
Жаль, что среди примеров которые шли с компонетами в был пример только создания бд, без добавления в нее таблиц...

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 01 дек 2005, 21:57

Базу после создания закрывал, открывал, запросы пытался выполнять как через TpFIBDatabase так и через TpFIBQuery. Результат одинаков.
а чего сразу возмущаться? подумаешь - не разобрался, и т.п.
было бы любопытно увидеть грамотную реализацию этой задачки. У Вас листинга не найдется?
не поленился наваять, ничего что на Delphi? А то я C не люблю. Правда, у меня еще и IBX используется, а не FIBPlus, но это значения не имеет.
компоненты DB, TR и Q - Соответственно IBDatabase, IBTransaction, IBQuery (в FIBPlus такого нет, можно использовать FIBQuery или FIBDataSet, не суть важно).

Код: Выделить всё

procedure TForm2.Button1Click(Sender: TObject);
begin
  // готовим параметры БД для создания
  DB.Params.Clear;
  DB.Params.Add('USER ''SYSDBA'' password ''masterkey''');
  DB.Params.Add(' PAGE_SIZE = 4096 ');
  DB.Params.Add(' DEFAULT CHARACTER SET WIN1251');
  // извиняюсь за localhost, т.к. у меня на компе каша из серверов и клиентов
  // было недосуг искать правильный gds32.dll для fb 1.5,
  // который бы не выдавал ошибку unavailable database при CreateDatabase
  // по причине несовместимости локального протокола между разными
  // клиентом и сервером
  DB.DatabaseName:='localhost:C:\TEST.FDB';
  DB.SQLDialect:=3;
  DB.CreateDatabase; // СОЗДАЕМ
  DB.Close; // ЗАКРЫВАЕМ

  // готовим параметры для коннекта к БД, т.к. они отличаются от параметров создания
  DB.Params.Clear;
  DB.Params.Add('user_name=SYSDBA');
  DB.Params.Add('password=masterkey');
  DB.Params.Add('lc_ctype=win1251');
  DB.LoginPrompt:=False;

  DB.Open; // открыли

  Q.SQL.Clear;
  Q.SQL.Add('CREATE TABLE AbonList( ');
  Q.SQL.Add('iNumber int, ');
  Q.SQL.Add('strName varchar(30))');

  TR.StartTransaction; // стартуем транзакцию

  Q.ExecSQL; // выполняем запрос создания таблицы
  Q.Close;

  TR.Commit; // завершаем транзакцию

  DB.Close; // закрываем БД
end;
Все. После чего можем открыть БД в IBExpert, и насладиться лицезрением таблицы (со строковым столбцом, как и требовалось в задаче).
Код рабочий, 100%. Нужны комментарии?

HeadHunter
Сообщения: 19
Зарегистрирован: 30 ноя 2005, 17:48

Сообщение HeadHunter » 02 дек 2005, 17:43

За код большое человеческое спасибо.
Перевести-дело вроде нехитрое, но пока работоспособности не получается.
Компоненты взял TbFIB

void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{

// готовим параметры БД для создания
DB->DBParams->Clear();
DB->DBParams->Add("USER 'SYSDBA' password 'masterkey'");
DB->DBParams->Add(" PAGE_SIZE = 4096 ");
DB->DBParams->Add(" DEFAULT CHARACTER SET WIN1251");
// извиняюсь за localhost, т.к. у меня на компе каша из серверов и клиентов
// было недосуг искать правильный gds32.dll для fb 1.5,
// который бы не выдавал ошибку unavailable database при CreateDatabase
// по причине несовместимости локального протокола между разными
// клиентом и сервером
DB->DatabaseName = "C:\\TEST.FDB";
DB->SQLDialect = 3;
DB->CreateDatabase(); // СОЗДАЕМ
DB->Close(); // ЗАКРЫВАЕМ

// готовим параметры для коннекта к БД, т.к. они отличаются от параметров создания
DB->DBParams->Clear();
DB->DBParams->Add("user_name=SYSDBA");
DB->DBParams->Add("password=masterkey");
DB->DBParams->Add("lc_ctype=win1251");
DB->UseLoginPrompt = false;

DB->Open(); // открыли

ИМЕЕМ ЭТО
Изображение

Q->SQL->Clear();
Q->SQL->Add("CREATE TABLE AbonList( ");
Q->SQL->Add("iNumber int, ");
Q->SQL->Add("strName varchar(30))");

TR->StartTransaction(); // стартуем транзакцию

Q->ExecQuery(); // выполняем запрос создания таблицы
Q->Close();

TR->Commit(); // завершаем транзакцию

DB->Close(); // закрываем БД
}

Буду разбираться.
К сожалению, Дельфи не установлена, будет время поставлю.

HeadHunter
Сообщения: 19
Зарегистрирован: 30 ноя 2005, 17:48

Сообщение HeadHunter » 02 дек 2005, 17:51

Хех, так может трабл в том что при создании базы что-то с charset не то творится? Отсюда и отсутствие проблемы при создании базы только с INTEGER. Т.к. нет CHAR() - нет проблем

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 02 дек 2005, 21:14

win1251 is not defined - это ты неправильно embedded установил - каталог intl присутствует? www.ibase.ru/devinfo/ibrusfaq.htm читал?

HeadHunter
Сообщения: 19
Зарегистрирован: 30 ноя 2005, 17:48

Сообщение HeadHunter » 04 дек 2005, 15:58

Да!! Проблема была в отсутствии каталога intl - я положил только gds32.dll, msg и еще какието рядом лежащие файлы. Теперь работает.
Спасибо!

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 05 дек 2005, 09:07

kdv писал(а): Код рабочий, 100%. Нужны комментарии?
Есть мнение, что если к параметрам создания БД добавить недокументированный "NAMES WIN1251", то закрытие и повторное открытие не понадобится...

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 05 дек 2005, 09:33

Дим, set names win1251 - это команда ISQL, которую НИКТО кроме isql больше не понимает.

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 05 дек 2005, 09:59

Дим, к CREATE DATABASE перед посылкой на сервер добавляется параметр SET NAMES если ранее он был установлен командой SET NAMES. И вот этот параметр при разборке DSQL-ем преобразуется в lc_ctype, добавляемый в dpb, передаваемый в isc_create_database(). Не веришь - посмотри в код PREPARSE_execute.
А необходимость реконнекта как раз и вызвана отсутствием клиентского чарсета после создания базы документированными способами. Таким образом, добавление "SET NAMES" в параметры создания действительно должно помочь. Ты ведь не делаешь дополнительный CONNECT в скриптах для isql?..
Кстати, в предыдущем сообщении я ошибся и параметр действительно звучит как "SET NAMES ..."

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 05 дек 2005, 17:06

в такие ужасы я не вникал, и это даже неинтересно. Потому что раньше были случаи "окривевания" БД, если с ней работали не закрывая после create. Подтвердить достоверно не могу, на такие случаи вырабатывается привычка обхода, которая всегда работает 100%. Как минимум, если не надо будет создавать БД в коде, можно этот код просто закомментировать и вырезать. Так что мой пример удобнее :)

Ответить