Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебное пособие СУБД 2011.pdf
Скачиваний:
68
Добавлен:
10.06.2015
Размер:
2.75 Mб
Скачать

78

В листинге приведён пример вызова функции Locate() для поиска некого гражданина по фамилии “Петров” рождённого в 1980 году. Метод осуществит поиск сразу в двух полях таблицы не обращая внимания на регистр символов.

with ADOTable1 do

Locate('Name; Born', VarArrayOf(['Петров', '1980']), [loCaseInsensitive]);

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

В классе TDataSet заложен виртуальный метод поиска Lookup(), который перекрыт у его потомков:

function Lookup(const KeyFields: string; const KeyValues: Variant; const ResultFields: string): Variant;

По аналогии с методом Locate() функция Lookup() обладает тремя параметрами: строковый параметр KeyFields определяет столбец или список столбцов (разделяемый точкой с запятой) в которых будет осуществлён поиск, параметр KeyValues содержит шаблон или массив шаблонов, в соответствии с которыми производится поиск. Последний параметр – ResultFields перечисляет имена столбцов, которым присваивается результат функции. Функция не позиционирует курсор на найденной записи, а только возвращает найденные значения. Способ применения метода предложен ниже.

Var Results: Variant;

Begin

With ADOTable1 do

Results := Lookup('CompanyName', 'Иванов и К', 'City; Street; Home');

End;

Поиск осуществляется в колонке “CompanyName” набора данных Table1. Если метод обнаружит значение “Иванов и К”, то в переменную Results помещается адрес компании

– содержимое колонок City, Street и Home.

Взаимодействие с элементами управления данными

Как правило, потомки класса TDataSet (элементы управления TADOTable, TADOQuery, и т.д.) ещё в период разработки приложения связываются с элементами управления, отвечающими за отображение и редактирование данных. Посредником в этих операциях выступает компонент TDataSource (источник данных). Для подключения к набору данных источника данных (компонент класса TDataSource) предназначено одноимённое свойство:

property DataSource: TDataSource;

Задание

Улучшите начатый на лабораторной работе 11 проект БД. Используя компонентытаблицы TADOTable, TDataSource и TDBGrid научите проект БД следующим операциям:

1.Перемещаться по строкам таблицы.

2.Создавать закладки и возвращаться к ним.

3.Добавлять, редактировать и удалять строки из таблицы.

4.Фильтровать строки в таблице (например, строить фильтр по дате).

5.Производить поиск строки в таблице, по значению поля.

Внимание! При выполнении задания нельзя использовать компонент TDBNavigator.

© 2011 г. Д.Л. Осипов

79

XIII. Работа с полями набора данных

Вид занятия – самостоятельная работа. Время занятия – 2 часа.

При формировании библиотеки VCL программисты Embarcadero реализовали целый арсенал компонентов предназначенных для организации доступа к данным. К моменту появления Delphi XE перечень этих элементов управления настолько расширился, что даже простое их перечисление способно внушить благоговение любому программисту. Вместе с этим, не смотря на впечатляющий перечень классов, компоненты достаточно просты в изучении, так как построены по схожим принципам. Как уже отмечалось на предыдущем занятии, все компоненты доступа к данным обладают общим предком – классом TDataSet. Материал, сегодняшнего занятия, также является общим для всех компонентов доступа к данным. Он посвящён особому классу TField – полю набора данных.

Поле таблицы – класс TField

Класс TField (от англ. field поле) инкапсулирует физический объект – поле набора данных. Сам по себе класс TField является абстрактным и посему в первозданном виде не используется. А вот богатое потомство класса интегрируется во все построенные на основе класса TDataSet компоненты. При открытии набора данных (например, при помощи компонентов TADOTable или TADOQuery) автоматически рождается ровно столько объектов TField, сколько столбцов физически доступно в этом наборе. Объекты-поля созданные таким образом (без явного вмешательства программиста) называют динамическими. Основная особенность подобных объектов в том, что они уничтожаются сразу после отключения от набора данных.

Однако, в некоторых ситуациях, и на долю программиста выпадает обязанность немного поработать. Особенно если идёт речь о реализации:

-полей синхронного просмотра (lookup);

-вычисляемых полей (calculated);

-агрегатных полей (aggregate).

Для этого в среде Delphi реализован специальный редактор “Fields Editor”, вызываемый по двойному щелчку кнопкой мышки по компоненту-набору данных. Все объ- екты-поля созданные руками программиста именуют статическими. В отличие от динамического поля, жизненный цикл его статического собрата начинается практически в момент старта приложения, продолжается до завершения его работы и ни коим образом не зависит от того, открыт или закрыт набор данных.

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

Теперь немного об основных обязанностях класса TField, потомки класса умеют:

1.Читать данные из текущей записи конкретного столбца таблицы.

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

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

4.Обрабатывать вычисляемые поля.

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

©Осипов Д.Л., 2011

80

Классификация полей по функциональному назначению

Для того, чтобы выяснить назначение поля сразу стоит обратиться к его свойству: property FieldKind: TFieldKind;

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

 

Значения TFieldKind. Таблица 13.1

Значение

Описание

fkData

Объект представляет собой поле данных.

fkCalculated

Это вычисляемое поле, содержимое которого определяется в обра-

 

ботчике события OnCalcFields() содержащего его компонента.

fkLookup

Поле синхронного просмотра.

fkInternalCalc

Внутренне вычисляемое поле.

fkAggregate

Агрегатное поле.

Самый распространённый тип поля – fkData. На физическом уровне это чаще всего поле обычной таблицы, доступ к которому мы получили с помощью компонентов

TTable, TQuery или их коллег.

Классификация полей по типу обслуживаемых данных

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

property DataType: TFieldType;

Например, поле предназначенное для работы с 32-х разрядными целыми числами имеет тип данных ftInteger, вещественное поле – ftFloat, строковое – ftString.

Обращение к отдельному объекту-полю

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

property DataSet: TDataSet;

Свойство вернёт ссылку на родительский компонент.

Каждое поле владеет информацией об имени связанного с ним столбца таблицы: property FieldName : string;

В наборе данных (потомке TDataSet) поля хранятся в свойстве Fields. В этом списке, каждое поле описывается уникальным индексом.

property Index: Integer;

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

property FieldNo: Integer;//только для чтения;

Оно отображает физическую последовательность столбцов в наборе.

Доступ к данным поля

Для того, чтобы проверить содержит ли поле значение обращайтесь к свойству: property IsNull: Boolean;

Если значение поля неопределённое, то свойство вернёт true. Если значение поля определено, то Вы имеете полное право выяснить, что там находится. Для чтения и записи данных в поле предназначается свойство:

property Value: Variant;

If ADOTable1.Fields[0].IsNull=False Then

© 2011 г. Д.Л. Осипов

81

Result:= Table1.Fields[0].Value;

Для полной очистки содержимого поля стоит применять процедуру: procedure Clear;

После вызова метода значение поля будет соответствовать NULL.

Поле можно перевести в режим “только для чтения” применив свойство: property ReadOnly: Boolean;

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

property CanModify: Boolean;//только для чтения

Свойство информирует нас о том, разрешено (true) или запрещено (false) модифицировать данные поля.

При вводе новой или редактировании существующей записи важную роль играет свойство:

property Required: Boolean;

Значение true свидетельствует о том, что это так называемое “обязательное” поле. Другими словами оно должно быть заполнено, иначе (если при сохранении записи поле окажется пустым) – мы получим сообщение об ошибке.

Приведение типов

Один и тот же объект-поле способен представлять содержащееся в нём значение в виде некоторых стандартных типов данных. Для этого в классе TField инкапсулировано несколько свойств (см. таблицу 13.2).

 

Таблица 13.2

Свойство

Описание

property AsBCD: TBcd;

Содержит значение поля в формате дво-

 

ично-кодированного десятичного числа.

 

Значения такого типа иногда применяют-

 

ся вместо денежных (currency) типов дан-

 

ных.

property AsBoolean: Boolean;

Содержит значение в логическом форма-

 

те.

property AsCurrency: Currency;

Денежный формат.

property AsDateTime: TDateTime;

Формат дата/время.

property AsFloat: Double;

Вещественное число.

property AsInteger: Integer;

Целое число.

property AsSQLTimeStamp: TSQLTimeStamp;

Значение поля представлено в формате

 

TSQLTimeStamp. Это один из способов

 

хранения даты/времени, в виде записи,

 

применяемый в серверах SQL.

property AsString: String;

Строка символов.

property AsVariant: Variant;

Универсальный формат.

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

Lable1.Caption:=Query1.FieldByName('CityName ').AsString;

Или обратный пример, показывающий каким образом можно забрать значение из компо- нента-календаря:

Table1.Fields[1].AsDateTime:= DateTimePicker1.Date;

© 2011 г. Д.Л. Осипов

82

Размер поля

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

property DataSize: Integer;

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

Ещё одно свойство:

property Size: Integer;

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

Значение по умолчанию

Значение по умолчанию, вносимое в поле при вводе новой записи определяется в свойстве.

property DefaultExpression: String;

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

FieldCurrentTime.DefaultExpression:='12:00:00';

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

Ограничения на ввод данных

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

Ограничения на диапазон допустимых значений определяются в свойстве: property CustomConstraint: String;

Это ни что иное, как обычная строка, в которой описывается выражение на языке SQL. Допустим, что физическое имя поля “field1”, тогда примерно так будет выглядеть выражение, определяющее допустимые пределы вводимого значения:

CustomConstraint:=‘field1>=10 and field1<100’;

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

property ConstraintErrorMessage: String;

Если ограничения определены на уровне СУБД, то Вы можете лишь ознакомится с ними, посмотрев содержимое свойства:

property ImportedConstraint: String;

Попытка внести изменения в импортируемые ограничения обречена на провал.

Ещё одно справочное свойство предназначено для проверки – есть ли какие-нибудь ограничения на вводимые значения:

property HasConstraints: Boolean; //только для чтения

Маска ввода

Маска ввода, предназначена для определения формата вводимых пользователем значений и для повышения наглядности представляемых данных.

property EditMask: TEditMask;

© 2011 г. Д.Л. Осипов