с реляционными базами данных 8 глава




TBCDField Поле BCD-значения

TFloatField Поле вещественного значения

TCurrencyField Поле значения денежной суммы

TIntegerField Поле целочисленного значения (32 разряда)

TAutoincField Поле автоинкрементного значения (32 разряда)

TSmallintField Поле целочисленного короткого значения (16 разрядов)

TLargeintField Поле целочисленного длинного значения (64 разряда)

TWordField Поле целочисленного значения без знака (16 разрядов)

TStringField Поле строкового значения

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

Задать состав полей набора данных можно двумя способами:

□ по умолчанию (динамические поля);

□ с помощью редактора полей (статические поля).

По умолчанию при каждом открытии набора данных как на этапе проектирова­ния, так и на этапе выполнения приложения для каждого поля набора автомати­чески создается свой объект типа TField. В этом случае мы имеем дело с динами­ческими полями, достоинством которых является корректность отображения структуры набора данных даже при ее изменении. Напомним, что для компонента Table состав полей определяется структурой таблицы, с которой этот компонент связан, а для компонента Query состав полей зависит от SQL-запроса.

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

На этапе разработки приложения с помощью Редактора полей можно создавать для набора данных статические (устойчивые) поля, основные достоинства кото­рых состоят в реализации следующих возможностей:

□ определение вычисляемых полей, значения которых рассчитываются с по­
мощью выражений, использующих значения других полей;


Глава 5. Компоненты доступа к данным


107


П ограничение состава полей набора данных;

□ изменение порядка полей набора данных;

□ скрытие или показ отдельных полей при выполнении приложения;

□ задание формата отображения или редактирования данных поля на этапе разработки приложения.

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

Редактор полей

По умолчанию для каждого физического поля при открытии набора данных автоматически создается объект типа TField, а все поля в наборе данных яв­ляются динамическими и доступными. Для создания статических (устойчивых) полей используется специальный Редактор полей. В случае, если хотя бы одно поле набора данных является статическим, динамические поля больше созда­ваться не будут. Таким образом, в наборе данных будут доступны только стати­ческие поля, а все остальные считаются отсутствующими. Определить или от­менить состав статических полей можно с помощью Редактора полей на этапе разработки приложения.

(_____ ЗамечаниеJ

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

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

Для запуска Редактора полей (рис. 5.6) следует сделать двойной щелчок на ком­поненте Table или Query или вызвать для этих компонентов контекстное меню правой кнопкой мыши и выбрать пункт Fields Editor. В заголовке Редактора по­лей выводится составное имя набора данных, например, Forml.Tablel. Для перемещения по полям используются четыре кнопки навигации Редактора или мышь. Большую часть Редактора занимает список статических полей, при этом поля перечисляются в порядке их создания, который может отличаться от по­рядка полей в таблице БД.

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

□ создать новое статическое поле;

□ удалить статическое поле;

□ изменить порядок следования статических полей.


108


Часть I. Основы работы с базами данных


Кроме того, для любого выбранного в редакторе статического поля с помощью Инспектора объектов можно задать или изменить свойства этого поля (объекта типа TField) и определить обработчики его событий. Подобные действия раз­решается производить благодаря тому, что соответствующие статическим полям объекты типа TField доступны на этапе разработки приложения.



 


 


Рис. 5.6. Редактор полей


Рис. 5.7. Добавление новых статических полей


Для создания статического поля следует вызвать контекстное меню Редактора полей и выбрать пункт Add Fields (Добавить поля), в результате чего появляется диалоговое окно добавления новых полей (рис. 5.7). В списке Available fields (Доступные поля) окна содержатся все те поля набора данных, которые еще не являются статическими. После выбора одного или нескольких полей и нажатия кнопки ОК эти поля добавляются в состав статических полей набора данных. Добавленное статическое поле является полем данных и связано с конкретным физическим полем таблицы БД.

Для добавления в список всех физических полей таблицы (для набора данных Table) или результата выполнения SQL-запроса (для набора данных Query) нужно выбрать в контекстном меню Редактора полей пункт Add all Fields (Доба­вить все поля).

При каждом открытии (в том числе при разработке приложения) набора данных проверяется возможность создания экземпляров класса TField для статических полей. Если поле вследствие какой-нибудь ошибки является недопустимым, и создание объекта типа TField невозможно, то генерируется исключение, а на­бор данных закрывается.

Для удаления статического поля нужно выбрать пункт Delete контекстного ме­ню или выделить поле в списке и нажать клавишу < Delete >. После удаления статического поля оно становится недоступным для операций в программе, од­нако в случае необходимости его снова можно сделать статическим, добавив в


Глава 5. Компоненты доступа к данным


109


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

(_____ ЗамечаниеJ

Если удалены все статические поля, то все поля набора данных становятся дина­мическими и доступными при выполнении приложения.

Порядок следования полей определяется их местом в списке Редактора полей. По умолчанию порядок полей соответствует порядку физических полей в таб­лицах БД. Его можно изменить, перемещая поля в списке с помощью мыши или комбинаций клавиш <Ctrl>+<Page Up> и <Ctrl>+<Page Down>.

(_____ ЗамечаниеJ

Если для набора данных определены статические поля, то изменение значения свойства TableName этого набора данных может привести к ошибке, что обычно и происходит. Это связано с тем, что в новой таблице, связываемой с набором дан­ных, могут отсутствовать физические поля, для которых были созданы статические поля. d таких случаях программист должен предусматривать соответствующие опе­рации, например, формирование нового состава статических полей.

Есть три типа статических полей:

□ поле данных, связанное с соответствующим физическим полем таблицы;

□ вычисляемое поле, значение которого рассчитывается в обработчике события OnCalcFields во время выполнения приложения;

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

Для создания нового статического поля любого типа нужно выбрать в контекст­ном меню Редактора полей пункт New Field, в результате чего открывается од­ноименное диалоговое окно (рис. 5.8).

Для задания общих свойств (параметров) нового поля используется группа эле­ментов управления Field properties (Свойства поля). В поле ввода Name задается значение свойства FieldName (имя поля), а в поле ввода Component — значение свойства Name (имя компонента поля — объекта типа TField). При программи­ровании обычно используется имя поля. Delphi автоматически формирует зна­чение в поле ввода Component, и попытка изменить его не приводит к желаемо­му результату. В списке Туре и поле ввода Size указываются тип данных и размер поля. Тип данных обязательно задается для всех полей, а необходимость задания размера зависит от типа данных. Например, для поля с типом данных integer задание размера не имеет смысла, а для типа string размер поля огра­ничивает максимальную длину строки.

Тип нового поля выбирается в группе переключателей Field type из следующих вариантов:

Data (поле данных);

Calculated (вычисляемое поле);

Lookup (поле выбора).


110


Часть I. Основы работы с базами данных


 



 


Рис. 5.8. Окно создания статического поля

В группе Lookup definition (Определение выбора) для поля выбора устанавлива­ются такие параметры, как набор данных и поля связи, а также поля для фор­мирования списка выбора и результата.

После создания нового статического поля его свойства становятся доступными через Инспектор объектов и могут быть изменены. При этом каждому парамет­ру, задаваемому с помощью поля ввода или переключателя окна New Field (см. рис. 5.8), соответствует определенное свойство объекта типа TField (табл. 5.2). Все свойства объекта доступны через Инспектор объектов, за исклю­чением свойства FieldName, которое доступно только во время выполнения приложения, однако при разработке приложения значение этого свойства видно в окне Редактора полей. Значение параметра Туре определяет класс объекта Field, который будет соответствовать статическому полю, например, для типа String это TStringField, а для типа Float — это TFloatField.

Таблица 5.2. Свойства объекта поля


Свойство объекта поля


Элемент управления


 


FieldName

Name

Size (для строковых полей)

Precision (для числовых полей)

FieldKind

KeyFields

LookupKeyFields

LookupDataset

LookupResultField


Поле ввода Name Поле ввода Component Поле ввода Size

Группа переключателей Field type Комбинированный список Key Fields Комбинированный список Lookup Keys Комбинированный список Dataset Комбинированный список Result Field


Глава 5. Компоненты доступа к данным


111


Свойство FieldKind типа TFieldKind определяет тип поля и принимает сле­дующие значения:

□ f kData (поле данных);

□ f kCalculated (вычисляемое поле);

□ f kLookupField (поле выбора);

□ fkinternalCalc (вычисляемое поле, которое сохраняется в наборе данных);

□ f kAggregate (поле, содержащее агрегированный результат).

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

Для создания статического вычисляемого поля нужно выполнить следующие действия:

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

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

После создания вычисляемого поля его свойство FieldKind автоматически по­лучает значение fkCalculated. Кроме того, также автоматически свойство Calculated типа Boolean устанавливается в значение True, указывающее на то, что это поле является вычисляемым. Для полей другого типа свойство Calculated имеет значение False.

Событие OnCalcFields предназначено для определения значений всех вычис­ляемых полей набора данных. Оно генерируется каждый раз при считывании записи из таблицы, а также при изменении значений невычисляемых полей, если свойство AutoCalcFields типа Boolean установлено в значение True (по умолчанию). На время выполнения обработчика события OnCalcFields набор данных переводится в режим dsCalcFields расчета вычисляемых полей, а затем возвращается в предыдущий режим.

СЗамечание^

d обработчике события OnCalcFields можно присваивать значения вычисляемым полям, а также полям выбора (в том числе не входящим в состав списка выбора). Попытка изменить значение поля данных (физического поля таблицы) вызывает ис­ключение.

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

Пусть в состав таблицы входят три поля: Name (название товара), Price (цена единицы товара, в рублях) и Number (количество товара). Набор данных должен


112


Часть I. Основы работы с базами данных


содержать для каждого товара также данные об общей стоимости товара в руб­лях и в Евро. Общая стоимость определяется на основании цены единицы това­ра и количества товара, поэтому в набор данных добавляются два вычисляемых поля: Total и TotalEvro для рублей и Евро соответственно (рис. 5.9).

Рис. 5.9. Использование вычисляемых полей

Для вычисления значений новых полей используется код обработчика события OnCalcFields, приведенный ниже. Обращение к вычисляемым полям и полям данных выполнено разными способами: по имени компонента (для вычисляе­мых полей Total и TotalEvro) и по имени поля (для полей данных Price и Number). Следует иметь в виду, что поля Price и Number тоже должны быть ста­тическими, в противном случае при попытке обращения к ним произойдет ошибка. В примере статическим является также поле Name.

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

// Отформатировать значения поля можно следующим образом

// TablelTotalEvro.DisplayFormat:='#####.##'

procedure TForml.TablelCalcFields(DataSet: TDataSet);

begin

TablelTotal.AsFloat:= Tablel.FieldByName('Price').AsFloat*

Tablel.FieldByName('Number').AsInteger; TablelTotalEvro.AsFloat:= TablelTotal.AsFloat/31; end;

Если в качестве обменного курса взять некоторое реальное значение, напри­мер, 31.75, то значения поля TotalEvro будут содержать большое количество дробных разрядов. Поэтому необходимо округлять получаемые значения или выводить полученные значения в требуемом формате. Для форматирования зна­чений можно использовать свойство DisplayFormat этого поля, установив его через Инспектор объектов или при создании формы, например, следующей ин­струкцией: TablelTotalEvro.DisplayFormat:= '#####.##';


Глава 5. Компоненты доступа к данным


113


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

Необходимость использования поля выбора может возникнуть в случае, когда при поступлении товара ведется таблица реестра, в которую заносится такая, например, информация (в скобках приведены названия полей таблицы):

□ уникальный номер записи (r_n);

□ дата поступления товара (R_Date);

□ уникальный код товара (R_Code);

□ количество поступившего товара (r_number);

□ примечание (R_Note).

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

□ уникальный код товара (G_Code);

□ название товара (G_Name);

□ единица измерения товара (G_Unit);

□ цена единицы товара (c_Price);

□ примечание (c_Note).

В таблице данных о товаре поле уникального кода товара (c_Code) является ав­тоинкрементным — его значение формируется автоматически при добавлении нового товара. При добавлении новой записи в таблицу реестра в поле кода то­вара (R_Code) должен заноситься код поступившего товара. Для установления соответствия между поступившими товарами и их характеристиками обе табли­цы связываются по этим полям. Однако при занесении нового товара в реестр пользователь должен самостоятельно задавать код, соответствующий поступив­шему товару. Эта операция неудобна для пользователя, т. к. нужно знать эти коды, и может привести к ошибкам.

Более удобным вариантом в данном случае будет формирование поля выбора, содержащего товары, из которого пользователь выбирает одно из наименований. Тогда после выбора товара соответствующий код будет заноситься в поле R_Code таблицы реестра автоматически. Окно создания поля выбора показано на рис. 5.10.

Поле выбора названо R_Name и принадлежит набору данных Tablel, содержа­щему записи таблицы реестра. Для формирования списка выбора используется поле G_Name набора данных ТаЫе2, содержащего записи таблицы данных това­ра. Связь между двумя наборами данных Tablel и ТаЫе2 осуществляется че­рез их поля кода товара R_Code и G_Code соответственно (рис. 5.11).


114


Часть I. Основы работы с базами данных



Рис. 5.10.Окно создания поля выбора

Рис. 5.11. Схема использования поля выбора

Использование поля выбора заключается в том, что пользователь выбирает зна­чение в поле R_Name, содержащем список, который построен на основании зна­чений поля G_Name. После выбора значения для поля R_Name из поля связи G_Code автоматически заносится соответствующее значение в поле R_Code. Та­ким образом, поле R_Name, содержащее список, используется для выбора, а поле связи R Code — для занесения в него значения.


Глава 5. Компоненты доступа к данным


115


J

Замечание

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

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

На рис. 5.12 демонстрируется использование поля выбора. В верхней части фор­мы отображается таблица реестра, в нижней — таблица данных, которая приве­дена для наглядности. На практике связанный набор данных обычно не показывается. При выборе значения в списке поля выбора для связанного набо­ра данных текущий указатель устанавливается на запись, значение из которой было выбрано.

Рис. 5.12. Использование поля выбора

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

RefreshLookupList.

Операции с полями

Через объект типа TField разработчик может:

□ обратиться к полю и его значению;

□ проверить тип и значение поля;


116


Часть I. Основы работы с базами данных


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

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

Доступ к значению поля

Объект поля, как и любой другой объект, имеет имя (название), определяемое его свойством Name типа string. Имя объекта Field зависит от того, является ли поле динамическим или статическим. По умолчанию для динамического по­ля имя объекта Field совпадает с именем соответствующего физического поля таблицы БД, для которого создан объект, и не может быть изменено. Имя ста­тического поля является составным и по умолчанию образуется путем слияния имен набора данных и имени физического поля таблицы БД. Например, если для физического поля Name набора данных Tablel с помощью Редактора полей создано статическое поле, то оно получит имя TablelName. Программист может изменить это имя через Инспектор объектов, когда соответствующее статиче­ское поле выбрано в Редакторе полей.

В отличие от имени объекта Field, свойство FieldName типа string содержит имя физического поля, заданное при создании таблицы. Не следует путать свой­ства Name и FieldName, они обозначают разные объекты и в общем случае мо­гут не совпадать.

Пример обращения к полю:

Tablel.FieldByName('Number').DisplayLabel:= 'Количество'; TablelNumber.DisplayLabel:= 'Количество';

Здесь для статического поля Number возможны два способа обращения: по име­ни поля в наборе данных и по имени объекта Field поля.

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

var x: integer;

х:= Tablel.FieldByName('Date').FieldNo;

Для доступа к значению поля служат свойства Value и Asxxx. Свойство Value типа Variant представляет собой фактические данные в объекте типа TFieid. При выполнении приложения это свойство используется для чтения и записи значений в поле. Если программист обращается к свойству Value, то он должен самостоятельно обеспечивать преобразование и согласование типов значений полей и читаемых или записываемых значений. В табл. 5.3 приводятся возмож­ные типы свойства Value для различных объектов типа TFieid.


Глава 5. Компоненты доступа к данным


117


Таблица 5.3. Возможные типы свойства Value

Тип объекта поля Тип свойства value

TField Variant

TStringField, TBLOBField String

TIntegerField, TSmallntField, TWordField, Longint

TAutoincField

TBCDField, TFloatField, TCurrencyField Double

TBooleanField Boolean

TDateTimeField, TDateField, TTimeField TDateTime

Рассмотрим пример, в котором доступ к значению поля осуществляется с по­мощью свойства Value:

procedure TForml.ButtonlClick(Sender: TObject); var s: string;

x: real; begin

// Доступ к полю по его имени в наборе данных s:= Tablel.FieldByName('Salary').Value; x:= Tablel.FieldByName('Salary').Value; Labell.Caption:= s; Label2.Caption:= FloatToStr(x); // Доступ к полю как к отдельному компоненту х:= TablelSalary.Value; Label3.Caption:= FloatToStr(x); // Поле вещественного типа,

// в связи с чем следующая инструкция присваивания недопустима // s:= TablelSalary.Value; end;

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

СЗамечание^

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


118


Часть I. Основы работы с базами данных


Поскольку при доступе к полю с помощью свойства Value программист дол­жен обеспечивать преобразование и согласование типов значений, то часто бо­лее удобно использовать варианты свойства Asxxx:

□ AsVariant типа Variant;

□ AsString типа String;

□ Aslnteger типа Longint;

□ As Float типа Double;

П AsCurrency типа Currency;

□ AsBoolean типа Boolean;

□ AsDateTime типа TdateTime.

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

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

procedure TForml.Button2Click(Sender: TObject); var s: string;

x: real; begin

// Доступ к полю по его имени в наборе данных s:= Tablel.FieldByName('Salary').AsString; x:= Tablel.FieldByName('Salary').AsFloat; Labell.Caption:= s; Label2.Caption:= FloatToStr(x); // Доступ к полю как к отдельному компоненту s:= TablelSalary.AsString; х:= TablelSalary.AsFloat; Label3.Caption:= s; Label4.Caption:= FloatToStr(x); end;

Как и в предыдущем примере, чтение значения поля Salary осуществляется несколькими способами. Доступ к полю выполняется по имени поля и по име­ни объекта поля, а значение поля интерпретируется как строковое или как ве­щественное.

СЗамечание^

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


Глава 5. Компоненты доступа к данным


119


При необходимости программист может запретить модификацию поля, а также скрыть его, используя свойства Readonly и visible типа Boolean. Сама воз­можность модификации данных в отдельном поле определяется значением свойства CanModify типа Boolean. Напомним, что свойства Readonly и CanModify есть также у набора данных: они определяют возможность модифи­кации набора данных (всех его полей) в целом.

(_____ ЗамечаниеJ

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

Если поле является невидимым (свойство Visible установлено в False), но раз­решено для редактирования (свойство Readonly установлено в False), то можно изменить значения этого поля программно.

Рассмотрим управление видимостью поля и возможностью его модификации на примере:

Tablel.FieldByName('Number').Readonly:= True; Tablel.FieldByName('Salary').Visible:= False;

Здесь для поля Number запрещаются любые изменения, а поле Salary скрывается, однако для него по-прежнему допускаются чтение и изменение значения.

Для полей, имеющих типы TBLOBField (BLOB-объект), TGraphicField (гра­фическое изображение) и TMemoField (текст), доступ к их содержимому вы­полняется обычными для объектов данного типа способами. Например, для за­грузки содержимого из файла можно использовать метод LoadFromFile.



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: