1 Что такое bde?

Вид материалаДокументы

Содержание


1.2.Базы данных в BDE
1.3.Создание alias.
1.4.Косметическая настройка BDE
1.5.Таблица в Database Desktop
1.6.Мастер форм
1.7.Каким образом это все работает.
1.8.Компонент TTable. Создание таблиц. Типы полей
1.9.Создание таблиц. Ключи и индексы
1.10.Класс TFieldDef.
Select цена, количество (цена*количество)
1.11.Коллекция TFieldDefs
1.12.Изменение значений полей
MDI-приложения, как это делали ранее. Напомню, что для MDI
TDBGrid), редактор элементов таблицы (созданный только что) и далее мы еще напишем список истории чтения. Соответственно fName
1.13.Проект приложения CView
1.14.Создание произвольной таблицы
Bcdemos. в
Подобный материал:

1.1. Что такое BDE? 1

1.2. Базы данных в BDE 1

1.3. Создание alias. 2

1.4. Косметическая настройка BDE 3

1.5. Таблица в Database Desktop 4

1.6. Мастер форм 4

1.7. Каким образом это все работает. 5

1.8. Компонент TTable. Создание таблиц. Типы полей 6

1.9. Создание таблиц. Ключи и индексы 8

1.10. Класс TFieldDef. 9

1.11. Коллекция TFieldDefs 10

1.12. Изменение значений полей 12

1.13. Проект приложения CView 13

1.14. Создание произвольной таблицы 15

1.1.Что такое BDE?


BDE - в C++Builder механизм управления базами данных. Это посредник между Вашей программой и базами данных разных форматов - Paradox, MS Access, dBase и так далее. BDE - набор системных DLL файлов, которые включатют драйвера. Вашей программе не придется вручную эти самые драйвера создавать, просто можно воспользоваться встроенным механизмом.


В C++Builder BDE не является монополистом. В программу включены также такие механизмы, как ADO и InterBase.

ADO представляет собой также набор библиотек, как и BDE. В отличие от их обоих, InterBase позволяет обращаться к базам данных через COM-интерфейсы, минуя посреднические механизмы. В этом плане InterBase более эффективен для распространения, поскольку нет необходимости включать установочный файл BDE в дистрибутив программы, который, кстати, имеет большой размер.


В любом случае BDE манипулировать проще всего.


Основное для работы с базами данных церез BDE предоставляется на палитрах Data Access и Data Controls.


BDE имеет довольно мощные средства для работы с SQL. SQL - язык транзакций RDBMS реляционных баз данных.
^

1.2.Базы данных в BDE


Чаще всего базы данных адресуются в программах своим псевдонимом [alias]. Псевдоним - приблизительно то же самое для базы данных, что и домен для сайта. То есть через псевдоним можно обращаться к базе данных, не зная ее физического расположения.

Чтобы узнать, какие alias есть на Вашем компьютере, нужно запустить командой Database-Explore т.н. SQL Explorer. Его окно показано на скриншоте:



В левой части показаны псевдонимы баз данных, в правой - их свойства. Отметьте, что получить доступ к базе данных можно только с установленным сервером этой базы. Например, после установки InterBase сервера становится доступным база данных IBLocal. Сразу же доступными являются базы данных BCDEMOS и DBDEMOS.

Никто не ограничивает Вас в выборе alias. Можно создать и свой собственный alias для рабочих файлов.На скриншоте виден псевдоним Local tables, как раз в нем все примеры баз данных и размещены.

С BDE поставляется довольно много примеров баз данных. Эти таблицы, как и все другие, можно посмотреть, если два раза щелкнуть на BCDEMOS, а затем на появившемся Tables.
^

1.3.Создание alias.


Запустите SQL Explorer командой Database-Explore. Как обычно, alias с левой, свойства с правой строны. Выберите команду Object-New. Появится оконо:



Оконо дает возможность выбрать тип драйвера для базы данных. Стандартный нам подходит. Жмите OK.

Слева появится поле для ввода имени для таблицы. Введем, например, "Local tables", и нажмем Enter. Обратите внимание, что рядом со значком базы данных в данный момент изображена зеленая стрелка. Эта стрелка означает, что над базой проводятся изменения типа транзакции. Чтобы изменения вошли в силу, надо из контекстного меню выбрать команду Apply.

Для того, чтобы Explorer знал, откуда брать таблицы, нужно задать путь к директории с таблицами. Например каталог "C:\program files\borland\database desktop\workdir".

После всех этих махинаций можно выполгить команду Apply. До ее выполнения ничего работать не будет, а возникнет ошибка "Operation not supported":



Теперь все таблицы, помещенные в эту директорию, Проводник будет отображать в раскрывающемся дереве.
^

1.4.Косметическая настройка BDE


Чтобы работать с BDE, надо ее немного поднастроить, чтобы русский выводила как положено. Для настройки BDE используется утилита BDE Administrator. Выглядит она довольно схоже с SQL Explorer'ом:



Вкладка Databases нам не нужна, мы ее и из Проводника видим. Зато на вкладке Configuration есть настройки по драйверам баз данных и системным параметрам.

Открываем ветвь Drivers. Там должны быть пункты Native и ODBC. Второй нам пока не нужен, открываем первый. Там есть значок Paradox. По нему и щелкаем. В правой части, как обычно, свойства. Пока установим правлильный драйвер для языка, как на скриншоте:



Чтобы в Database Desktop отображался нормальный шрифт, нужно в файл win.ini, в раздел FontSubstitutes подставить строку Arial,0=Arial,204. После этого перезагрузиться.
^

1.5.Таблица в Database Desktop


Запускается Database desktop через Tools-Database Desktop.



Выбираем команду File-New-Table, появляется окно, в котором предлагается выбрать тип создаваемой таблицы. Выберем Paradox 7. Жмите OK. Появится другое окно:



Кто работал с MS Access в режиме конструктора. Первый столбец - номер поля, второй - его имя. Третий определяет тип (выпадающий по правой клавише мыщи список), четвертый - размер, а пятый - является ли поле ключевым. Для начала - строковые типы - ALPHA, числовые - NUMBER. Поля, то есть столбцы, когда они уже готовы, создаются как обычно. Для начала создайте простую записную книжки и нажмите Save as для сохранения таблицы. Внизу можно выбирать alias для сохранения.
^

1.6.Мастер форм


Попробуем создать форму на основе базы данных, используя Мастер форм (Form Wizard). Этот мастер запускается командой Database-Form Wizard... Как и у всякого другого мастера, у него несколько окон.



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

В следующем окне предлагается выбрать источник для построения формы. Выберите alias базы данных в выпадающем списке справа внизу, и название таблицы слева. Предпочтительнее выбрать таблицу из BCDEMOS, называемую Clients.

Жмите Next. Далее будет предложено выбрать поля из таблицы, которые будут использоваться в форме. Можно выбрать все поля кнопкой ">>". Если какие-то Вам не подходят, уберите их.

В следующем окне мастера будет предложен вариант размещения полей таблицы.

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

В итоге получится:




^

1.7.Каким образом это все работает.


Общая схема работы типичного BDE-приложения базы данных такова:


[База данных]


|



BDE



|



Компоненты доступа к BDE [TTable, TQuery]



|



Компонент TDataSource



|



Компоненты Data Controls [TDBLabel, TDBEdit]



|



Пользователь



Это не единственный вариант доступа к базе данных. Как уже отмечалось, есть еще ADO и InterBase. Но общий принцип работы такой.

В данном случае всю информацию о доступе к конкретной базе данных в данной программе хранит TTable. В ней и были заданы свойства DatabaseName и TableName. В компоненте же DataSource1 был задан набор данных как Table1. После этого DataSource стал промежуточным звеном между таблицей и компонентами TDBEdit и TDBImage, отвечавшими за отображение и редактирование записей.

Последние компоненты "понимают", к какому полю таблицы относятся, по свойству FieldName.
^

1.8.Компонент TTable. Создание таблиц. Типы полей


Этот компонент отвечает за системное соединение с выбранной базой данной и соответствующей таблицей. Для подключения используется текущая конфигурация BDE. Выбранный alias задается в свойстве DatabaseName, а выбранная таблица в свойстве TableName.

При этом этот компонент автоматически сканирует все возможные таблицы для предоставления доступа к ним. Если для доступа к выбранной базе (например, MS Access 97 Database) необходим ввод логина и/или пароля, при соединении появится дилоговое окно. Это окно чаще всего используется при доступе к базам данных ODBC.

Свойство Active таблицы дает возможность активировать ее уже на стадии выполнения. При этом автоматически тестируется соединение. Если при подобном тестировании вылетает какая-нибудь ошибка, чаще всего это какая-то ошибка настройки alias.

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

Насчет создания таблиц. Как мы знаем, таблица определяется полями и их типами. Типы бывают разные. Можно привести их все, правда, много места займет. DD - это Database DeskTop.

Название поля
в DD


Константа

Описание

 

ftUnknown

Неизвестный, неограниченный тип.

Alpha A

ftString

Одиночный символ или целая строка.

Short S

ftSmallInt

Короткое целое, размерностью 16 бит.

Integer I

ftInteger

Стандартное целое, размерность 32 бит.




ftWord

Слово - целое размерностью 16. В отличие от short, не имеет знака.

Logical L

ftBoolean

Логическая переменная - принимает значения true




ftFloat

Число с плавающей точкой.




ftCurrency

Всеми нами любимая валюта - спецформат :).




ftBCD

Поле, содержащее кодированное в бинарном формате десятичное значение.

Date D

ftDate

Дата - тоже специальный формат.

Time T

ftTime

Аналогично время.




ftDateTime

И дата, и время в одном флаконе :)

Bytes Y

ftBytes

Фиксированное количество байтов.




ftVarBytes

Вариантное (нефиксированное) количество байтов.

AutoIncrement +

ftAutoInc

Поле-автоинкремент, которое увеличивается автоматически при добавлении новой записи.




ftBlob

Большой Бинарный ОБъект - оюычно что-то вроде изображения.

Memo M

ftMemo

Поле типа Memo. В обще по своей структуре напоминает AnsiString - неограниченный размер.

Graphic G

ftGraphic

Поле типа Bitmap - стандартный BMP файл.

Formatted Memo F

ftFmtMemo

Форматированное поле Memo.

OLE O

ftParadoxOle

Поле OLE для таблиц типа Paradox.




ftDBaseOle

Поле OLE для таблиц dBase.

Binary B

ftTypedBinary

Типизированный бинарный формат.




ftCursor

Содержит образ курсора, выдаваемого хранимой процедурой данных Oracle.




ftFixedChar

Поле - одиночный символ.




ftWideString

Строка UNICODE-символов - wide chars. Аналогично типу WideString.

Long Integer L

ftLargeInt

Написано LargeInt, читай long int.




ftADT

Поле абстрактного типа.




ftArray

Массив.




ftReference

Ссылка.




ftDataSet

Набор данных.




ftOraBlob

Большой Бинарный ОБъект для баз данных Oracle 7 и иже с ними.




ftOraClob

CLOB - тип для той же компании.




ftVariant

Вариантное поле. Его тип может динамически изменяться во время работы программы




ftInterface

Интерфейс.




ftIDispatch

Интерфейс IDispatch.




ftGuid

Стандартный GUID - универсальный OLE/COM идентификатор.



^

1.9.Создание таблиц. Ключи и индексы


Поле - это ячейка в таблице. Запись - набор из полей. Существуют разные типы полей - обычные, индексные и ключевые. Обычные поля - просто данные. Индексное поле - поле, по которому данные сортируются. Ключевое - поле, значение которого уникально.

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

В BDE достаточно логично поределена структура построения полей и их типов. Для этого имеются классы TxxxDef (три икса здесь обозначают подстановку, а то мало ли что Вы подумаете ;)), произведенные ото абстрактного базового класса TNamedItem. В компоненте TTable имеются и соответствующие свойства
  • TIndexDefs
  • TFieldDefs

Как и следовало предполагать, эти свойства содержат в себе определения индексных и обычных полей. Здесь нет свойства типа TKeyDefs, потому что в таблицах типа Парадокс индексные поля могут быть сами по себе уникальны. За счет этих свойств и задаются параметры таблицы, ее сетка. Создание таблицы довершает метод CreateTable.

Пример:

if (!Table1->Exists) // Проверка существования таблицы

{

Table1->Active = false; // Компонент TTable должен быть отключен.


// Опишем параметры таблицы.

Table1->DatabaseName = "BCDEMOS";//это по желанию

Table1->TableType = ttParadox; //тип таблицы - Парадокс.

Table1->TableName = "CustInfo";//имя создаваемой таблицы.


// Опишем поля и их типы.

Table1->FieldDefs->Clear();

TFieldDef *pNewDef = Table1->FieldDefs->AddFieldDef();

pNewDef->Name = "Field1";// имя, обычной строкой.

pNewDef->DataType = ftInteger;

//установим, является ли поле обязательным

pNewDef->Required = true;

//еще одно поле.

pNewDef = Table1->FieldDefs->AddFieldDef();

pNewDef->Name = "Field2";

pNewDef->DataType = ftString;

//определим размер поля.

pNewDef->Size = 30;


// Теперь взялись за индексы


Table1->IndexDefs->Clear();

/* Первый индекс безымянный, поскольку это основной индекс Парадокса. */


Table1->IndexDefs->Add("","Field1", TIndexOptions() <

Table1->IndexDefs->Add("Fld2Index","Field2", TIndexOptions() << ixCaseInsensitive);


// Ну и наконец, создаем таблицу.


Table1->CreateTable();
^

1.10.Класс TFieldDef.


Этот класс описывает поле, его тип и т.п. Свойства этого класса.

Attributes

Это свойство содержит аттрибуты данного поля. Это множество, состоящее из значений faHiddenCol, faReadonly, faRequired, faLink, faUnNamed, faFixed. Вот что они значат:
  • faHiddenCol

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

Если этот флаг установлен, то редактирование данного поля запрещено.
  • faRequired

Данное поле обязательно должно содержать установленное значение.
  • faLink

Внутренний флаг для вложенных таблиц.
  • faUnNamed

Только для внутреннего использования.
  • faFixed

Обозначает, что поле имеет фиксированный размер.

ChildDefs

Это свойство и с ним связанные относятся не ко всем разновидностям (потомкам) класса TFieldDef, а только к производным TObjectField, например TADTField.

Определяет вложенные определения полей - дочерние поля. Это указатель на объект класса TFiledDefs. Для добавления вложеннных полей используется метод AddChild(void), возвращающий указатель на объект TFieldDef. Свойство ParentDef содержит указатель на родительское поле. Взаимосвязь - fDef = fDef->AddChild()->ParentDef. Метод HasChildDefs(void) возвращает, есть ли у данного поля вложенные.

DataType

Это свойство определяет реальный тип физического поля (того, которое записано в таблице или выдается по SQL запросу). Разные специализированные потомки TFieldDef автоматически проставляют значение этого свойсва. Пользователи, впрямую работающему с TFieldDef, приходится вручную устанавливать его значение.

FieldClass

Определяет метакласс поля, основываясь на значении DataType. Возвращается значение, к которому можно приравнять с помощью оператора __classid, например, fDef->DataType = ftInteger; fDef->FieldClass==__classid(TIntegerField);

InternalCalcField

Есть понятие RequestLive запроса, то есть запроса, который выдает динамически просчитываемые данные. Например, как в часто бывает на практике, есть поле ЦЕНА и поле КОЛИЧЕСТВО. Какое-либо поле типа ИТОГ не должно быть ведено отдельно и вводится отдельно. Это источник ошибок и вообще нерациональный метод ведения базы. Для этого есть запросы, например

^ SELECT ЦЕНА, КОЛИЧЕСТВО (ЦЕНА*КОЛИЧЕСТВО)

FROM DATA

Вот третье поле-то и будет ИТОГ. InternalCalcField как раз и определяет, является ли поле динамическим или нет. Это read-only property, его значение менять нельзя.

Required, Size

Своство Required определяет, обязательно ли поле должно иметь значение вообще. Свойство Size дает возможность установить или считать размер для поля. Тип поля должен быть следующий: ftString, ftBCD, ftBytes, ftVarBytes, ftBlob, ftMemo или ftGraphic.

Collection

Определяет указатель на содержащий данный объект (this) объект-список, коллекцию, производный абстрактного класса TCollection.

Это наиболее значимые свойства данного класса. Надо отметить, что обычно вместо этого класса используются более специализированные, например TADTFiled, TGraphicField, TStringField. Но основные свойства у них эти.
^

1.11.Коллекция TFieldDefs


Коллекция - в общем-то, специальный список с конкретизированными под данные нужды методами и свойствами. Вот TFieldDefs - коллекция для определений TFieldDef:

HiddenFields

Определеят, следует ли отображать дополнительные скрытые поля в запросе к базе данных. Преимущественно для внутреннего использования.

Items

Свойство типа массив, содержащее указатели на объекты типа TFieldDef.

ParentDef

Вроде мы уже это видели :). Определяет родительское (parent)поле. Логично :).

DataSet

Набор данных, использующий данную коллекцию. Я уже говорил, что по иерархии к DataSet относятся TTable и TDataSource.

Updated

Определяет, совпадают ли определения полей в реальном наборе данных и в данной коллекции.

Count

Количество полей.

Это были свойства. А теперь методы.

Add

Описание -

HIDESBASE void __fastcall Add(const AnsiString Name, TFieldType DataType, int Size, bool Required);

Параметр Name определяет имя для нового FieldDef, dataType тип поля, Size его размер, ну а Required - обязательно ли присвоение значения этому полю.

Пример использования - Table1->FieldDefs->Add("IntField",ftInteger,4,false);.

AddFieldDef

Описание -

TFieldDef* __fastcall AddFieldDef(void);

Этот метод возвращает указатель на новый объект типа TFieldDef, а потом уже можно с этим указателем делать все что угодно. Пример:

void TForm1::Example()

{

TFieldDef* def = Table1->FieldDefs->AddFieldDef();

def->DataType=ftString; //например

def->Size=20;

def->Required=true;//тоже например

}

Update

Описание -

HIDESBASE void __fastcall Update(void);

Обновляет записи в источнике данных (чаще всего таблице).

Find

Описание -

HIDESBASE TFieldDef* __fastcall Find(const AnsiString Name);

Производит поиск по коллекции, сравнивая значения Name полей. Как видно из описания, возвращает указатель на объект найденный. Если он не найден, то... Как это ни странно, возвращается не NULL, а чтобы определить, найден или нет, нужно вызвать метод IndexOf класса TDefCollection (предок TFieldDefs). О нем.

IndexOf

Описание -

int __fastcall IndexOf(const AnsiString AName);

Возвращает индекс данного объекта TFieldDef. Если нет такого, возвращается -1.
^

1.12.Изменение значений полей


А сейчас мы попробуем создать форму в стиле "Мастера форм" MS Access. В этом нам очень помогут компоненты с вкладки Data Controls, а именно TDBEdit, TDBComboBox, TDbCheckBox, TDBNavigator. После размещения всех элементов на форме получим следующее окно:



Теперь переходим к начинке системы. Бросаем объект TDataSource туда же. Выбираем все уже брошенные компоненты (кроме само собой TDataSource), и ставим их DataSource = DataSource1. Просто оценивая ситуацию поверхностным взглядом, ясно, что чего-то не хватает... А, нужно еще обозначить, к каким полям таблицы имеют отношение все элементы. Так как design-time таблицу мы подключить по ясным причинам (разные формы) не можем, то с клавиатуры впечатываем в свойства DataField компонентов имена соответствующих полей.

Реализуем свой просмотрщик в виде ^ MDI-приложения, как это делали ранее. Напомню, что для MDI приложения одно окно (главное) должно иметь FormStyle = fsMDIForm, а все остальные принадлежащие клиентской области этого окна окна должны иметь FormStyle = fsMDIChild. Настоятельно рекомендуется все формы, кроме главной, создавать динамически (вкладка Forms меню Project->Options). Функция создания окон должна выглядеть так:

TForm* TTextMain::AddChild(String fName,String caption)

{

TForm* child = NULL;

if(fName=="BOOKLIST")

child = new TBookList(this);

if(fName=="EDITBOOK")

child = new TEditBook(this);

if(!child)

{

child = new TTextView(this);

try

{

((TTextView*)child)->Output->Lines->LoadFromFile(fName);

}

catch(...)

{

delete child;

return 0;

}

}

Pages->Tabs->AddObject(caption,child);

Pages->TabIndex = Pages->Tabs->Count - 1;

child->Caption = caption;

child->Tag = Pages->Tabs->Count - 1;

return child;

}

В программе-просмотрщике окна подразделяются на несколько типов - список книг (^ TDBGrid), редактор элементов таблицы (созданный только что) и далее мы еще напишем список истории чтения. Соответственно fName - это имя файла с текстом книги. Если fName - некоторое предопределенное значение ("BOOKLIST" например), то создается вариант окна на эту тему, иначе открывается файл с книгой. Компонент TTabControl* Pages - некий суррогат панели задач, предоставляет быстрый доступ к окнам. Если все делалось правильно, то должна получится такого рода форма:


^

1.13.Проект приложения CView


Далее в разработке этого приложения созданим историю по принципу FIFO. Реализация представлена ниже:

void TTextHist::LoadHistory(String fName)

{

hist->Items->BeginUpdate();

hist->Clear();

dataset->DisableControls();

TListItem* itm = hist->Items->Add();

int p = dataset->RecNo;

dataset->First();

int cur = -1;

for(int i=0;iCount;i++)

{

dataset->RecNo = history->Names[i].ToInt();

cur = dataset->RecNo;

TListItem* itm = hist->Items->Add();

itm->Caption = dataset->Fields->Fields[1]->AsString;

itm->SubItems->Add(dataset->Fields->Fields[0]->AsString);

itm->SubItems->Add(dataset->Fields->Fields[2]->AsString);

itm->Data = (void*)cur;

}

dataset->RecNo = p;

dataset->EnableControls();

hist->Items->EndUpdate();

}

Формат файла истории hist.inf выглядит следующим образом:

;номер книги=позиция полосы прокрутки

23=100

Занесение в историю выполняется при добавлении очередного TextView.

TForm* TTextMain::AddChild(String fName,String caption,int id)

{

TForm* child = NULL;

if(fName=="BOOKLIST")

child = new TBookList(this);

if(fName=="EDITBOOK")

child = new TEditBook(this);

if(fName=="TEXTHIST")

child = new TTextHist(this);

if(!child)

{

for(int i=0;iClassName())=="TTextView")

if(((TTextView*)MDIChildren[i])->id==id)

{

BringWindowToTop(MDIChildren[i]->Handle);

return 0;

};

child = new TTextView(this);


try

{

((TTextView*)child)->Output->Lines->LoadFromFile(fName);

}


catch(...)

{

delete child;

return 0;

}


((TTextView*)child)->id = id;

int x = history->IndexOfName(id);


if(x!=-1)

{

history->Exchange(0,x);

SendMessage(((TTextView*)child)->Output->Handle,

EM_LINESCROLL,0,history->Values[id].ToInt());

}

else

{

history->Insert(0,String(id)+"=0");

if(history->Count>count)

history->Delete(count);

}

}

Pages->Tabs->AddObject(caption,child);

Pages->TabIndex = Pages->Tabs->Count - 1;

child->Caption = caption;

child->Tag = Pages->Tabs->Count - 1;

child->OnActivate = (TNotifyEvent)&ChildShow;

return child;

}

Принцип FIFO предполагает, что последний внесенный объект будет стоять на первом месте, а первый внесенный объект при этом удаляется.

Сохранение истории происходит при закрытии окна:

void __fastcall TTextMain::FormClose(TObject *Sender, TCloseAction &Action)

{

for(int i=0;iClassName())=="TTextView")

history->Values[((TTextView*)MDIChildren[i])->id] =

IntToStr(GetScrollPos(((TTextView*)MDIChildren[i])->Output->Handle,SB_VERT));

history->SaveToFile("hist.inf");

}

В данном случае перебором всех дочерних окон выбираются только относящиеся к типу TTextView. Для определения позиции полосы прокрутки используется стандартная WinAPI функция GetScrollPos.
^

1.14.Создание произвольной таблицы


Для создания таблицы используется метод CreateTable() компонента TTable (или любого другого аналогичного ему). Строго говоря, в таблице существуют простые поля и индексные. По индексным полям производится автоматическая сортировка. Предварительные описания полей содержатся в свойстве FieldDefs. В качестве примера создадим программу создающую произвольную таблицу . Форма ее будет такова:



Компонент TTable нужно настроить на конкретный алиас, используем ^ BCDEMOS. В TComboBox* FieldType и заполним все значения типов полей:

ftUnknown ftString ftSmallint ftInteger ftWord

ftBoolean ftFloat ftCurrency ftBCD ftDate

ftTime ftDateTime ftBytes ftVarBytes ftAutoInc

ftBlob ftMemo ftGraphic ftFmtMemo ftParadoxOle

ftDBaseOle ftTypedBinary ftCursor ftFixedChar

ftWideString ftLargeint ftADT ftArray ftReference

ftDataSet ftOraBlob ftOraClob ftVariant ftInterface

ftIDispatch ftGuid ftTimeStamp ftFMTBcd

Очень важным является соблюдения порядка, соответствующего enum TFieldType. Затем пишем код:

//---------------------------------------

void __fastcall TForm1::AddDefClick(TObject *Sender)

{

ListBox->Enabled = false;

AddBox->Enabled = true;

}


//---------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)

{

table->FieldDefs->Clear();

}

//---------------------------------------

void __fastcall TForm1::AddFieldClick(TObject *Sender)

{

TFieldDef* def = table->FieldDefs->AddFieldDef();

def->Name = FieldName->Text;

def->Size = FieldSize->Text.ToInt();

def->DataType = (TFieldType)FieldType->ItemIndex;

def->Attributes << (TFieldAttribute)((faHiddenCol&FieldHidden->Checked)|

(faRequired&FieldRequired->Checked)|

(faReadonly&FieldReadOnly->Checked)|

(faFixed&FieldFixed->Checked));

Fields->Items->AddObject(FieldName->Text,def);

Fields->ItemIndex = Fields->Items->Count - 1;

CancelFieldClick(0);

}


//---------------------------------------

void __fastcall TForm1::CancelFieldClick(TObject *Sender)

{

ListBox->Enabled = true;

AddBox->Enabled = false;

}


//---------------------------------------

void __fastcall TForm1::BitBtn1Click(TObject *Sender)

{

for(int i=0;iItems->Count;i++)

((TFieldDef*)Fields->Items->Objects[i])->FieldNo = i;

table->TableType = (TTableType)TableType->ItemIndex;

table->TableName = TableName->Text;

table->CreateTable();

}


//---------------------------------------

void __fastcall TForm1::RemoveDefClick(TObject *Sender)

{

table->Active = false;

if(Fields->ItemIndex==-1)return;

TFieldDef* def = (TFieldDef*)Fields->Items->Objects[Fields->ItemIndex];

table->FieldDefs->Delete(def->Index);

Fields->DeleteSelected();

}


//---------------------------------------

void __fastcall TForm1::FieldsChange(TObject *Sender)

{

TFieldDef* def = (TFieldDef*)Fields->Items->Objects[Fields->ItemIndex];

FieldSize->Text = def->Size;

FieldType->ItemIndex = def->DataType;

FieldName->Text = def->Name;

FieldHidden->Checked = def->Attributes.Contains(faHiddenCol);

FieldRequired->Checked = def->Attributes.Contains(faRequired);

FieldReadOnly->Checked = def->Attributes.Contains(faReadonly);

FieldFixed->Checked = def->Attributes.Contains(faFixed);

}