В рассмотренных примерах выполнялось чтение содержимого полей текущей записи. Аналогичным образом можно присваивать произвольному полю текущей записи новое значение, при этом набор данных должен находиться в режиме редактирования или вставки.
Например, с помощью следующих инструкций:
Var x: integer;
// Перевод набора данных в режим редактирования
Tablel.Edit;
// Изменение значений полей
Tablel.FieldByName('Name').AsString:= Editl.Text;
Tablel.FieldByName('Number').Aslnteger:= x;
// Сохранение изменений
Tablel.Post;
выполняется присвоение новых значений полям Name и Number текущей записи после того, как набор данных Tablel переведен в режим редактирования. Произведенные изменения сохраняются, а набор данных переводится в режим просмотра.
Особенности набора данных Table
Компонент Table представляет собой набор данных, который в текущий момент времени может быть связан только с одной таблицей БД. Этот набор данных формируется на базе навигационного способа доступа к данным, поэтому
Глава 5. Компоненты доступа к данным
93
компонент Table рекомендуется использовать для локальных БД, таких как dBase или Paradox. При работе с удаленными БД следует использовать компонент Query. В дальнейшем при рассмотрении вопросов, связанных с локальными БД, мы обычно будем работать с компонентом Table.
Связь между таблицей и компонентом Table устанавливается через его свойство TableName типа TFileName, которое задает имя таблицы (и имя файла с данными таблицы). При задании свойства TableName указываются имя файла и расширение имени файла.
На этапе разработки приложения имена всех таблиц доступны в раскрывающемся списке Инспектора объектов. В этот список попадают таблицы, файлы которых расположены в каталоге, указанном свойством DatabaseName.
|
(Замечание^
При смене имени таблицы на этапе проектирования приложения свойство Active набора данных автоматически устанавливается в значение False. При задании имени таблицы программным способом набор данных предварительно необходимо закрыть, установив его свойство Active в значение False. d противном случае генерируется исключение.
Приведем пример, иллюстрирующий, как задается имя таблицы БД:
procedure TForml.ButtonlClick(Sender: TObject);
begin
if OpenDialogl.Execute then begin
Tablel.Active:= False;
Tablel.TableName:= OpenDialogl.FileName;
Tablel.Active:= True;
end; end;
Здесь нажатие кнопки Buttonl приводит к появлению диалогового окна выбора имени файла. При выборе файла таблицы его имя устанавливается в качестве значения свойства TableName. Набор данных Tablel предварительно закрывается и снова открывается уже после смены таблицы. Тип таблицы определяется автоматически по расширению имени файла. При наличии ошибок, например, связанных с нарушением структуры таблицы, выдается соответствующее сообщение, а набор данных остается закрытым.
Свойство ТаЫеТуре типа TTtableType определяет тип таблицы. Для локальных таблиц это свойство может принимать следующие значения:
□ ttDefault — тип таблицы автоматически определяется по расширению файла;
□ ttParadox — таблица Paradox;
□ ttDBase — таблица dBASE;
94
Часть I. Основы работы с базами данных
П ttFoxPro — таблица FoxPro;
□ ttASCII — текстовый файл, содержащий данные в табличном виде (таблица
ASCII).
Если свойство ТаЫеТуре имеет значение ttDefault (по умолчанию), то тип таблицы определяется по расширению файла:
□ db или отсутствует — таблица Paradox;
□ dbf — таблица dBASE;
|
□ txt — текстовый файл (таблица ASCII).
По умолчанию в состав набора данных Table попадают все записи связанной с ним таблицы. Для отбора записей, удовлетворяющих определенным условиям, используются фильтры.
Delphi через BDE автоматически поддерживает многопользовательский доступ к локальным таблицам. При этом по умолчанию все пользовательские приложения имеют равные права и могут редактировать содержащиеся в таблицах данные. Чтобы запретить пользователям изменять содержание записей, можно использовать свойство Readonly типа Boolean. По умолчанию оно имеет значение False, что предоставляет пользователю право изменения записей.
Если приложению требуется получить к таблице монопольный доступ, то это можно осуществить через свойство Exclusive типа Boolean. По умолчанию свойство имеет значение False, и для таблицы, с которой связан набор данных, действует многопользовательский режим доступа. Если установить свойство Exclusive в значение True, то приложение получает монопольный доступ к соответствующей таблице, при этом другим приложениям доступ к таблице запрещается. Перед заданием значения свойства Exclusive набор данных должен быть закрыт, т. е. разорвана его связь с таблицей. Если какое-либо приложение или набор данных этого же приложения уже взаимодействуют с таблицей, то попытка установить режим монопольного доступа к ней вызовет исключение.
Монопольный режим доступа необходим при выполнении таких операций, как добавление или удаление индекса методами Addindex и Deleteindex или очистка таблицы методом EmptyTable.
(_____ ЗамечаниеJ
Такие приложения, как Delphi и Database Desktop, также могут осуществлять доступ к таблицам. Поэтому перед отладкой приложения, которое устанавливает монопольный доступ к таблице, необходимо проверить, не работают ли с этой таблицей Delphi и/или Database Desktop. В приложении Database Desktop таблицу нужно закрыть, а в среде Delphi достаточно через Инспектор объектов установить в значение False свойство Active набора данных, связанного с таблицей.
|
В наборе данных Table можно указать текущий индекс для:
□ сортировки записей;
□ поиска записей;
□ установления связей между таблицами.
Глава 5. Компоненты доступа к данным
95
Текущий индекс устанавливается с помощью свойства indexName или indexFieldNames типа string. На этапе разработки приложения текущий индекс выбирается в списке индексов, заданных при создании таблицы. Все возможные значения свойств IndexName и IndexFieldNames содержатся в раскрывающихся списках, доступных через Инспектор объектов. Оба свойства во многом схожи, и их использование практически одинаково. Значением свойства IndexName является имя индекса, заданное при создании таблицы, а значением свойства IndexFieldNames является имя поля, для которого был создан индекс. Если индекс состоит из нескольких полей, то для свойства IndexName по-прежнему задается имя этого индекса, а для свойства IndexFieldNames через точку с запятой перечисляются имена полей, входящие в этот индекс.
Вот как текущий индекс задается в программе:
Tablel.IndexName:= 'indName'; Table2.IndexFieldNames:= 'Name';
Здесь компоненты Tablel и ТаЫе2 связаны с одной таблицей, для поля Name которой определен индекс indName. Этот индекс устанавливается в качестве текущего для обоих наборов данных.
Для таблиц Paradox сделать текущим индексом ключ (главный индекс) можно только с помощью свойства IndexFieldNames, перечислив ключевые поля таблицы, т. к. ключ не имеет имени и поэтому недоступен через свойство IndexName.
Задать ключ в качестве текущего индекса можно так:
Tablel.IndexFieldNames:= 'Name;Post;BirthDay';
Здесь для таблицы Paradox, с которой связан компонент Tablel, определен ключ, в который входят поля Name, Post и BirthDay. Этот ключ устанавливается в качестве текущего индекса таблицы.
(_____ ЗамечаниеJ
Свойства IndexName и IndexFieldNames взаимозависимы. При установке значения одного из них другое автоматически очищается.
Индекс, устанавливаемый текущим, должен существовать. Если индекс, задаваемый как значение свойства IndexName или IndexFieldNames, для таблицы не существует, то возникает исключение.
При смене таблицы, с которой ассоциирован компонент Table, значения свойств IndexName и IndexFieldNames не изменяются автоматически, поэтому программист должен установить нужные значения самостоятельно.
Получить доступ к полям в составе текущего индекса можно с помощью свойств IndexFieldCount и IndexFields.
Свойство IndexFieldCount типа Integer содержит число полей в текущем индексе и доступно для чтения при выполнении приложения.
Свойство IndexFields [Index: Integer] типа TField позволяет обращаться к полям текущего индекса, при этом переменная index задает номер индекса в
96
Часть I. Основы работы с базами данных
массиве полей этого индекса (отсчет начинается с нуля). Класс TField представляет собой поле набора данных и имеет большое число свойств и методов.
Чаще всего индексы определяются при создании таблицы и в дальнейшем при работе с таблицей не изменяются. Однако у программиста есть возможность изменять определенные для таблицы индексы динамически, т. е. в процессе выполнения приложения, с помощью методов Addlndex и Deletelndex.
(Замечание^
Допускается изменять индексы для таблицы, открытой в режиме монопольного доступа, когда свойство Exclusive имеет значение True.
Процедура Addlndex (const Name, Fields: String; Options: TIndexOptions) добавляет к таблице индекс, имя которого задано параметром Name. Входящие в состав индекса поля указываются в параметре Fields; если индекс состоит из нескольких полей, то они разделяются точкой с запятой. Указывать можно только поля, которые входят в структуру таблицы, в противном случае генерируется исключение, а индекс не создается. Параметр Options содержит параметры индекса. Он имеет множественный тип и может принимать комбинации следующих значений:
□ ixPrimarу (первичный индекс);
□ ixUnique (уникальный индекс) — для этого индекса не допускается повторение значений полей в его составе;
□ ixDescending (сортировка в порядке убывания значений) — по умолчанию строится индекс, определяющий сортировку по возрастанию;
□ ixExpression (индекс создается на основе выражения) — только для таблиц dBase;
□ ixCaseinsensitive (сортировка не зависит от регистра букв);
□ ixNonMaintained (индекс автоматически не изменяется, если таблица открыта).
Приведем пример, демонстрирующий добавление индекса к таблице:
procedure TForml.Button3Click(Sender: TObject);
begin
// Перевод таблицы в режим монопольного доступа
Tablel.Close;
Tablel.Exclusive:= True;
Tablel.Open;
// Добавление индекса
Tablel.Addlndex('indPosition', 'Position', [ixDescending, ixCaseinsensitive]);
// Закрытие режима монопольного доступа к таблице
Tablel.Close;
Глава 5. Компоненты доступа к данным
97
Tablel.Exclusive:= False;
Tablel.Open;
end;
Здесь к таблице, с которой связан набор данных Tablel, добавляется индекс indPosition, построенный по полю Position. Для нового индекса определяется порядок сортировки по убыванию значений, не зависящий от регистра букв.
Процедура Deletelndex (const Name: String) удаляет из таблицы индекс, имя которого задано параметром Name. При попытке удаления несуществующего индекса генерируется исключение.
В программе удаление индекса из таблицы можно реализовать так:
Tablel.Deletelndex('indPosition');
Перед удалением индекса таблица должна быть переведена в режим монопольного доступа аналогично тому, как это происходило при добавлении индекса.
Для доступа к информации обо всех индексах, определенных для таблицы и, соответственно, для связанного с ней набора данных, можно использовать свойство indexDef s типа TindexDef s. Это свойство доступно как на этапе разработки, так и на этапе выполнения приложения. Класс TindexDefs в свою очередь также имеет полезные свойства и методы, которые мы сейчас и рассмотрим.
Перед работой с индексами всегда рекомендуется вызывать метод UpDate, который производит обновление информации об индексах так, чтобы значение свойства IndexDef s отражало реальное состояние с учетом сделанных изменений.
Свойство Count типа integer содержит количество индексов и доступно для чтения. Управление количеством индексов осуществляется косвенно, т. е. через другие свойства и методы.
Свойство Items [Index: Integer] типа TindexDef представляет собой список, содержащий информацию обо всех индексах таблицы. Переменная index указывает номер индекса в списке, отсчет начинается с нуля. Тип TindexDef (не путать с классом TindexDefs) является классом и, в свою очередь, также имеет свойства, главные из которых — Name, Fields и Options.
(_____ ЗамечаниеJ
При доступе к информации об индексах можно не указывать свойство Items. Например, чтобы считать в редактор Editl список полей, составляющих второй индекс, можно использовать следующие эквивалентные по действию инструкции:
Editl.Text:= Tablel.IndexDefs[1].Fields;
или
Editl.Text:= Tablel.IndexDefs.Items[1].Fields;
Свойство Name типа string содержит имя индекса. Для индексов, построенных на основе выражений (таблицы dBase), и для главного индекса таблиц Paradox вместо имени возвращается пустая строка.
98
Часть I. Основы работы с базами данных
Свойство Fields типа string содержит имена полей, по которым построен индекс. Если в индексе используется несколько полей, то их имена разделяются точкой с запятой.
Свойство Options типа TindexOption содержит параметры индекса, заданные при его создании.
Рассмотрим работу со списком индексов и индексных полей на примере.
В форме расположены следующие компоненты: сетка DBGrid, в которой отображаются записи таблицы БД, два списка ListBox с соответствующими надписями, а также две кнопки Button. При нажатии кнопки Индексы (Buttonl) в список ListBoxl загружается список индексов, определенных для набора данных Tablel, а в список ListBox2 — список полей, образующих эти индексы (рис. 5.2). Так как компонент Tablel связан с таблицей Paradox, то имя главного индекса, построенного по полю P_Code, содержит пустую строку.
Обработчик события нажатия кнопки Buttonl выглядит так:
procedure TForml.ButtonlClick(Sender: TObject);
var n: integer;
begin
for n:= 0 to Tablel.IndexDefs.Count - 1 do begin
ListBoxl.Items.Add(Tablel.IndexDefs[n].Name);
ListBox2.Items.Add(Tablel.IndexDefs[n].Fields);
Рис. 5.2. Получение списка индексов и полей |
Для получения списка имен индексов можно использовать методGetitemNames (List: TStrings). Он возвращает список имен индексов через |
end; end;
Глава 5. Компоненты доступа к данным
99
параметр List, в качестве которого можно использовать любой объект типа TStrings, например, ListBoxItems.
Получение списка имен индексов в программе может выглядеть так:
ListBoxl.Items.Clear; Tablel.GetltemNames(ListBoxl.Items);
Для добавления и удаления индексов используются методы Add и clear. Процедура Add (const Name, Fields: String; Options: TIndexOptions) добавляет новый индекс. Параметры этой процедуры не отличаются от параметров метода Addindex набора данных Table, однако для метода Add не требуется перевод таблицы в режим монопольного доступа, что делает его использование более удобным.
(Замечание^
Для таблиц Paradox при определении ключа (главного индекса) имя индекса не задается, т. к. этот индекс не именуется.
Процедура clear удаляет все индексы, содержащиеся в списке индексов. Вот как удаление и добавление индексов к таблице реализуется в программе:
Tablel.IndexDefs.Clear;
Tablel.IndexDefs.Add('', 'Number', [ixPrimary, ixUnique]); Tablel.IndexDefs.Add('indMain', 'Code;Position', [ixDescending, ixCaselnsensitive]);
В этом примере из набора данных Tablel, связанного с таблицей Paradox, удаляются все индексы и создаются два новых индекса: первичный индекс, построенный по полю Number, и вторичный индекс indMain, построенный по полям
Code и Position.
Ряд методов предназначен для поиска индексов в списке, например, indexOf, Find и FindindexForFields. Их удобно использовать в случае, когда индексы или их поля вводит пользователь на этапе выполнения приложения. Перед использованием таких индексов целесообразно проверять, существуют ли они в списке индексов, т. к. в противном случае мы рискуем получить исключение.
Функция IndexOf (const AName: String): Integer осуществляет ПОИСК индекса по имени, заданному параметром AName. В качестве результата возвращается номер индекса в свойстве items. В случае неудачного поиска возвращается значение -1.
Рассмотрим пример поиска индекса:
procedure TForml.Button2Click(Sender: TObject); begin
if Tablel.IndexDefs.IndexOf(Editl.Text) = -1 then begin MessageDlg('Индекс отсутствует!', mtError, [mbOK], 0);
100
Часть I. Основы работы с базами данных
if Editl.CanFocus then Editl.SetFocus; end; end;
Здесь при нажатии кнопки Button2 выполняется проверка существования индекса, имя которого введено в поле ввода Editl. При отсутствии в наборе данных Tablel указанного индекса выдается сообщение об ошибке, и фокус ввода устанавливается на Editl.
Функция FindlndexForFields(const Fields: String): TIndexDef осуществляет поиск индекса по списку полей, заданному параметром Fields. В случае успешного поиска функция возвращает информацию об индексе, если же индекс отсутствует, то генерируется исключение.
(_____ ЗамечаниеJ
Если не найден индекс, поля которого полностью совпадают с заданными, но есть индексы, которые включают в себя все заданные поля, то в качестве результата возвращается первый такой индекс.
При запуске приложения информация об индексах таблицы считывается с диска из соответствующих индексных файлов. При динамическом, т. е. в процессе выполнения приложения, изменении индексов содержимое индексных файлов остается прежним. При необходимости программист должен предусмотреть сохранение новой информации на диске для ее последующего применения. Для этого можно использовать свойство storeDef s типа Boolean, которое указывает, нужно ли сохранять информацию об индексах на диске. При любых изменениях в индексах это свойство нужно установить в значение True, тогда информация об индексах будет автоматически сохранена на диске. Если изменения в индексах сохранять не нужно, то достаточно установить свойство storeDefs в значение False, и изменения в индексах будут действовать только при выполнении приложения.
Особенности набора данных Query
Компонент Query представляет собой набор данных, записи которого формируются в результате выполнения SQL-запроса и основаны на реляционном способе доступа к данным. При работе с удаленными БД рекомендуется использовать именно набор данных Query.
(_____ ЗамечаниеJ
При работе с удаленными БД следует обращаться к средствам языка SQL. Это относится и к таким операциям, как перемещение по набору данных или вставка в него записей. Если же для компонента Query используются методы типа Next или Insert, то вместо реляционного способа доступа к удаленным данным будет применен навигационный. В результате набор данных Query будет мало отличаться от набора данных Table.
Глава 5. Компоненты доступа к данным
101
В отличие от компонента Table, набор данных Query может включать в себя записи более чем одной таблицы БД.
Текст запроса, на основании которого в набор данных отбираются записи, содержится в свойстве SQL типа TStrings. Запрос включает в себя команды на языке SQL и выполняется при открытии набора данных. Запрос SQL иногда называют SQL-программой.
При формировании запроса на этапе разработки приложения можно использовать текстовый редактор (рис. 5.3), вызываемый через Инспектор объектов двойным щелчком в области значения свойства SQL.
Рис. 5.З. Редактирование запроса SQL
SQL-запрос также можно формировать и изменять динамически, внося изменения в его текст (значение свойства SQL компонента Query) непосредственно при выполнении приложения.
Замечание
J
В процессе формирования SQL-запроса проверка его правильности не производится, и если в запросе имеются ошибки, то они выявляются только при открытии набора данных. Одним из вариантов предотвращения ошибок в SQL-запросе является его предварительная отладка, например, с помощью программы Database Desktop.
Рассмотрим пример приложения — простейшего редактора, позволяющего подготавливать и выполнять SQL-запросы. На рис. 5.4 показана форма приложения при его выполнении. Кроме визуальных компонентов, форма содержит два компонента доступа к данным Queryl и DataSourcel, которые при выполнении приложения не видны.
102
Часть I. Основы работы с базами данных
Рис. 5.4. Приложение-редактор SQL-запросов
Редактирование SQL-запроса осуществляется с помощью компонента Memol. Набранный запрос выполняется при нажатии кнопки Выполнить (Buttonl), a результат выполнения отображается в компоненте DBGridl.
При наличии в тексте SQL-запроса ошибки генерируется исключение и выдается сообщение об ошибке (рис. 5.5), а результат запроса оказывается не определен. При этом набор данных Queryl автоматически закрывается.
Значения свойств DataSet источников данных DataSourcel и DataSource компонента DBGridl, с помощью которых организуется взаимодействие компонентов Queryl, DataSourcel и DBGridl, устанавливаются при создании формы. В последующих примерах приложений значения этих свойств задаются через Инспектор объектов, поэтому инструкции, присваивающие свойствам необходимые значения, в модуле формы отсутствуют.
Рис. 5.5. Сообщение об ошибке в тексте SQL-запроса
Приведем код модуля uSQLEdit формы Forml приложения:
unit uSQLEdit; interface
Глава 5. Компоненты доступа к данным
103
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Grids, DBGrids, Db, DBTables;
type
TForml = class(TForm) Memol: TMemo; DataSourcel: TDataSource; Queryl: TQuery; DBGridl: TDBGrid; Buttonl: TButton; Labell: TLabel; Label2: TLabel; procedure FormCreate(Sender: TObject); procedure ButtonlClick(Sender: TObject); private
{ Private declarations } public
{ Public declarations } end;
var
Forml: TForml;
implementation
{$R *.DFM}
procedure TForml.FormCreate(Sender: TObject); begin
DataSourcel.DataSet:= Queryl; DBGridl.DataSource:= DataSourcel; end;
procedure TForml.ButtonlClick(Sender: TObject); begin
Queryl.Close;
Queryl.SQL.Assign(Memol.Lines); Que г у 1. Open; end;
end.
Метод Assign выполняет присваивание одного объекта другому, при этом объекты должны иметь совместимые типы. Применительно к списку строк (класс TStrings), которому принадлежат свойства SQL компонента Queryl и Lines
104
Часть I. Основы работы с базами данных
компонента Memol, подобное присваивание означает копирование информации из одного списка в другой с заменой содержимого последнего. Если размеры списков (число элементов) не совпадают, то после замены число элементов заменяемого списка становится равным числу элементов копируемого списка.
Компонент Query обеспечивает выполнение SQL-запроса и является набором данных, который формируется на основе этого запроса. Формирование набора данных выполняется при активизации компонента Query вызовом метода Open или установкой свойства Active в значение True. В ряде случаев при выполнении SQL-запроса не требуется возвращать набор данных, например, при удалении, вставке или изменении записей. В этом случае предпочтительнее выполнять запрос компонента Query не его открытием, а вызовом метода ExecSQL. При работе в сети вызов метода ExecSQL выполняет требуемую модификацию набора данных, не передавая в вызывающее приложение (компьютер) записи набора данных, что заметно снижает нагрузку на сеть.
Компонент Query может быть связан с таблицей БД или напрямую, или содержать копии отобранных записей таблицы, доступные для чтения. Вид взаимодействия определяется свойством RequestLive типа Boolean. По умолчанию свойство имеет значение False, и набор данных Query доступен только для чтения. Если пользователю или программисту требуется возможность редактирования записей, то свойство RequestLive нужно установить в значение True. В этом случае набор данных Query напрямую связывается с соответствующей таблицей, аналогично набору данных Table.
(_____ ЗамечаниеJ
Влияние свойства RequestLive зависит от текста выполняемого SQL-запроса. Если в результате выполнения запроса не может быть получен редактируемый набор данных, то установка свойства RequestLive в значение True игнорируется.
Чтобы проверить результат установки значения свойства RequestLive, можно воспользоваться свойством CanModif у типа Boolean. Если оно имеет значение True, то набор данных является редактируемым, если False — то нередактируемым.
Чтобы получить в результате выполнения SQL-запроса редактируемый набор данных, кроме установки свойства RequestLive в значение True, должны быть выполнены следующие условия:
□ данные отбираются только из одной таблицы или просмотра (view);
□ таблица или просмотр допускают модификацию;
□ в запросе не используется операнд distinct и агрегатные (статистические) функции;
□ в запросе не применяется соединение таблиц;
□ в запросе отсутствуют подзапросы и вложенные запросы;
□ не используется группирование данных;
□ сортировка применяется только к индексированным полям.
Глава 5. Компоненты доступа к данным
Для локальных БД вместо компонента Table можно также использовать компонент Query. Если установить свойство sql в значение select * from NameTableBD, а свойство RequestLive — в значение True, то набор данных Query будет аналогичен набору данных Table. (Здесь NameTableBD является именем таблицы БД, которое для компонента Table задается в свойстве TableName.) Однако набор данных Query, в отличие от Table, не имеет системы индексов, поэтому к Query неприменимы методы, использующие индексирование, например, методы FindFirst, FindLast, FindNext И FindPrior.
Более подробно компонент Query и язык SQL рассматриваются в главе 8, посвященной реляционному доступу к данным.
Объекты поля
Объект поля Field имеет тип TField и служит полем набора данных. Тип TField является абстрактным классом и непосредственно не используется. Вместо него применяются производные классы (табл. 5.1), соответствующие типу данных, размещаемых в рассматриваемом поле набора данных. Производные классы отличаются от базового класса TField некоторыми особенностями, связанными с манипулированием конкретным типом данных, например, символьным, числовым или логическим. Далее под объектами типа TField мы будем понимать либо сам объект типа TField, либо один из производных от него объектов, например, типа TStringField (строковое значение) или TlntegerField (целочисленное значение).
Таблица 5.1. Типы объектов Field
Тип объекта Вид поля
TBLOBField Поле BLOB-значенмя (BLOB, Binary Large Object - большой
двоичный объект)
TMemoField Мемо-поле (поле комментария)
TGraphicField Графическое поле
TBooleanField Поле логического значения
TBinaryField Поле двоичного значения
TBytesField Поле байтового значения фиксированной длины
TVarBytesField Поле байтового значения переменной длины
TDateTimeField Поле значения даты и времени
TDateField Поле значения даты
TTimeField Поле значения времени
TNumericField Поле числового значения
Часть I. Основы работы с базами данных
Таблица 5.1 (окончание)
Тип объекта Вид поля