Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
1 Базы данных.docx
Скачиваний:
21
Добавлен:
23.09.2019
Размер:
808.59 Кб
Скачать

Методы компонента

procedure Close;

Отсоединяет все связанные с ним компоненты TTable TQuery и TStoredProc.

procedure CloseDatasets;

Отсоединяет все дочерние компоненты класса TDataSet, но сам компонент остается открытым.

procedure Commit;

Фиксирует все изменения, проведенные транзакцией. Этот метод можно исполь­зовать только при наличии связи с базой данных.

procedure Open;

Соединяет компонент с сервером или BDE в случае использования СУБД Paradox или dBase.

procedure Rollback;

Отменяет все действия, совершенные транзакцией, то есть запрещает ее фиксацию.

procedure StartTransaction;

Начинает выполнение транзакции, используя уровень изоляции из свойства Translsolation. Этот метод рекомендуется использовать только при наличии связи с базой данных.

  34 Компоненты Delphi для работы с БД: TTable (свойства и методы, используемые для подключения таблиц).

Компонент Tтаblе инкапсулирует таблицу реляционной базы данных, причем независимо от типа базы данных. Для доступа к данным компонент использует функции BDE (см. выше).

Необходимая для работы база данных задается свойством DatabaseName, в котором можно указать зарегистрированный в BDE псевдоним БД или полный путь к файлам БД.

Таблица БД, на основе которой создается набор данных, определяется свойством TableName. При необходимости тип таблицы задается свойством TаblеТуре, хотя обычно это свойство имеет значение ttDefault (см. табл. 16.4), которое включает автоматическое определение типа таблицы по расширению файла.

Примечание

Свойство ТаblеТуре работает только в локальных БД. Обратите внимание, что возможные значения свойства соответствуют основным типам локальных драйверов BDE.

При помощи методов Open и close набор данных открывается и закрывается. О его состоянии можно судить по значению свойства Active. Более подробно о состоянии набора данных расскажет свойство state (см. ниже).

Записи в набор данных можно отбирать при помощи свойств Filter, Filtered, FilterOptions, создающих фильтр, ограничивающий набор данных по значениям данных в одном или нескольких полях.

Методы SetRangeStart, SetRangeEnd, SetRange, ApplyRange, EditRangeStart, EditRangeEnd создают специальный диапазон включаемых в набор данных записей, отбор в диапазон проводится по задаваемым граничным значениям любых полей набора данных.

Поиск нужной записи можно осуществлять методами Lookup или Locate (достаточно просто, но не очень быстро) или, используя существующие в таблице базы данных индексы, методом FindKey (сложнее, но очень быстро).

От предков компонент унаследовал инструменты для работы с закладками. Это свойство Bookmark и методы GetBookmark, FreeBookmark, GotoBookmark.

Работа с полями осуществляется целой группой свойств и методов, среди которых особое место занимает свойство Fields, представляющее собой индексированный список всех полей набора данных. Это свойство удобно использовать в процессе разработки для организации доступа к полям.

Использование индексов обеспечено свойствами indexName, indexFieids, IndexFieldNames, IndexFiles.

Свойства MasterSource, MasterField, IndexName дают возможность установить отношение типа главный/подчиненный с другой таблицей.

Очень полезны в практическом использовании методы и свойства для работы С буфером изменений (свойства CachedUpdates, PendingUpdates, UpdateRecordTypes, МСТОДЫ ApplyUpdates, CancelUpdates, CommitUpdate, RevertRecord). Буфер применяется в клиентских приложениях многоуровневых систем доступа к данным.

От классов TDataSet и TBDEDataSet унаследован обширный набор методов-обработчиков событий, позволяющий решать любые задачи по управлению набором данных.

В табл. 16.8 приведена справочная информация о свойствах и методах компонента ттаble. После этого рассматриваются подробности применения основных механизмов набора данных.

Таблица 16.8. Свойства и методы класса Tтаblеl

Объявление

Тип

Описание

Свойства

property DataSource: TDataSource;

Pu, Ro

Ссылается на компонент TDataSource главного набора данных в отношении  главный/подчиненный

property Defaultlndex: Boolean;

Pb

Управляет сортировкой данных. При значении True записи упорядочиваются по первичному ключу. При значении False упорядочивание не производится

property Exclusive: Boolean;

Pb

Ограничивает доступ к таблице. При значении True с таблицей может работать только одно приложение. Это свойство важно при одновременной работе нескольких приложений с данными в локальной сети

property Exists: Boolean;

Pu, Ro

Значение True говорит о том, что связанная с компонентом таблица базы данных существует

property IndexDef s: TindexDefs;

Pb

Содержит информацию об индексах таблицы

property IndexFieldCount: Integer;

Pu, Ro

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

property IndexFieldNames: string;

Pb

Разделенный запятыми список названий полей, составляющих текущий индекс. Используется для таблиц серверов SQL

property IndexFields: [Index: Integer] : TField;

Pu

Индексированный список полей текущего индекса

property IndexFiles: TStrings;

Pb

Список индексных файлов для таблиц dBASE

property IndexName: string;

Pb

Определяет вторичный индекс для таблицы. Используется для таблиц локальных СУБД

property KeyExclusive: Boolean;

Pu

Управляет границами диапазона, задаваемого методом SetRange. При значении True крайние записи в диапазон не включаются

property KeyFieldCount: Integer;

Pu

Содержит число полей ключа, используемых при поиске. При значении 0 применяется только первое поле, при значении 1 — два первых поля и т. д. По умолчанию устанавливается полное число полей ключа

property MasterFields: string;

Pb

Список имен полей главной таблицы, разделенных запятой, используемых при создании отношения главный/подчиненный

property MasterSource: TDataSource;

Pb

Содержит имя компонента TDataSource, связанного с набором данных, который является главным в отношении главный/подчиненный

property Readonly: Boolean;

Pb

Включает и отключает режим "только для чтения". В некоторых случаях набор данных можно открыть только в этом режиме

property StoreDef s: Boolean;

Pb

При значении True все сведения об индексах и структуре таблицы хранятся вместе с формой или модулем данных. В этом случае при создании набора данных одновременно создаются поля, индексы, ограничения

property TableLevel: Integer;

Pu

Содержит значение уровня таблицы, используемого в драйвере ВОЕ

property TableName: TFileName;

Pb

Определяет имя таблицы

type TTableType = (ttDefault, ttParadox, ttDBase, ttASCII, ttFoxPro) ;

property TableType: TTableType;

Pb

Определяет тип таблицы для стандартного драйвера ВОЕ. Значение ttDefault означает, что тип таблицы определяется по расширению файла

Методы

procedure Addlndex (const Name, Fields: string; Options: TIndexOptions) ;

Pu

Создает новый индекс. Параметр Name определяет имя нового индекса, параметр Fields — список полей индекса через запятую, параметр Options задает тип индекса

procedure ApplyRange;

Pu

Включает в работу границы диапазона, заданные методами SetRangeStart, SetRangeEnd или EditRangeStart, EditRangeEnd

type TBatchMode = (batAppend, batUpdate, batAppendUpdate , batDelete, batCopy) ;

function BatchMove (ASource: TBDEDataSet; AMode : TBatchMode) : Longint;

Pu

Переносит записи из таблицы ASource в набор данных. Тип операции задается параметром AMode. Возвращает число обработанных записей

procedure CancelRange;

procedure CloselndexFile (const  IndexFileName: string) ;

Pu Pu

Удаляет текущий диапазон

Закрывает индексный файл для таблиц dBASE

procedure CreateTable;

Pu

Создает новую таблицу, основываясь на данных о структуре таблицы, содержащихся в свойствах FieldDef s и indexDef s. Если свойство FieldDef s пустое, используется свойство Fields. Структура и данные существующей таблицы перезаписываются

procedure Deletelndex (const  Name: string);

Pu

Удаляет вторичный индекс

procedure DeleteTable;

Pu

Уничтожает таблицу базы данных. Набор данных при этом должен быть закрыт

procedure EditKey;

Pu

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

procedure EditRangeEnd;

Pu

Разрешает редактирование нижней границы диапазона

procedure EditRangeStart;

Pu

Разрешает редактирование верхней границы диапазона

procedure EmptyTable;

Pu

Удаляет все записи из набора данных

function FindKey (const  KeyValues: array of  const) : Boolean;

Pu

Проводит поиск записи, значения полей которой удовлетворяют условиям, заданным параметром KeyValues. Значения разделяются запятыми. Для поиска можно использовать только поля, входящие в текущий индекс. Для локальных стандартных таблиц BDE это поля, определяемые свойством indexName. Для таблиц серверов SQL индекс можно задать свойством indexFieldNames. При успешном поиске функция возвращает значение True

procedure FindNearest (const KeyValues: array of  const);

Pu

Проводит поиск записи, значения полей которой, заданные параметром KeyValues, в минимальной степени отличаются от требуемых в большую сторону. Значения для поиска разделяются запятыми. Для поиска можно использовать толькополя, входящие в текущий индекс. Для  локальных стандартных таблиц ВОЕ  это поля, определяемые свойствомIndexName. Для таблиц серверов SQL индекс можно задать свойством indexFieldNames. При успешном поиске  функция возвращает True

procedure GetlndexNames (List : TStrings) ;

Pu

Возвращает список индексов таблицы

procedure GotoCurrent (Table: TTable) ;

Pu

Синхронизирует курсор набора данных с курсором таблицы, заданной параметром Table

function GotoKey: Boolean;

Pu

Устанавливает курсор на запись, соответствующую значениям полей, заданным  при последнем применении метода

SetKey или EditKey

procedure GotoNearest;

Pu

Устанавливает курсор на запись, точно соответствующую значениям полей,  заданным при последнем применении метода SetKey или EditKey, или следующую ближайшую к ним по значениям

type TLockType = (ItReadLock, ItWriteLock) ; procedure LockTable ( LockType : TLockType) ;

Pu

Закрывает доступ к таблице Paradox или dBASE из других приложений

procedure OpenlndexFile (const IndexFileName: string);

Pu

Открывает индексный файл таблицы dBASE

procedure RenameTable (const NewTableName: string);

Pu

Переименовывает таблицу Paradox или dBASE

procedure SetKey;

Pu

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

procedure SetRange (const StartValues, EndValues:

array of const) ;

Pu

Задает диапазон отбора записей. Параметр StartValues определяет значения полей для верхней границы диапазона.

Параметр EndValues определяет значения полей для нижней границы диапазона. Значения диапазона задаются для полей текущего индекса

procedure SetRangeEnd;

Pu

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

procedure SetRangeStart;

Pu

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

type TLockType = (ItReadLock, ItWriteLock) ; procedure UnlockTable (LockType : TLockType) ;

Pu

Разблокирует таблицу Paradox или dBASE для доступа из других приложений

35 Компоненты Delphi для работы с БД: TTable (свойства и методы, используемые для перемещения по таблице).

Для навигации по таблице используется компонент DBNavi-gator (рис. 11.2.8) со страницы DataControl.

Положите на форму компонент DBNavigator (рис. 11.2.9).

Компонент объединяет в себе ряд кнопок: NbFirst перемещение к первой записи; NbPrior перемещение к предыдущей записи; NbNext перемещение к следующей записи;

NbLast перемещение к последней записи;

Nblnsert вставка новой записи в место, указанное курсором;

NbDelete удаление текущей записи;

NbEdit редактирование текущей записи;

NbPost внесение изменений после редактирования в БД;

NbCancel отмена результатов редактирования или добавления

новой записи; NbRef resh очистка буфера, связанного с набором данных.

Примечание. Для перемещения по записям таблицы можно воспо­льзоваться методами компонента Table — First (на первую запись), Next (на следующую запись), Last (на последнюю запись), Pred (на предыдущую запись). Для определения начала и конца набора данных используются свойства EOF и BOF.

Для связи навигатора с набором данных установите свойство DataSource компонента DBNavigator в DataSourcel.

Для просмотра таблицы biolife необходимы кнопки NbFirst, NbPrior, NbNext, NbLast. Удалите лишние кнопки навигатора, изменив значение свойства VisibleButtons (установите значение False для всех кнопок, кроме необходимых для работы прило­жения).

Эксперимент. Запустите приложение. Убедитесь, что кнопки навигатора позволяют перемещаться по записям таб­лицы. ♦

Чтобы грамотно оформить приложение, работающее с БД, необходимо добавить соединение с набором данных в момент начала работы и разорвать его в момент окончания.

Vf4TaHOBHTe значение свойства Active компонента Table в F

сдайте обработчик события OnCreate формы:

procedure TForml.FormCreate(Sender: TObject);

begin

Tablel.Active := true; end/

В обработчике события OnDestroy формы напишите:

procedure TForml.FormDestroy{Sender: TObject); begin

Tablel.Active := false; end;

Эксперимент. Запустите приложение. Убедитесь, что ниче­го не изменилось в функционировании приложения. ♦

3-й способ. Использование редактора полей.

Отображение данных на форме в отдельных полях можно сделать автоматически.

Создайте новое приложение, сохраните файлы приложения в каталоге BioLife_3, файл проекта под именем Main.pas, файл проекта — BioLife_3.dpr.

Положите на форму компоненты DataSource и Table.

Измените значения свойств так же, как и при выполнении первого и второго способов.

Выполните двойной щелчок левой кнопкой мыши на компо­ненте Table 1, появится редактор полей (рис. 11.2.10). Щелкни­те правой кнопкой мыши и выберите из всплывающего меню Add all Fields (рис. 11.2.11).

В Инспекторе объектов измените свойство DisplayLabel каж­дого поля на значение, соответствующее заголовку, например, Notes — описание. Из всплывающего меню выберите Select all. Перетащите поля на форму, в результате чего автоматически создаются компоненты, отображающие данные.

Положите на форму DBNavigator для перемещения по запи­сям таблицы.

Эксперимент. Запустите приложение. Убедитесь в работо­способности созданного приложения. ♦

36 Компоненты Delphi для работы с БД: TTable (свойства и методы, используемые для сортировки таблиц). 37 Компоненты Delphi для работы с БД: TTable (свойства и методы, используемые для фильтрования данных таблиц). 38 Компоненты Delphi для работы с БД: TTable (свойства и методы, используемые для манипулирования данными в таблицах).

Компонент Tтаblе инкапсулирует таблицу реляционной базы данных, причем независимо от типа базы данных. Для доступа к данным компонент использует функции BDE (см. выше).

Необходимая для работы база данных задается свойством DatabaseName, в котором можно указать зарегистрированный в BDE псевдоним БД или полный путь к файлам БД.

Таблица БД, на основе которой создается набор данных, определяется свойством TableName. При необходимости тип таблицы задается свойством TаblеТуре, хотя обычно это свойство имеет значение ttDefault (см. табл. 16.4), которое включает автоматическое определение типа таблицы по расширению файла.

 Примечание 

Свойство ТаblеТуре работает только в локальных БД. Обратите внимание, что возможные значения свойства соответствуют основным типам локальных драйверов BDE.

При помощи методов Open и close набор данных открывается и закрывается. О его состоянии можно судить по значению свойства Active. Более подробно о состоянии набора данных расскажет свойство state (см. ниже).

Записи в набор данных можно отбирать при помощи свойств Filter, Filtered, FilterOptions, создающих фильтр, ограничивающий набор данных по значениям данных в одном или нескольких полях.

Методы SetRangeStart, SetRangeEnd, SetRange, ApplyRange, EditRangeStart, EditRangeEnd создают специальный диапазон включаемых в набор данных записей, отбор в диапазон проводится по задаваемым граничным значениям любых полей набора данных.

Поиск нужной записи можно осуществлять методами Lookup или Locate (достаточно просто, но не очень быстро) или, используя существующие в таблице базы данных индексы, методом FindKey (сложнее, но очень быстро).

От предков компонент унаследовал инструменты для работы с закладками. Это свойство Bookmark и методы GetBookmark, FreeBookmark, GotoBookmark.

Работа с полями осуществляется целой группой свойств и методов, среди которых особое место занимает свойство Fields, представляющее собой индексированный список всех полей набора данных. Это свойство удобно использовать в процессе разработки для организации доступа к полям.

Использование индексов обеспечено свойствами indexName, indexFieids, IndexFieldNames, IndexFiles.

Свойства MasterSource, MasterField, IndexName дают возможность установить отношение типа главный/подчиненный с другой таблицей.

Очень полезны в практическом использовании методы и свойства для работы С буфером изменений (свойства CachedUpdates, PendingUpdates, UpdateRecordTypes, МСТОДЫ ApplyUpdates, CancelUpdates, CommitUpdate, RevertRecord). Буфер применяется в клиентских приложениях многоуровневых систем доступа к данным.

От классов TDataSet и TBDEDataSet унаследован обширный набор методов-обработчиков событий, позволяющий решать любые задачи по управлению набором данных.

39 Компоненты Delphi для работы с БД: TDataSource (назначение, свойства, методы события).

Невизуальный компонент DataSource представляет собой источник данных, который обеспечивает связь между набором данных и компонентами отображения и редактирования данных. Все наборы данных должны быть связаны с компонентом источника данных, если требуется редактирование данных. Основное свойство источника данных – DataSet. Оно указывает на компонент набора данных (Table, Query и др), с которыми связан источник.  Свойство State дает информацию о текущем состоянии набора данных: находится ли он в состоянии редактирования, вставки данных и так далее. Основные методы Edit – подтверждает возможность редактирования набора данных (не путать этот метод с методом Edit из набора TDataSet). Объявление: procedure Edit; IslinkedTo – проверяет связь источника с указанным набором данных. Обычно напрямую не используется, а применяется при разработке новых компонентов. Объявление: function IslinkedTo(DataSet: TDataSet):Boolean;

События OnDataChange – наступает при перемещении на новое поле или новую запись, если текущая запись редактировалась. OnStateChange – наступает при изменении состояния набора данных, связанного с данным источником. OnUpdateData – наступает, когда намечается обновление текущей записи.

Основные свойства AutoEdit определяет, вызывается ли автоматически метод редактирования данных Edit. DataSet набор данных, с которым связан компонент. Enabled определяет, отображается ли данные в компонентах отображения, связанных с этим источником. State – указывает текущее состояние набора данных, связанного с источником данных.

40 Компоненты Delphi для работы с БД: TField (назначение, свойства, методы события).

TObject->TPersistent->TComponent-”TField Модуль DB

В Палитре компонентов отсутствует

Предназначен для работы с полями таблиц баз данных. Отсутствует в Палитре компонентов, так как является абстрактным компонентом и выступает предком для ряда типизированных компонентов (см. рис. 4.17), которые наследуют все базовые свойства и методы для работы с полями. Объекты-наследники авто­матически создаются для каждого используемого приложением поля при вы­полнении приложения. Эти компоненты создаются динамически в случае опре­деления значения True для свойства Active компонентов TTable и TQuery. Компонент TField играет важную роль для приложений, работающих с базами данных, так как предоставляет возможность прямого доступа к полям таблиц. Каждый компонент содержит не только сведения о типе данных, наборе зна­чений и т. п., но и предоставляет информацию, которая используется визу­альными компонентами отображения данных. В процессе разработки работа с компонентами TField осуществляется при помощи Редактора полей.

Свойства компонента

^Ъ) property Alignment: TAlignment;

Содержит способ выравнивания (см. главы 1, 2) компонента и используется визуальными компонентами TDBGrid и TDBEdit.

property AsBoolean: Boolean-

Содержит значение для TBooleanField. Для TStringField возвращает True, если поле начинается с символов Y,y,T,t (Yes, yes, True, true).

property AsDateTime: TDataTime;

Содержит значение для TDateTimeField или TTimeField. Для TStringField проводит конвертацию.

 

property AsFloat: Double;

Содержит значение для TFloatField, TBCDField, TCurrencyField. Для TStringField проводит конвертацию.

property Aslnteger: Longing-

Содержит значение для TIntegerField, TSmallintField, TWordField. Для TStringField проводит конвертацию.

property AsString: String;

Содержит значение для TStringField. Для TBCDField, TFloatField, TCurrencyField, TDateTimeField, TTimeField, TIntegerField, TSmallintField, TWordField проводит конвертацию. Для TBooleanField возвращает True, если текст начинается с символов Y,y,T,t. Для TMemoField, TGraphicField, TBIobField, TBytesField, TVarBytesField используется только для чтения и возвращает строки "Memo", "Graphic", "Blob", "Bytes", "VarBytes".

(Pb) property Calculated: Boolean;

Содержит True, если поле вычисляемое.

(Ro) property CariModify: Boolean;

Определяет возможность изменения характеристик поля.

property DataSet: TDataSet;

Идентифицирует набор данных поля.

60) property DataSize: Word;

Содержит число байт, необходимое для размещения компонента в памяти.

Q property DataType: TFieldType; TFieldType = (ft Unknown, ftString, ftSmallint, ftlnteger, ftWord, ftBoolean, ftFloat, ftCurrency, ftBCD, ftDate, ftTime, ftDateTime, ftBytes, ftVarBytes, ftBlob, ftMemo, ftGraphic) ;

Определяет тип данных поля.

1рЬ) property DisplayLabel: String;

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

Ro) property DisplayName: PString;

Содержит имя поля. Используется аналогично свойствам DisplayLabel или FieldName других компонентов.

^o) property DisplayText: String;

Содержит символьное представление значения поля, используемое визуальными компонентами в состоянии Edit.

^b) property DisplayWidth: Integer;

Отражает ширину в символах поля, используемого компонентом TDBGrid.

 

property EditMask: String;

Служит для создания шаблона, ограни­чивающего данные, выводимые в поле. Маска состоит из трех секции, разделяемых точкой с запятой. Первая содержит тело маски. Вторая содержит символ, определя­ющий, будут ли буквенные символы маски сохраняться как часть данных (0 — не со­храняются, 1 — сохраняются). Третья содержит символ, определяющий пробел для маски.

(Ro) property EditMaskPtr: PString;

Является указателем на строку свойства EditMask.

(Pb) property FieldName: String;

Содержит имя, которое поле имеет в таблице базы данных.

(Re) property FieldNo: Integer;

Порядковый номер компонента в наборе данных.

(Pk) property Index: Integer;

Номер компонента в массиве свойства Fields набора данных. Изменение значения этого свойства приводит к изменению расположения поля в наборе данных.

(Ro) property IsIndexField: Boolean;

В состоянии True означает, что поле индексировано.

(Ro) property IsNull: Boolean;

Находится в состоянии True, если текущее поле пустое.

(Pb) property Readonly: Boolean;

Определяет режим редактирования текущего поля. Значение True определяет режим "Только для чтения".

(№) property Required: Boolean;

В значении True означает, что поле обязательно должно быть не пустым.

property Size: Word;

Определяет размер поля, размещаемого в наборе данных.

property Text: String;

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

(Pb) property Visible: Boolean;

Определяет режим отображения компонента.

  Обработчики событий

(Pb) property OnChange: TFieldNotifyEvent ; TFieldNotifyEvent = procedure(Sender: TField! of object;

Реагирует на изменение значений полей компонента. Если поле связано с визуальным компонентом отображения данных, то обработчик вызывается только при попытке изменить текущую запись.

 

(Pb) property OnGetText: TFieldGetTextEvent ; TFieldGetTextEvent = procedure(Sender: TField; var Text: String; DisplayText: Boolean) of object;

Обрабатывает обращение к свойствам DisplayText и Text. Обработчик работает с DisplayText при использовании режима просмотра и Text при режиме редак­тирования.

(Pb) property OnSetText: TFieldSetTextEvent; TFieldSetTextEvent = procedure(Sender: TField; const Text: String) of object;

Используется при переопределении зна­чения свойства Text.

(Pb) property OnValidate: TFieldNotifyEvent;

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

  Методы компонента

procedure Assign(Source: TPersistent); override;

Копирует данные из одного компонента в другой, при этом должны быть корректно определены свойства DataType и Size. Параметр Source определяет поле — источник данных. Свойство DataSize источника должно иметь значение не больше 255.

procedure AssignValue(const Value: 'TVarRec) ;

Устанавливает значение поля в соответствие с параметром метода Value, используя для преобразования данных свойства AsBoolean, Aslnteger, AsFloat, AsString, в зависимости от типа данных.

procedure Clear; virtual;

Обнуляет набор значений поля.

procedure FocusControl;

Устанавливает фокус формы на первый связанный с TField компонент отображения данных.

function GetData(Buffer:Pointer): Boolean

Помещает в буфер данные поля без преобразований. Для определения размера буфера можно использовать свойство DataSize. Возвращает False в случае отсутствия данных.

function IsValidChar(InputChar: Char) : Boolean; virtual

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

procedure SetData(Buffer: Pointer);

Записывает в поле данные из буфера без преобразования. Размер буфера определяется свойством DataSize.

Класс TField представляет поле (столбец) базы данных. Через этот класс вы можете установить атрибуты поля. К атрибутам поля относятся тип данных (строковый, целый, с плавающей точкой и т. д.), размер поля, индекс, используется ли это поле в вычислениях и т. п. Вы можете получить или установить значение поля через свойства AsString, AsVariant И AsInteger.

TField является базовым классом для специализированных классов полей. К потомкам TField относятся TStringField, TIntegerField, TSmallIn-tField, TWordField, TFloatField, TCurrencyField, TBCDField, TBooleanFi-eld, TDateTimeField, TDateField, TBIobField, TBytesField, TVarBytesFi-eld, TMemoField и TGraphicField. Эти производные классы расширяют базовый класс, добавляя новые функциональные возможности. Например, классы числовых полей имеют свойство DisplayFormat, которое определяет способ отображения чисел, а также свойство EditFormat, которое определяет вид чисел во время редактирования. Каждый потомок TField соответствует определенному типу поля базы данных. Класс TIntegerField используется для полей целого типа, класс TTimeField — для полей, содержащих дату или время (или дату/время), класс TBIobField — для полей, содержащих большие двоичные объекты, и т. д.

Во время проектирования приложения вы можете обращаться к свойствам TField через редактор полей. После добавления полей достаточно щелкнуть на поле, и в инспекторе объектов будут отображены его свойства. На рис. 16.5 показаны редактор полей и инспектор объектов во время редактирования полей.

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

Доступ к полям

Чтобы получить или установить значение поля, необходимо иметь к нему доступ. Это можно сделать по крайней мере тремя способами:

q   По имени указателя

q   Через свойство Fields класса TDataSet

q   Через метод FieldByName класса TDataSet

Доступ к полю по имени указателя используется, по-видимому, реже всего. Он работает только в том случае, если вы предварительно добавили поля к проекту с помощью редактора полей. Когда вы добавляете поля через редактор полей, Delphi создает для каждого поля указатель, имя которого составляется из имени таблицы и имени поля. Если у вас есть таблица Table! и строковое поле FirstName, указатель на объект TStringField получит имя TablelFirstName. Вы можете использовать этот указатель для доступа к полю:

 

Table1.FirstName.Value := 'Per';

 

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

Свойство Fields предлагает другой способ доступа к полю — по его положению в таблице. Если вы знаете, что поле LastName стоит в таблице первым, можно сделать примерно следующее:

 

Edit1.Text := Table1.Fields[0].Value;

 

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

Из трех способов доступа к полям наиболее распространенным и надежным является использование метода FieldByName. Для доступа к полю через FieldByName вы должны знать только имя этого поля:

 

Table1.FieldByName('LastName').AsString := Edit1.Text;

 

FieldByName возвращает указатель на TField. Для большей ясности я разделю предыдущую строку кода:

 

var

Field : TField;

begin

Field := Table1.FieldByName('LastName');

Field.AsString := Edit1.Text;

end;

 

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

Извлечение и установка значений полей

После получения указателя на конкретное поле вы можете изменять его значение с помощью свойства value или любого из свойств As. Под свойствами As Я имею В виду AsString, Aslnteger, AsDateTime, AsBoolean и т. д. Эти свойства выполняют преобразования между разными типами данных. Естественно, преобразование возможно не во всех случаях. Например, если вы попытаетесь преобразовать строковое поле со значением Smith к целому типу, будет возбуждено исключение.

Установка значения поля очень проста, если вы знаете секрет FieldByName:

 

Table1.Edit;

Table1.FieldByName('LastName').AsString := Edit1.Text;

Table1.Post;

 

Сначала вызывается метод Edit, который переводит таблицу в режим редактирования. Если вы не вызовете Edit, то получите исключение при попытке изменения значения поля. После того, как таблица переведена в режим редактирования, устанавливается новое значение поля. В данном случае я использую AsString вместо свойства Value. Для строкового поля это в любом случае одно и то же. В завершение вызывается метод Post, который отправляет изменения в базу данных (или кэш изменений, если включено свойство СасhedUpdates). Вот и все. Извлечение значения поля выполняется еще проще:

 

int AcctNo := Tablel.FieldByName('ACCT NBR').Value;

 

События TField

К событиям TField, заслуживающим внимания, относятся OnChange и OnValidate. Событие OnChange генерируется при каждом изменении значения поля, после того, как данные были отправлены в базу данных. Вы можете использовать это событие для уведомления об изменениях.

Событие OnValidate, с другой стороны, происходит непосредственно перед отправкой данных. Если у вас на форме имеется компонент отображения, связанный с полем, то он обычно будет сам проверять допустимость вводимых значений. Однако если вы устанавливаете значение поля программным путем, может потребоваться отдельная проверка в обработчике события OnValidate. Это событие немного странное, в том смысле, что оно не передает вам параметра, который мог бы использоваться для отмены изменений. Вместо этого вам нужно возбудить исключение, если результат проверки отрицательный:

 

procedure TForm1.TablelACCT_NBRValidate(Sender: TField);

begin

if (Sender.Aslnteger < 3000) then

raise EDBEditError.Create('Bad Account Number.');

end;

 

Когда вы возбуждаете исключение, отправка изменений в базу данных отменяется.

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

 

41 Создание в Delphi подчиненных таблиц.

Связанные таблицы

В рамках одного проекта таблицы БД можно связывать отношениями "один- ко- многим" и "многие- ко- многим", при этом отношения обязательно устанавливаются между индексированными полями двух таблиц.

При создании отношений в качестве главной таблицы можно использовать любой компонент, инкапсулирующий набор данных. Для задания подчиненной таблицы можно использовать только табличные компоненты (см. гл. 12).

 

42 Создание вычисляемых полей в Delphi.

  1. Редактор DataSet

  2. Редактор DataSet может быть вызван с помощью объектов TTable или TQuery. Чтобы начать работать с ним, положите объект TQuery на форму, установите псевдоним DBDEMOS, введите SQL запрос "select * from customer" и активизируйте его (установив св-во Active в True).

Откройте комбобокс “Object Selector” вверху Инспектора Объектов - в настоящее время там имеется два компонента: TForm и TQuery.

Нажмите правую кнопку мыши на объекте TQuery и в контекстном меню выберите пункт “Fields Editor”. Нажмите кнопку Add - появиться диалог Add Fields, как показано на рис.1

Рис.1: Диалог Add Fields Редактора DataSet.

По-умолчанию, все поля в диалоге выбраны. Нажмите на кнопку OK, чтобы выбрать все поля, и закройте редактор. Снова загляните в “Object Selector”, теперь здесь появилось несколько новых объектов, (см. рис.2)

Рис.2: Object Selector показывает в списке все объекты созданные в Редакторе DataSet. Вы можете также найти этот список в определении класса TForm1.

Эти новые объекты будут использоваться для визуального представления таблицы CUSTOMER пользователю.

Вот полный список объектов, которые только что созданы:

Query1CustNo: TFloatField;

Query1Company: TStringField;

Query1Addr1: TStringField;

Query1Addr2: TStringField;

Query1City: TStringField;

Query1State: TStringField;

Query1Zip: TStringField;

Query1Country: TStringField;

Query1Phone: TStringField;

Query1FAX: TStringField;

Query1TaxRate: TFloatField;

Query1Contact: TStringField;

Query1LastInvoiceDate: TDateTimeField;

Я вырезал и вставил этот список из определения класса TForm1, которое можно найти в окне Редактора исходного текста. Происхождение имен показанных здесь, должно быть достаточно очевидно. Часть "Query1" берется по-умолчанию от имени объекта TQuery, а вторая половина от имени поля в таблице Customer. Если бы мы сейчас переименовали объект Query1 в Customer, то получили бы такие имена:

CustomerCustNo

CustomerCompany

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

Любой объект, созданный в редакторе DataSet является наследником класса TField. Точный тип потомка зависит от типа данных в конкретном поле. Например, поле CustNo имеет тип TFloatField, а поле Query1City имеет тип TStringField. Это два типа полей, которые Вы будете встречать наиболее часто. Другие типы включают тип TDateTimeField, который представлен полем Query1LastInvoiceDate, и TIntegerField, который не встречается в этой таблице.

Чтобы понять, что можно делать с потомками TField, откройте Browser, выключите просмотр полей Private и Protected, и просмотрите свойства и методы Public и Published соответствующих классов.

Наиболее важное свойство называется Value. Вы можете получить доступ к нему так:

procedure TForm1.Button1Click(Sender: TObject);

var

d: Double;

S: string;

begin

d := Query1CustNo.Value;

S := Query1Company.Value;

d:=d+1;

S := 'Zoo';

Query1CustNo.Value := d;

Query1Company.Value := S;

end;

В коде, показанном здесь, сначала присваиваются значения переменным d и S. Следующие две строки изменяют эти значения, а последний две присваивают новые значения объектам. Не имеет большого смысла писать код, подобный этому, в программе, но этот код служит лишь для того, чтобы продемонстрировать синтаксис, используемый с потомками TField.

Свойство Value всегда соответствует типу поля, к которому оно относится. Например у TStringFields - string, TCurrencyFields - double. Однако, если вы отображаете поле типа TCurrencyField с помощью компонент, “чувствительных к данным” (data-aware: TDBEdit, TDBGrid etc.), то оно будет представлена строкой типа: "$5.00".

Это могло бы заставить вас думать, что у Delphi внезапно отключился строгий контроль типов. Ведь TCurrencyField.Value объявлена как Double, и если Вы пробуете присвоить ему строку, Вы получите ошибку “type mismatch” (несоответствие типа). Вышеупомянутый пример демонстрирует на самом деле свойства объектов визуализации данных, а не ослабление проверки типов. (Однако, есть возможность получить значение поля уже преобразованное к другому типу. Для этого у TField и его потомков имеется набор методов типа AsString или AsFloat. Конечно, преобразование происходит только тогда, когда имеет смысл.)

Если нужно получить имена полей в текущем DataSet, то для этого используется свойство FieldName одним из двух способов, показанных ниже:

S := Query1.Fields[0].FieldName;

S := Query1CustNo.FieldName;

Если вы хотите получить имя объекта, связанного с полем, то вы должны использовать свойство Name:

S := Query1.Fields[0].Name;

S := Query1CustNo.Name;

Для таблицы CUSTOMER, первый пример вернет строку "CustNo", а любая из строк второго примера строку "Query1CustNo".

  1. Вычисляемые Поля

Создание вычисляемых полей - одно из наиболее ценных свойств Редактора DataSet. Вы можете использовать эти поля для различных целей, но два случая выделяются особо:

  •  

  • выполнение вычислений по двум или более полям в DataSet, и отображение результата вычислений в третьем поле.

  •  

  • имитация соединения двух таблиц с возможностью редактировать результат соединения.

Программа CALC_SUM.DPR из примеров к данному уроку иллюстрирует первый случай использования вычисляемых полей.

 

Эта программа связывает три таблицы в отношении один ко многим. В частности, ORDERS и ITEMS связаны по полю OrderNo, а ITEMS и PARTS связаны по полю PartNo. (В таблице ORDERS хранятся все заказы; в таблице ITEMS - предметы, указанные в заказах; PARTS - справочник предметов). В программе можно перемещаться по таблице ORDERS и видеть связанный с текущим заказом список включенных в него предметов. Программа CALC_SUM достаточно сложная, но хорошо иллюстрирует мощность вычисляемых полей.

Последовательность создания проекта CALC_SUM:

  •  

  • Создайте новый проект (File|New Project) и удалите из него форму (в Менеджере Проекта View|Project Manager)

  •  

  • Выберите эксперта форм БД из меню Help.

  •  

  • На первом экране, выберите "Create a master/detail form" и "Create a form using TQuery Objects".

  •  

  • Нажмите кнопку Next и выберите таблицу ORDERS.DB из псевдонима БД DBDEMOS.

  •  

  • Нажмите Next и выберите поля OrderNo, CustNo, SaleDate, ShipDate и ItemsTotal из таблицы ORDERS.DB.

  •  

  • Нажмите Next и выберите "Horizontal" из расстановки компонентов dbEdit на форме.

  •  

  • Нажмите Next и выберите таблицу ITEMS.DB.

  •  

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

  •  

  • Нажмите Next и выберите поле OrderNo из Master и Detail ListBoxes, и Нажмите кнопку Add.

  •  

  • Нажмите Next и сгенерируйте форму.

Требуется много слов для того, чтобы описать процесс показанный выше, но, фактически, выполнение команд в Эксперте форм БД легко и интуитивно.

Выделите первый из двух объектов TQuery и установят свойство Active в True. Для Query2 в свойстве SQL напишите текст запроса:

select * from Items I, Parts P

where (I.OrderNo =:OrderNo) and

(I.PartNo=P.PartNo)

Активизируйте объект Query2 (Active установите в True) и вызовите редактор DataSet (Fields Editor) для него. Вызовите диалог Add Fields и добавьте поля OrderNo, PartNo, Qty и ListPrice.

Нажмите Define и ведите слово Total в поле FieldName. Установите Field Type в CurrencyField. Проверьте что Calculated CheckBox отмечен. Нажмите Ok и закройте редактор DataSet.

Простой процесс описанный в предыдущем абзаце, показывает как создать вычисляемое поле. Если посмотреть в DBGrid, то можно видеть, что там теперь есть еще одно пустое поле. Для того, чтобы поместить значение в это поле, откройте в Инспекторе Объектов страницу событий для объекта Query2 и сделайте двойной щелчок на OnCalcFields. Заполните созданный метод так:

procedure TForm2.Query2CalcFields(DataSet: TDataSet);

begin

Query2NewTotalInvoice.Value := 23.0;

end;

После запуска программы поле Total будет содержит строку $23.00.

Это показывает, насколько просто создать вычисляемое поле, которое показывает правильно сформатированные данные. На самом деле это поле должно показывать нечто другое - произведение полей Qty (количество) и ListPrice (цена). Для этого вышеприведенный код для события OnCalcFields нужно изменить следующим образом:

procedure TForm1.Query2CalcFields(DataSet: TDataset);

begin

Query2Total.Value:=Query2Qty.Value*Query2ListPrice.Value;

end;

 

Если теперь запустить программу, то поле Total будет содержать требуемое значение.

В обработчике события OnCalcFields можно выполнять и более сложные вычисления (это будет показано позже), однако следует помнить, что это вызывает соответствующее замедление скорости работы программы.

Теперь давайте добавим вычисляемое поле для первой таблицы (Query1, ORDERS), которое будет отображать сумму значений из поля Total второй таблицы (Query2) для данного заказа. Вызовите редактор DataSet для объекта Query1 и добавьте вычисляемое поле NewItemsTotal типа CurrencyField. В обработчике события OnCalcFields для Query1 нужно подсчитать сумму и присвоить ее полю NewItemsTotal:

procedure TForm1.Query1CalcFields(DataSet: TDataset);

var

R : Double;

begin

R:=0;

with Query2 do begin

DisableControls;

Close;

Open;

repeat

R:=R+Query2Total.Value;

Next;

until EOF;

First;

EnableControls;

end;

Query1NewItemsTotal.Value:=R;

end;

В данном примере сумма подсчитывается с помощью простого перебора записей, это не самый оптимальный вариант - можно, например, для подсчета суммы использовать дополнительный объект типа TQuery. Метод DisableControls вызывается для того, чтобы отменить перерисовку DBGrid при сканировании таблицы. Запрос Query2 переоткрывается для уверенности в том, что его текущий набор записей соответствует текущему заказу.

Поместите на форму еще один элемент DBEdit и привяжите его к Query1, полю NewItemsTotal. Запустите программу, ее примерный вид показан на рис.3

Рис.3: Программа CALC_SUM

Как видно из программы, наличие поля ItemsTotal в таблице ORDERS для данного примера необязательно и его можно было бы удалить (однако, оно необходимо в других случаях).

 

      1.  

      2. Управление TDBGrid во время выполнения

Объект DBGrid может быть полностью реконфигурирован во время выполнения программы. Вы можете прятать и показывать колонки, изменять порядок показа колонок и их ширину.

Вы можете использовать свойство Options объекта DBGrid, чтобы изменить ее представление. Свойство Options может принимать следующие возможные значения:

DgEditing

Установлен по-умолчанию в true, позволяет пользователю редактировать grid. Вы можете также установить свойство ReadOnly grid в True или False.

DgTitles

Будут ли видны названия колонок.

DgIndicator

Будут ли видны небольшие иконки слева.

DgColumnResize

Может ли пользователь менять размер колонки.

dgColLines

Показывать ли линии между колонками.

dgRowLines

Показывать ли линии между строками.

dgTabs

Может ли пользователь использовать tab и shift-tab для переключения между колонками.

Как объявлено в этой структуре:

TDBGridOption = (dgEditing, gdAlwaysShowEditor, dgTitles,

dgIndicator, dgColumnResize, dgColLines,

dgRowLines, dgTabs);

Например Вы можете установить опции в Runtime написав такой код:

DBGrid1.Options := [dgTitles, dgIndicator];

Если Вы хотите включать и выключать опции, это можно сделать с помощью логических операций. Например, следующий код будет добавлять dgTitles к текущему набору параметров:

DBGrid1.Options := DBGrid1.Options + [dgTitles];

Пусть есть переменная ShowTitles типа Boolean, тогда следующий код позволяют включать и выключать параметр одной кнопкой:

procedure TForm1.Button3Click(Sender: TObject);

begin

if ShowTitles then

DBGrid1.Options := DBGrid1.Options + [dgTitles]

else

DBGrid1.Options := DBGrid1.Options - [dgTitles];

ShowTitles := not ShowTitles;

end;

 

Если Вы хотите скрыть поле в run-time, то можете установить свойство visible в false:

Query1.FieldByName(‘CustNo’).Visible := False;

Query1CustNo.Visible := False;

Обе строки кода выполняют идентичную задачу. Чтобы показать поле снова, установите видимый в true:

Query1.FieldByName(‘CustNo’).Visible := True;

Query1CustNo.Visible := True;

Если Вы хотите изменить положение колонки в Runtime, можете просто изменить индекс, (первое поле в записи имеет индекс нуль):

Query1.FieldByName(‘CustNo’).Index := 1;

Query1CustNo.Index := 2;

По-умолчанию, поле CustNo в таблице Customer является первым. Код в первой строке перемещает это поле во вторую позицию, а следующая строка перемещает его в третью позицию. Помните, что нумерация полей начинается с нуля, так присвоение свойству Index 1 делает поле вторым в записи. Первое поле имеет Index 0.

Когда Вы изменяете индекс поля, индексы других полей в записи изменяются автоматически.

Если Вы хотите изменить ширину колонки в Runtime, только измените свойство DisplayWidth соответствующего TField.

Query1.FieldByName(‘CustNo’).DisplayWidth := 12;

Query1CustNo.DisplayWidth := 12;

Величина 12 относится к числу символов, которые могут быть показаны в видимом элементе.

Программа DBGR_RT показывает как работать с DBGrid в Runtime. Программа достаточно проста, кроме двух небольших частей, которые описаны ниже. Первая часть показывает, как создать check box в Runtime, а вторая показывает, как изменить порядок пунктов в listbox в Runtime.

При создании формы (событие OnCreate) ListBox заполняется именами полей, далее создается массив объектов CheckBox, соответствующий полям в таблице. Сперва все CheckBox’ы выбраны и все поля в таблице видимы. Программа узнает через TTable1 имена полей и присваивает их свойству Caption соответствующего CheckBox. Кроме того, обработчику события OnClick всех CheckBox’ов присваивается процедура ChBClick, которая и включает/выключает поля в DBGrid.

procedure TForm1.FormCreate(Sender: TObject);

var

i : Word;

R : Array[0..49] of TCheckBox;

begin

{Fill ListBox}

ListBox1.Clear;

for i:=0 to Table1.FieldCount-1 do

ListBox1.Items.Add(Table1.Fields[i].FieldName);

{Make CheckBoxes}

for i:=0 to Table1.FieldCount-1 do begin

R[I] := TCheckBox.Create(Self);

R[I].Parent := ScrollBox1;

R[I].Caption := Table1.Fields[i].FieldName;

R[I].Left := 10;

R[I].Top := I * CheckBox1.Height + 5;

R[I].Width := 200;

R[I].Checked := True;

R[I].OnClick := ChBClick;

end;

end;

Большая часть кода в этом примере выполняет относительно простые задачи, типа назначения имен и положений check boxes. Вот две ключевых строки:

R[I] := TCheckBox.Create(Self);

R[I].Parent := ScrollBox1;

Первая строки создает CheckBox с заданным Owner (Владельцем). Вторая строки назначает Parent (Родителя) для CheckBox. Чтобы понять различия между Родителем и Владельцем, посмотрите соответствующие свойства в online-help.

Программа содержит ListBox, который показывает текущий порядок полей в DataSet. Для изменения порядка полей в DataSet (а, следовательно, в DBGrid) используются две кнопки. При нажатии на одну из кнопок, выбранное в ListBox’е поле перемещается на одну позицию вверх или вниз. Синхронно с этим меняется и порядок полей в DBGrid. Код, показанный ниже, изменяет Index поля для Table1, изменяя, таким образом, позицию поля в DBGrid. Эти изменения касаются только визуального представления DataSet. Физически данные на диске не изменяются.

procedure TForm1.downButtonClick(Sender: TObject);

var

i : Integer;

begin

with ListBox1 do

if (ItemIndex<Items.Count-1)and(ItemIndex<>-1) then begin

i := ItemIndex;

{move ListBox item}

Items.Move(i, i+1);

ItemIndex := i+1;

{move Field}

Table1.Fields[i].Index:=i+1;

end;

end;

Последняя строка в примере как раз та, которая фактически изменяет индекс колонки, которую пользователь хочет переместить. Две строки кода непосредственно перед ней перемещают текущую строку в ListBox на новую позицию.

Внешний вид программы DBGR_RT показан на рис.4

Рис.4: Программа DBGR_RT

Вычисляемые поля

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

procedure TForml.TablelCalcFields(DataSet: TDataSet)

; begin

with Tablel do

TabielCalcFieldl.Value := Fields[0].Value + Fields[1].Value;

 with Queryl do 

begin

Params[0].AsInteger := Tablel.Fields[0].Aslnteger;

 Open;

TabielCalcFieldl.Value := Fields[0].AsString; 

Close;

 end;

 end;

Метод OnCalcFields выполняется при открытии набора данных, при переходе в режим редактирования, при передаче фокуса между компонентами отображения данных или колонок сетки, при удалении записи. Но для этого нужно, чтобы свойство AutoCaicFields набора данных было равно значению True.

Примечание

Необходимо учитывать, что сложные вычисляемые поля могут существенно замедлить работу набора данных (особенно при использовании при этом запросов SQL). Кроме того, в процессе редактирования набора данных (при изменении значения поля, сохранении изменений и переходе на следующую запись) вычисляемые поля рассчитываются несколько раз подряд. Для уменьшения числа автоматических обращений к методу OnCalcFields нужно использовать свойство AutoCaicFieids := False.

Для создания вычисляемого поля достаточно в диалоге создания нового поля Редактора полей в качестве типа поля задать "вычисляемое", в остальном процесс совпадает с созданием поля данных.

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

Вычисляемые поля нельзя использовать при фильтрации набора данных при помощи метода-обработчика onFilterRecord, т. к. он вызывается до метода-обработчика OnCalcFields, а вычисляемые поля не сохраняются.

43 Создание полей типа "LookUp" d Delphi.

Для чего нужны lookup-поля, поясним на примере. Допустим, имеется две таблицы БД: таблица "Заказы" с полями N, Date, ClientID, Amount и таблица "Клиенты" с полями ID, Name, Address. В таблице "Заказы" содержится информация о заказах (номер, дата, идентификатор клиента, сделавшего заказ, и сумма заказа). В таблице "Клиенты" содержится информация о клиентах (идентификатор клиента, полное наименование, адрес).

Чтобы сформировать простейший отчет по таблице "Заказы" вида Номер заказа - Дата - Наименование клиента - Сумма, потребуется связать обе таблицы по полям ClientID -> ID. Эта задача решается путем создания lookup-поля, которое добавляется к таблице "Заказы" и представляет собой ссылку на поле Name таблицы "Клиенты".

Диалог создания lookup-поля доступен из редактора полей.

Для создания lookup-поля надо указать его имя и тип, а также размер (в случае, если выбран строковый тип). Далее необходимо заполнить следующие поля:

  • Ключевое поле - поле в исходном наборе данных, которое следует рассматривать как ссылку на поле из lookup-набора. В нашем примере это будет поле ClientID.

  • Источник данных - lookup-набор данных.

  • Lookup ключ - поле в lookup-наборе, являющееся ключевым. В нашем примере это поле ID.

  • Результирующее поле - поле lookup-набора, которое надо подставить в исходный набор данных. В нашем примере это поле Name.

После этого в таблице "Заказы" создается фиктивное поле с заданным именем, которое содержит расшифровку поля ClientID. К нему можно обращаться как к обычному полю, но только для чтения.

Кроме обычных полей и вычисляемых полей, в Delphi имеется возможность создания полей выбора данных (Lookup-полей).

    Поле выбора данных одного НД содержит значения из другого набора данных, связанных по ключу с НД, к которому принадлежит это поле. Первый НД - родительский, а второй - дочерний. Lookup-поля и специализированные компоненты TDBLookupListBox, TDBLookupComboBox используют схожий механизм, основанный на реляционной связи двух НД, однако эти компоненты выбора не создают новых полей.

    В нашей программе FIRMA в таблице наименования товара содержится поле NSklad (номер склада). Давайте дополним наше приложение таким образом, чтобы при выборе записи из таблицы "Наличие товара" как дополнительная информация выводился бы номер склада, на котором этот товар находится.

    Создайте новое поле в НД Table2 с именем NSklad типа Integer. Установите переключатель в положение Lookup. После выбора переключателя становятся доступными элементы группы Lookup definition, с помощью которых устанавливаются параметры связи наборов данных (рисунок 1 и таблица 1).

Рис.1. Диалоговое окно New Field

Таблица 1. Параметры связи наборов данных

Название

Назначение

DataSet

Определяет имя родительского НД

Key Fields

Определяет список ключевых полей родительского НД. По этим полям построен индекс для связи родительского НД с дочерним. Если в индексе несколько полей, они разделяются точками с запятыми

Lookup Fields

Определяет список ключевых полей дочернего НД. По этим полям построен индекс для связи дочернего НД с родительским

Result Fields

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

    Установите у этих элементов следующие значения:

Таблица 2. Значения свойств

Элемент

Значение

DataSet

Table1

Key Fields

Naim

Lookup Fields

Naim

Result Fields

NSklad

    Таким образом, родительский НД Table1 связан с дочерним НД Table2 по полю Naim, и создаваемому нами полю присваивается значение из поля NSklad НД Table1.

    Выберите в редакторе полей НД Table2 созданный вновь объект TField NSklad и присвойте его свойству Visible значение False (таким образом, поле NSklad не будет отображаться в DBGrid2). Поместите на форму компонент TLabel с вкладки Standard, TDBText с вкладки Data Controls, присвоив их свойствам следующие значения:

DBText1

DataSource

DataSource2

DataField

NSklad

Label1

Caption

Номер склада

    Запустив программу, вы убедитесь, что при перемещении по таблице "Наличие товара", в DBLabel1 показывается номер склада, на котором находится этот товар. Как видно, значение берется из Table1 (рисунок 2).

Рис.2. Приложение с Lookup-полем

Созданное приложение можно взять здесь.

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

    Изменим нашу БД таким образом: пусть каждый товар будет находиться на отдельном складе с номерами 1, 2, 3 и т.д. Свойство Visible компонента TField NSklad установите в True. Теперь в DBGrid2 отображается номер склада, на котором находится товар, а при редактировании этого поля появляется комбинированный список и после выбора значения автоматически обновляется поле Naim. Заметим, что список выбора раскрывается, несмотря на то, что свойство ReadOnly (только чтение) компонента DBGrid2 установлено в True.

Рис.3. Результат работы приложения

44 Язык запросов SQL. 45 Формат оператора Select в языке SQL.

Язык SQL стал фактически стандартным языком доступа к базам данных. Все СУБД, претендующие на название "реляционные", реализуют тот или иной диалект SQL. Многие нереляционные системы также имеют в настоящее время средства доступа к реляционным данным. Целью стандартизации является переносимость приложений между различными СУБД.

Нужно заметить, что в настоящее время, ни одна система не реализует стандарт SQL в полном объеме. Кроме того, во всех диалектах языка имеются возможности, не являющиеся стандартными. Таким образом, можно сказать, что каждый диалект - это надмножество некоторого подмножества стандарта SQL. Это затрудняет переносимость приложений, разработанных для одних СУБД в другие СУБД.

Язык SQL оперирует терминами, несколько отличающимися от терминов реляционной теории, например, вместо "отношений" используются "таблицы", вместо "кортежей" - "строки", вместо "атрибутов" - "колонки" или "столбцы".

Стандарт языка SQL, хотя и основан на реляционной теории, но во многих местах отходит он нее. Например, отношение в реляционной модели данных не допускает наличия одинаковых кортежей, а таблицы в терминологии SQL могут иметь одинаковые строки. Имеются и другие отличия.

Язык SQL является реляционно полным. Это означает, что любой оператор реляционной алгебры может быть выражен подходящим оператором SQL.