Программа методичні вказівки І індивідуальні завдання до вивчення дисципліни «системи управління базами даних» для студентів за галузю знань 0201



Сторінка8/9
Дата конвертації27.04.2016
Розмір1.08 Mb.
1   2   3   4   5   6   7   8   9

3.2 Компоненты управления данными


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

Компонент TDBGrid позволяет представить таблицу базы данных в виде похожем на электронную таблицу.

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

Компонент TDBText подобен компоненту TLabel.

Компонент TDBEdit выполняет ту же функцию, что и компонент TEdit.

Компоненты TDBMemo, TDBRichEdit и TDBImage предназначены для отображения и редактирования текстовой и графической информации, содержащейся в Blob полях базы данных.

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

Компонент TDBComboBox аналогичен компоненту TComboBox. Посредством этого компонента пользователь получает возможность выбрать из списка необходимое значение или ввести его в поле ввода.

Компонент TDBCheckBox выполняет ту же функцию, что и компонент TCheckBox, однако источником данных для этого компонента является поле таблицы базы данных.
Тема 1 Класс tdataset – основной класс доступа к данным

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

1.1 Класс TDataSet

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

В большинстве случаев TDataSet имеет прямое соответствие (один к одному) с физической таблицей, существующей на диске. Тем не менее, TDataSet обладает методами, позволяющими получить любое подмножество записей одной таблицы или объединения нескольких таблиц. Однако, во многих случаях можно исполнять запрос или выполнять другое действие, возвращающие DataSet, содержащий любое подмножество записей одной таблицы, либо объединение (join) между несколькими таблицами. Далее в тексте будут иногда использоваться термины DataSet и TTable как синонимы.
Схема доступа к данным

Рис.1


1.2 Открытие и закрытие DataSet

При использовании объекта TTable для доступа к таблице необходимо определить некоторые его свойства. Для изучения объекта необходимо поместить его во время дизайна в форму, и указать с какой таблицей будет установлена связь. Связь с таблицей устанавливается с помощью свойств DatabaseName и TableName. Для свойства DatabaseName достаточно указать директорий, в которой расположены таблицы в форматах dBase или Paradox например: C:\DELPHI\DEMOS\DATA. Также можно выбрать из списка псевдоним базы данных DBDEMOS или любой другой псевдоним. Псевдоним базы данных (Alias) определяется в утилите Database Engine Configuration. В поле TableName необходимо указать имя таблицы. Если свойство Active установлено в состояние True, то при запуске приложения таблица будет открываться автоматически.

Существует два способа открытия таблицы во время выполнения программы. Первый способ соответствует записи: Table.Open;

а второй способ заключается в установке свойства Active таблицы в состояние True: Table.Active := True;

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

Также имеется и два способа закрыть таблицу. Первый способ определяется вызовом метода Close: Table.Close;

Второй способ осуществляется установкой свойства Active в состояние False: Table.Active := False;
1.3 Навигация

Для перемещения по записям внутри таблицы объект TDataSet обладает следующими методами и свойствами:



  • procedure First.

  • procedure Last.

  • procedure Next.

  • procedure Prior.

  • property BOF: Boolean read FBOF.

  • property EOF: Boolean read FEOF.

  • procedure MoveBy(Distance: Integer).

Метод Table.First перемещает указатель к первой записи в таблице. Метод Table.Last перемещает указатель к последней записи в таблице. Методы Table.Next и Table.Prior перемещают указатели на одну запись вперед и назад соответственно. Свойства BOF и EOF указывают на начало и конец таблицы. Метод MoveBy перемещает указатель на определенное число записей к началу или концу таблицы. Метод Table.MoveBy(1) аналогичен методу Table.Next, а метод Table.MoveBy(-1) аналогичен методу Table.Prior.

Рассмотрим на примере описанные методы и свойства объекта TDataSet. Необходимо поместить в форму следующие компоненты: DataSource, Table, DBGrid, DBNavigator, 4 компонента Button и компонент SpinEdit. Кнопкам Button необходимо присвоить следующие имена: NextBtn, PriorBtn, FirstBtn, LastBtn, ReturnBtn, GoEndBtn и MoveBtn. Посредством свойства DataSource требуется установить связь компонентов DBGrid1 и DBNavigator1 с компонентом DataSource1. Используя свойство DataSet компонента DataSource1, необходимо установить связь с компонентом Table1. Достаточно выбирать из списков DataBaseName псевдоним DBDEMOS и TableName имя таблицы CUSTOMER и установить свойство Active таблицы в состояние True. После выполнения данной операции в компоненте DBGrid1 появятся данные таблицы CUSTOMER (рис.2).


Доступ к данным в период дизайна

Рис.2


Теперь можно запустить приложение на выполнение и проследить перемещение по полям таблицы посредством нажатия соответствующих кнопок компонента DBNavigator1 и полос прокруток компонента DBGrid1.

Компонент DBNavigator обладает практически всеми необходимыми свойствами и методами управления таблицей. Однако нашей задачей является рассмотрение вопроса программного управления объектом TDataSet без использования универсального элемента управления DBNavigator. Поэтому, для обработчиков событий OnClick кнопок необходимо написать строки, приведенные в примере 1.



Пример 1

procedure TForm1.NextBtnClick(Sender: TObject);

begin

Table1.Next;



end;

procedure TForm1.PriorBtnClick(Sender: TObject);

begin

Table1.Prior;



end;

procedure TForm1.FirstBtnClick(Sender: TObject);

begin

Table1.First;



end;

procedure TForm1.LastBtnClick(Sender: TObject);

begin

Table1.Last;



end;

Теперь можно запустить приложение и проверить функционирование кнопок.

При работе с базами данных часто возникает необходимость изменять значения полей для всей таблицы. С этой целью удобно использовать свойства TDataSet.BOF и TDataSet.EOF.

TDataSet.BOFread-only Boolean свойство, используется для проверки, находитесь ли Вы в начале таблицы. Свойства BOF возвращает true в трех случаях:


  • После того, когда пользователь открыл файл.

  • После того, когда пользователь вызывал TDataSet.First.

  • После того, когда вызов TDataSet.Prior не выполняется.

Первые два пункта – очевидны. Когда пользователь открывает таблицу, выполняется помещение на первую запись. Когда вызывается метод First, также происходит перемещение указателя в начало таблицы. Метод Prior требует небольшого пояснения. После того, когда пользователь многократно вызывает метод Prior, возникает ситуация достижения начала таблицы, и следующий вызов Prior будет неудачным. При этом BOF возвратит значение True. Используя данное свойство, можно определить достижение начала таблицы, как показано в примере 2.

Пример 2

procedure TForm1.ReturnBtnClick(Sender: TObject);

begin

Table1.Last;



while not Table1.Bof do

begin

{ В данном месте должен находиться текст модификации

полей таблицы.}

Table1.Prior;



end;

end;

Аналогично свойству BOF применяется свойство EOF для проверки достижения конца таблицы. EOF возвращает True в следующих трех случаях:



  • После того, когда пользователь открыл пустой файл.

  • После того, когда пользователь вызывал TDataSet.Last.

  • После того, когда вызов TDataSet.Next не выполняется.

Пример 3 демонстрирует простой способ перемещения по всем записям таблицы, начиная с первой записи.
Пример 3

procedure TForm1.GoEndBtnClick(Sender: TObject);

begin

Table1.First;



while not Table1.EOF do

begin

{В данном месте должен находится текст модификации полей таблицы.}

Table1.Next;



end;

end;

Для перемещения на заданное число записей в любом напрвлении используется метод MoveBy. Пример 4 демонстрирует указанный метод.



Пример 4

procedure TForm1.MoveBtnClick(Sender: TObject);

begin

Table1.MoveBy(SpinEdit1.Value);



end;
1.4 Поля таблицы

Для получения доступа к полям таблицы объект TDataSet обладает рядом методов и свойств, основными из которых являются:



  • property Fields[Index: Integer];

  • function FieldByName(const FieldName: string): TField;

  • property FieldCount.

Свойство FieldCount возвращает число полей в текущей структуре записи. Если необходимо программным путем прочитать имена полей, то для доступа к ним следует применить свойство Fields (пример 5).

Пример 5

var

S: String;



begin

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



end;

В приведенном выше примере 5 переменной S присваивается имя первого поля таблицы, индекс которого соответствует нулю. Для доступа к имени последнего поля следует указать индекс равный Table.FieldCount – 1 (Пример 6).



Пример 6

var

S: String;



begin

S := Table.Fields[Table.FieldCount - 1].FieldName;



end;

Если необходимо определить текущее содержание выбранного поля конкретной записи, то рекомендуется использовать свойство Fields или метод FieldsByName. Для этого достаточно найти значение i - го поля записи как i - й элемент массива Fields (пример 7).



Пример 7

var

S: String;

i: Integer;

begin

i := 3;


S := Table.Fields[i].AsString;

end;

Предположим, что указанное поле в записи содержит номер записи, тогда код, приведенный выше, возвратил бы строку типа «10», «1012» или «1024». Если требуется получить доступ к этой переменный, как к числовой величине, тогда необходимо использовать тип AsInteger вместо типа AsString. Аналогично, указываются и другие типы данных: AsBoolean, AsFloat и AsDate.

В примере 8 показано, что для доступа к данным можно применять функцию FieldsByName вместо свойства Fields.

Пример 8

var

S: String;



begin

S := Table.FieldsByName(‘Nuncode’).AsString;



end;

В приведенных примерах 5 – 8 показано, что метод FieldsByName, и свойство Fields возвращают те же самые данные. Два различных синтаксиса используются для того, чтобы обеспечить программистов гибким и удобным набором инструментов для доступа к содержимому DataSet.

Рассмотрим пример, как можно использовать доступ к полям таблицы во время выполнения программы. Для этого необходимо поместить в форму объект Table, два объекта ListBox и две кнопки Button, и присвоить кнопкам имена Fields и Values (рис. 3.). Далее требуется установить связь объекта Table1 с базой данных DBDEMOS посредством свойства DatabaseName и выбрать таблицу CUSTOMER в списке свойства TableName. Для доступа к данным в период дизайна требуется установить свойство Active таблицы в состояние True.

Расположение элементов управления в форме



Рис.3
Далее необходимо написать обработчик события для нажатой кнопки Fields (пример 9).



Пример 9

procedure TForm1.FieldsClick(Sender: TObject);

var

i: Integer;



begin

ListBox1.Clear;



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

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



end;
Приведенная процедура (пример 9) функционирует следующим образом. Первая программная строка очищает компонент ListBox1. Затем в цикле последовательно добавляются имена полей таблицы. Обратите внимание на то, что счет в цикле начинается с 0, и заканчивается Table1.FieldCount – 1. Если не вычесть единицу из значения FieldCount, то произойдет исключительная ситуация «List Index Out of Bounds», обусловленная попыткой прочесть имя поля которое не существует.
Для получения доступа к содержимому полей обработчик события для кнопки Values будет иметь вид, приведенный в примере 10.

Пример 10

procedure TForm1.ValuesClick(Sender: TObject);

var

i: Integer;



begin

ListBox2.Clear;



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

ListBox2.Items.Add(Table1.Fields[i].AsString);



end;

На рисунке 4 приведено функционирующее приложение, демонстрирующее выполнение процедур приведенных в примерах 9 – 10.

Реализация процедур

Рис.4
Напомним, что класс TField обладает следующими свойствами:



  • property AsBoolean;

  • property AsFloat;

  • property AsInteger;

  • property AsString;

  • property AsDateTime.

Если возникает необходимость, то можно преобразовывать тип поля Boolean к Integer или к Float, тип поля Integer к String или тип поля Float к Integer. Однако преобразовывать тип поля String к Integer невозможно. Если необходимо работать с полями Date или DateTime, то можно использовать преобразования AsString и AsFloat для доступа к ним.

1.5 Работа с данными

Для работы с данными объект TTable имеет следующие методы:



  • procedure Append;

  • procedure Insert;

  • procedure Cancel;

  • procedure Delete;

  • procedure Edit;

  • procedure Post;

Все указанные методы являются методами TDataSet. Они унаследованы и используются объектами TTable и TQuery. Всякий раз, когда пользователь желает изменить данные, он должен сначала перевести DataSet в моду редактирования. Большинство элементов управления базами данных переводят DataSet в моду редактирования автоматически. Однако, если необходимо изменить TTable программно, пользователю придется использовать вышеуказанные функции.

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



Пример 11

Table1.Edit;

Table1.FieldByName(‘CustName’).AsString := ‘Client 1024’;

Table1.Post;

Первая строка программы переводит DataSet в режим редактирования. Вторая строка присваивает значение полю ‘CustName’. Третья строка обеспечивает запись данных на диск, путем вызова метода Post.

Другим способом сохранения записи на диске является перемещение к следующей записи после ее редактирования (пример 12).



Пример 12

Table1.Edit;

Table1.FieldByName(‘CustNo’).AsInteger := 1024;

Table1.Next;

На основании вышеизложенного, следует вывод, что всякий раз, когда выполняется перемещение с текущей записи на другую в режиме редактирования выполняется запись на диск. Это означает, что вызовы методов First, Next, Prior и Last завершаются методом Post, при условии, что объект DataSet нахотится в состоянии редактирования.

Для добавления и вставки новых записей в таблицу используются методы Append и Insert соответственно. Рассмотрим данные методы на следующем примере. Для демонстрации указанных методов необходимо разместить в форме компоненты Table, DataSource, DBGrid и три кнопки Button. Присвоим кнопкам соответствующие имена: InsertBtn, AppendBtn и DeleteBtn. Далее необходимо установить соединения между объектами DataSource1, Table1, DBGrid1, и связать объект Table1 с таблицей COUNTRY базы данных DBDEMOS (рис. 5). Для доступа к данным в период дизайна требуется установить свойство Active объекта Table1 в состояние true.


Расположение элементов управления в форме

Рис.5
Процедуры обработчиков событий OnClick кнопок, в нашем случае, будут иметь вид приведенный в примере 13.



Пример 13

procedure TForm1.InsertBtnClick(Sender: TObject);

begin

Table1.Insert;

Table1.FieldByName('Name').AsString := 'Ukraine';

Table1.FieldByName('Capital').AsString := 'Kiev';

Table1.Post;

end;

procedure TForm1.AppendBtnClick(Sender: TObject);

begin

Table1.Append;

Table1.FieldByName('Name').AsString := 'Ukraine';

Table1.FieldByName('Capital').AsString := 'Kiev';

Table1.Post;

end;

procedure TForm1.DeleteBtnClick(Sender: TObject);

begin

Table1.Delete;



end;
Процедура TForm1.InsertBtnClick(Sender: TObject) переводит таблицу в режим вставки, то есть, создается новая запись с пустыми полями, которая вставляется в текущую позицию dataset. После вставки пустой записи, выполняется присвоение значений одному или нескольким полям, а затем вызывается метод Post. Аналогично функционирует обработчик события AppendBtnClick.

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

Table1.FieldByName(‘Name’).AsString := Edit1.Text;
Интересным моментом в рассматриваемом примере является то, что нажатие кнопки Insert дважды подряд автоматически вызывает исключительную ситуацию ‘Key Violation’, так как первое поле таблицы COUNTRY опредедено как певичный ключ. Таким образом, DataSet защищает базу данных от повторного присвоения одинакового имени.

Если после вызова методов Insert или Append, необходимо отказаться от вставки или добавления новой записи, то надо вызвать метод Cancel до метода Post.



1.6 Использование SetKey для поиска записей в таблице

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

Для того, чтобы создать программу поиска данных, требуется поместить в форму компоненты Table, DataSource, DBGrid, Button, Label и Edit, и расположить их как показано на (рис. 5). Далее необходимо изменить имя кнопки Button на имя SearhBtn, и затем соединить компоненты управления базой данных так, чтобы пользователь открыл в DBGrid1 таблицу Customer.
Расположение компонентов в форме

Рис.6
Вся функциональность данной программы скрыта в единственном методе, который является обработчиком события OnClick кнопки SearchBtn. Данный обработчик считывает строку, введенную в окно редактора, и ищет ее значение в поле CustNo, и помещает фокус на найденной записи. В простейшем варианте, код обработчика события выглядит так (пример 14):



Пример 14

procedure TForm1.SearhBtnClick(Sender: TObject);

begin

Table1.SetKey;

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

Table1.GotoKey;



end;

Первый вызов в этой процедуре установит Table1 в режим поиска. Далее, свойству Fields присваивается значение, которое пользователь ввел в элемент ввода. Для фактического выполнения поиска нужно вызывать метод Table1.GotoKey.

Если необходимо выполнить поиск не по первичному индексу файла, тогда пользователю потребуется определить имя индекса, который будет использоваться свойством IndexName. Например, если таблица Customer имеет вторичный индекс по полю City, тогда пользователь должен установить свойство IndexName равным имени индекса. Реализация описанного метода приведена в примере 15.

Пример 15

procedure TForm1.SearhBtnClick(Sender: TObject);

begin

Table1.IndexName := 'CityIndex';

Table1.Active := True; Table1.SetKey;

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



end;

Обращаем внимание на тот факт, что поиск не будет выполняться, если пользователь не назначит правильно индекс (свойство IndexName). Также, пользователь должен помнить, что IndexName - это свойство объекта Ttable, и не присутствует в других прямых потомках TDataSet или TDBDataSet.

Когда пользователь производит поиск некоторого значения, всегда существует вероятность того, что поиск окажется неудачным. В таком случае будет автоматически возникать исключительная ситуация (exception). Если возникает необходимость обработать ошибку самостоятельно, то пользователь мог бы написать примерно такую процедуру (пример 16).

Пример 16

procedure TForm1.SearhBtnClick(Sender: TObject);

begin

Cust.SetKey;

Cust.FieldByName('CustNo').AsString:= CustNoEdit.Text;

if not Cust.GotoKey then

raise Exception.CreateFmt('Cannot find CustNo %g', [CustNo]);

end;

В приведенном примере 16, неверное присвоение номера, или неудача поиска автоматически приведут к сообщению об ошибке:

‘Cannot find CustNo %g’.

Иногда требуется найти не точно совпадающее значение поля, а близкое к его значению. Для этого следует вместо GotoKey пользоваться методом GotoNearest.


1.7 Использование фильтров для ограничения числа записей

Процедура ApplyRange позволяет установить фильтр, который ограничивает диапазон просматриваемых записей. Например, в таблице Customers, поле CustNo имеет диапазон от 1,000 до 10,000. Если пользователь желает получить доступ к идентификаторам в диапазоне 2000 – 3000, то он должен использовать метод ApplyRange, и еще два связанных с ним метода. Данные методы работают только с индексированным полем.

Приведенные ниже процедуры наиболее часто используются для установки фильтров:


  • procedure SetRangeStart;

  • procedure SetRangeEnd;

  • procedure ApplyRange;

  • procedure CancelRange.

Кроме того, объект TTable содержит дополнительные методы для управления фильтрами:

  • procedure EditRangeStart;

  • procedure EditRangeEnd;

  • procedure SetRange.

Для создания фильтра с использованием указанных процедур необходимо:

  • Вызвать метод SetRangeStart и посредством свойства Fields определит начало диапазона.

  • Вызвать метод SetRangeEnd и посредством свойства Fields указать конец диапазона.

  • Для активизации фильтра достаточно вызвать метод ApplyRange.

  • Чтобы отказаться от действия фильтра необходимо вызвать метод CancelRange.

Рассмотрим пример использования приведенных методов для создания фильтра. Для этого необходимо поместить компоненты Table, DataSource и DbGrid в форму и соединить их поля таким образом, чтобы обеспечить доступ к таблице CUSTOMERS базы данных DEMOS. Затем поместить в форму два объекта Label и назовить их Start Range и End Range. Затем включить в форму два объекта Edit и две кнопки ApplyRange и CancelRange (рис.7).
Расположение компонентов в форме

Рис.7


В примере 17 приведены процедуры, реализующие фильтр указанными методами.

Пример 17

procedure TForm1.ApplyRangeClick(Sender: TObject);

begin

Table1.SetRangeStart;



if Edit1.Text <> '' then

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

Table1.SetRangeEnd;

if Edit2.Text <> '' then

Table1.Fields[0].AsString := Edit2.Text;

Table1.ApplyRange;

end;

procedure TForm1.CancelRangeClick(Sender: TObject);

begin

Table1.CancelRange;



end;
1.8 Обновление данных

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

Для обновления данных DataSet располагает функцией Refresh.Функция Refresh связана с функцией Open, таким образом, что она считывает данные, или некоторую часть данных, связанных с данной таблицей. Например, когда пользователь открывает таблицу, DataSet считывает данные непосредственно из файла базы данных. Аналогично, когда пользователь регенерирует таблицу, DataSet считывает данные напрямую из таблицы. Вследствие чего, всегда можно использовать эту функцию, чтобы обновить таблицу. Быстрее и эффективнее, вызывать метод Refresh, чем метод Close и затем метод Open.

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


1.9 Закладки

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



  • function GetBookmark: TBookmark – устанавливает закладку в таблице.

  • procedure GotoBookmark(Bookmark: TBookmark) – переводит указатель на закладку.

  • procedure FreeBookmark(Bookmark: TBookmark) – освобождает память.

Как видно, вызов метода GetBookmark возвращает переменную типа Tbookmark. Метод TBookmark содержит достаточное количество информации, чтобы DataSet мог найти местоположение, к которому относится этот TBookmark. Поэтому пользователь может передавать Tbookmark функции GotoBookmark, которая немедленно возвратит указатель к местоположению, связанному с закладкой. Обращаем внимание на то, что вызов метода GetBookmark выделяет память для TBookmark, так что пользователю необходимо вызывать метод FreeBookmark до завершения работы программы, или перед каждой попыткой повторного использования метода GetBookMark.

1.10 Создание связанных курсоров

Связанные курсоры позволяют определить отношение один ко многим (one-to-many relationship). Например, иногда полезно связать таблицы, например CUSTOMER и ORDERS так, чтобы каждый раз, когда пользователь выбирает имя заказчика, то он видит список заказов связанных с этим заказчиком. Иначе говоря, когда пользователь выбирает запись о заказчике, то он может просматривать только заказы, сделанные этим заказчиком.

Рассмотрим пример программы, которая использует связанные курсоры. Дизайн программы сводится к установке в форму двух экземпляров объектов TTable, двух экземпляров TDataSource и двух экземпляров элементов управления TDBGrid. Далее необходимо присоединить первый набор к таблице CUSTOMER, а второй к таблице ORDERS. Программа в этой стадии имеет вид, приведенный на рис 8.
Дизайн программы

Рис.8
После выполнения дизайна следует связать таблицу ORDERS с таблицей CUSTOMER так, чтобы были видимы только те заказы, которые связанные с текущей записью в таблице заказчиков. В первой таблице заказчик однозначно идентифицируется своим номером – поле CustNo. Во второй таблице принадлежность заказа определяется также номером заказчика в поле CustNo. Следовательно, таблицы нужно связывать по полю CustNo. Следует заметить, что в обеих таблицах поля могут иметь различное название, но должны быть совместимы по типу. Для этого, чтобы установить связь необходимо выполнить три действия.



  • Установить свойство Table2.MasterSource = DataSource1.

  • Установить свойство Table2.MasterField = CustNo.

  • Установить свойство Table2.IndexName = CustNo.

Второе действие выполняется посредством редактора связей (рис. 9).
Общий вид редактора связей

Рис.9


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

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


1   2   3   4   5   6   7   8   9


База даних захищена авторським правом ©shag.com.ua 2016
звернутися до адміністрації

    Головна сторінка