"This operation is not defined for system tables."
Модератор: kdv
-
- Сообщения: 19
- Зарегистрирован: 30 ноя 2005, 17:48
"This operation is not defined for system tables."
Разбираюсь с 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()?
Не пинайте, если было
Да заодно и с 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()?
Не пинайте, если было
Здаётся мне ты хочешь повторно создать таблицу которая у тебя уже существует.
попробуй http://www.ibexpert.com/rus/ с ним проще будет.
попробуй http://www.ibexpert.com/rus/ с ним проще будет.
-
- Сообщения: 19
- Зарегистрирован: 30 ноя 2005, 17:48
Нет, не повторно. Перед созданием базы физически удаляю файл базы, если он присутствует на диске.
Иначе генерится другое исключение при создании базы.
Порылся в нете, нигде внятных ответов не нашел...
IB Expert при попытке подключения к созданной базе показывает курсор мыши в виде часов с надписью SQL и намертво виснет.
Я хочу программно (т.е.без всяких вспомогательных тулсов) создать базу, в ней-пару таблиц и заполнить (опять таки программно) эти таблицы данными. Неужели это так сложно?
Может, кто-нибудь подбросит ссылку на пример программного создания таблиц при помощи embedded firebird v1.5.2.4731?
Иначе генерится другое исключение при создании базы.
Порылся в нете, нигде внятных ответов не нашел...
IB Expert при попытке подключения к созданной базе показывает курсор мыши в виде часов с надписью SQL и намертво виснет.
Я хочу программно (т.е.без всяких вспомогательных тулсов) создать базу, в ней-пару таблиц и заполнить (опять таки программно) эти таблицы данными. Неужели это так сложно?
Может, кто-нибудь подбросит ссылку на пример программного создания таблиц при помощи embedded firebird v1.5.2.4731?
после создания БД ее надо ЗАКРЫТЬ. То есть, IBDatabase->Close (или как это там у вас в C++). Потом базу ОТКРЫТЬ, и уже дальше созавать там таблицы. Хотя зачем их создавать из приложения, если можно базу сделать заранее, или создать из скрипта, и т.п.
p.s. т.е. какие то странные мучения - сначала спроектировать БД, оттестировать приложение, потом загнать создание всех объектов БД в код...
это зачем?Перед созданием базы физически удаляю файл базы, если он присутствует на диске
p.s. т.е. какие то странные мучения - сначала спроектировать БД, оттестировать приложение, потом загнать создание всех объектов БД в код...
-
- Сообщения: 19
- Зарегистрирован: 30 ноя 2005, 17:48
Делал и так и эдак. Закрывал, переоткрывал - не помогало.kdv писал(а):после создания БД ее надо ЗАКРЫТЬ. То есть, IBDatabase->Close (или как это там у вас в C++). Потом базу ОТКРЫТЬ, и уже дальше созавать там таблицы.
Не хочу. Хочу жать на кнопку в приложении и получать БД с набором таблиц + заполнить их автоматически. Сейчас данные лежат в зашифр. текстовике, по-любому придется писать вычитывание и преобразование, а затем сохранение в БД. Почему бы не писануть вначале пару строк для программного создания БД? Вместо того чтобы качать ibexpert(неплохая кстати прога), устанавливать, изучать интерфэйс, создавать и коннектиться к БД, искать на венике gds32 etc.Хотя зачем их создавать из приложения, если можно базу сделать заранее, или создать из скрипта, и т.п.
чтобы избежать вот этого:это зачем?Перед созданием базы физически удаляю файл базы, если он присутствует на диске
до приложения и ясной структуры БД еще как до марсаp.s. т.е. какие то странные мучения - сначала спроектировать БД, оттестировать приложение, потом загнать создание всех объектов БД в код...
для начала конвертер из старого формата в новый писануть хочу
в качестве изучения вопроса
В общем вопрос не прояснился, обошел при помощи ibexpert - создал базу, создал таблицы, дальше все делаю программно...
не надо сказки рассказывать. Проблема с работой БД после ее создания и незакрытия известна чуть ли не со времен FreeIBComponents, которые стали основой для FIBPlus и IBX. И в которых это поведение сохранилось (собственно, это особенность InterBase API).Делал и так и эдак. Закрывал, переоткрывал - не помогало.
я чего то не понимаю. при чем тут IBExpert? И вообще - если базы еще как таковой нет - ну и разработай ее, создай скрипт, а потом скрипт в программе выполни через IBScript. ВСЕ. Вот тебе и создание БД из приложения. Скрипт можешь зашифровать, засунуть в exe как ресурс, и т.п.Хочу жать на кнопку в приложении и получать БД с набором таблиц + заполнить их автоматически. Сейчас данные лежат в зашифр. текстовике, по-любому придется писать вычитывание и преобразование, а затем сохранение в БД. Почему бы не писануть вначале пару строк для программного создания БД? Вместо того чтобы качать ibexpert(неплохая кстати прога), устанавливать, изучать интерфэйс, создавать и коннектиться к БД, искать на венике gds32 etc.
дело хозяйское. если конвертер не одноразовый, то тогда конечно...до приложения и ясной структуры БД еще как до марса
для начала конвертер из старого формата в новый писануть хочу
в качестве изучения вопроса
-
- Сообщения: 19
- Зарегистрирован: 30 ноя 2005, 17:48
Так вот главный вопрос не раскрыт-почему не отрабатывает это
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
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
-
- Сообщения: 19
- Зарегистрирован: 30 ноя 2005, 17:48
Зачем же так категорично, уважаемый. Предлагаете мне тут листинги моей писанины постить? Не думаю, что Вам или кому-нибудь будет интересно. Базу после создания закрывал, открывал, запросы пытался выполнять как через TpFIBDatabase так и через TpFIBQuery. Результат одинаков.kdv писал(а):не надо сказки рассказывать.Делал и так и эдак. Закрывал, переоткрывал - не помогало.
Это Вам известно. Мне - не было известно. Я конечно проверю, но было бы любопытно увидеть грамотную реализацию этой задачки. У Вас листинга не найдется?Проблема с работой БД после ее создания и незакрытия известна чуть ли не со времен FreeIBComponents, которые стали основой для FIBPlus и IBX. И в которых это поведение сохранилось (собственно, это особенность InterBase API).
Жаль, что среди примеров которые шли с компонетами в был пример только создания бд, без добавления в нее таблиц...
а чего сразу возмущаться? подумаешь - не разобрался, и т.п.Базу после создания закрывал, открывал, запросы пытался выполнять как через 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;
Код рабочий, 100%. Нужны комментарии?
-
- Сообщения: 19
- Зарегистрирован: 30 ноя 2005, 17:48
За код большое человеческое спасибо.
Перевести-дело вроде нехитрое, но пока работоспособности не получается.
Компоненты взял 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(); // закрываем БД
}
Буду разбираться.
К сожалению, Дельфи не установлена, будет время поставлю.
Перевести-дело вроде нехитрое, но пока работоспособности не получается.
Компоненты взял 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(); // закрываем БД
}
Буду разбираться.
К сожалению, Дельфи не установлена, будет время поставлю.
-
- Сообщения: 19
- Зарегистрирован: 30 ноя 2005, 17:48
win1251 is not defined - это ты неправильно embedded установил - каталог intl присутствует? www.ibase.ru/devinfo/ibrusfaq.htm читал?
-
- Сообщения: 19
- Зарегистрирован: 30 ноя 2005, 17:48
-
- Заслуженный разработчик
- Сообщения: 1436
- Зарегистрирован: 15 сен 2005, 09:05
-
- Заслуженный разработчик
- Сообщения: 1436
- Зарегистрирован: 15 сен 2005, 09:05
Дим, к CREATE DATABASE перед посылкой на сервер добавляется параметр SET NAMES если ранее он был установлен командой SET NAMES. И вот этот параметр при разборке DSQL-ем преобразуется в lc_ctype, добавляемый в dpb, передаваемый в isc_create_database(). Не веришь - посмотри в код PREPARSE_execute.
А необходимость реконнекта как раз и вызвана отсутствием клиентского чарсета после создания базы документированными способами. Таким образом, добавление "SET NAMES" в параметры создания действительно должно помочь. Ты ведь не делаешь дополнительный CONNECT в скриптах для isql?..
Кстати, в предыдущем сообщении я ошибся и параметр действительно звучит как "SET NAMES ..."
А необходимость реконнекта как раз и вызвана отсутствием клиентского чарсета после создания базы документированными способами. Таким образом, добавление "SET NAMES" в параметры создания действительно должно помочь. Ты ведь не делаешь дополнительный CONNECT в скриптах для isql?..
Кстати, в предыдущем сообщении я ошибся и параметр действительно звучит как "SET NAMES ..."
в такие ужасы я не вникал, и это даже неинтересно. Потому что раньше были случаи "окривевания" БД, если с ней работали не закрывая после create. Подтвердить достоверно не могу, на такие случаи вырабатывается привычка обхода, которая всегда работает 100%. Как минимум, если не надо будет создавать БД в коде, можно этот код просто закомментировать и вырезать. Так что мой пример удобнее