Автор работы: Пользователь скрыл имя, 26 Января 2013 в 14:13, лекция
Программирование баз данных - очень большой и серьезный раздел самого что ни на есть практического программирования. На предыдущем курсе "Введение в программирование на Delphi" мы лишь коснулись этой темы, затронули даже не верхушку айсберга под названием Базы Данных, а только его макушку. Между тем, многие программисты большую часть своего времени тратят именно на проектирование баз данных и разработку приложений, работающих с ними. Это неудивительно - в настоящее время каждая государственная организация, каждая фирма или крупная корпорация имеют рабочие места с к
Подготовим диалоговые компоненты. Выделите их и присвойте свойству Filter обоих компонентов строку
Таблицы dBase|*.dbf
Таким образом, мы указали, что диалоги будут работать только с таблицами типа dBase. Кроме того, у обоих диалогов измените свойство DefaultExt, указав там:
dbf
Это свойство указывает расширение файла по умолчанию, если пользователь не назначит расширения сам.
В свойстве DataSet компонента DataSource1 выберите таблицу Table1. В свойстве DataSource сетки DBGrid1 и навигатора DBNavigator1 выберите имеющийся DataSource1. Теперь при открытии таблицы она будет отображаться в сетке, а навигатор позволит управлять ей.
Теперь сложнее - настраиваем компонент Table1. Табличный компонент TTable имеет одно важное свойство TableType, с которым раньше нам не приходилось сталкиваться; компонент TADOTable такого свойства не имеет. Это свойство указывает на тип используемой или создаваемой таблицы. Свойство может иметь следующие значения:
Таблица 9.1 . Значения свойства TableType компонента TTable | |
Значение |
Описание |
ttASCI |
Таблица содержится в формате обычного текстового файла. Строки и поля разделяются специальными символами - разделителями. Имя файла таблицы имеет расширение *.TXT |
ttDBase |
Таблица содержится в формате dBase, файл по умолчанию имеет расширение *.DBF |
ttDefault |
Компонент определяет тип таблицы по расширению имени файла таблицы. При создании таблицы, если не указано расширение имени файла, принимается тип Paradox. |
ttFoxPro |
Таблица содержится в формате FoxPro, файл по умолчанию также имеет расширение *.DBF |
ttParadox |
Таблица содержится в формате Paradox, файл по умолчанию имеет расширение *.DB |
Если выбран тип таблицы (не ttDefault), то будет использован этот тип вне зависимости от расширения указанного имени файла таблицы.
В свойстве TableType компонента Table1 выберите значение ttDBase, то есть, таблица будет работать только с типом dBase. Далее дважды щелкните по компоненту, открыв редактор полей. Нам нужно будет добавить запланированные ранее поля. Щелкните по редактору правой кнопкой, выберите команду New Field (Новое поле). В поле Name впишите имя поля, например, FCeloe. В поле Type выберите тип поля Integer. В поле Size нужно указывать размер поля, но это справедливо только для текстовых полей и полей типов Memo или BLOB. Убедитесь, что переключатель Field Type установлен на Data, это создаст пустое поле указанного типа. Нажав кнопку "ОК" добавьте объект-поле в редактор полей.
Таким же образом создайте еще несколько разнотипных полей. Каждому полю присвойте уникальное имя (ведь в таблице не может быть двух полей с одинаковым именем!). Важно, чтобы вы добавляли только те типы полей, которые поддерживаются выбранным типом таблиц, в нашем случае это dBase. При добавлении типа Memo укажите размер от 1 до 255, например, 50. В этом случае в файле таблицы *.dbf будет сохранен текст поля в 50 символов. Текст, который не уместится в этот размер, будет сохранен в файле Memo с таким же именем, но с расширением *.dbt.
Делать табличный компонент активным на этапе проектирования не нужно. Итак, не имея базы данных, не имея физической таблицы, мы заранее установили тип таблицы и нужные нам поля. Как вы, наверное, догадываетесь, мы также имеем возможность сразу настроить нужные нам форматы для каждого поля, изменяя такие его свойства, как DisplayFormat, EditMask, DisplayLabel и др.
Далее нам осталось непосредственно создать и открыть таблицу. Дважды щелкните по кнопке "Создать таблицу", сгенерировав для нее событие. В процедуру этого события впишите код:
//если пользователь не выбрал таблицу, выходим:
if not SaveDialog1.Execute then Exit;
//закроем таблицу, если вдруг уже есть открытая:
Table1.Close;
//вначале устанавливаем адрес базы данных:
Table1.DatabaseName := ExtractFilePath(SaveDialog1.
//теперь устанавливаем имя таблицы:
Table1.TableName := SaveDialog1.FileName;
//физически создаем таблицу:
Table1.CreateTable;
//и открываем ее:
Table1.Open;
//запишем имя открытой таблицы:
fMain.Caption := 'Таблица - '+ Table1.TableName;
Комментарии к каждой строке достаточно подробны, чтобы вы самостоятельно разобрались с кодом. Метод CreateTable() компонента-таблицы создает файл таблицы, и дополнительные файлы (Memo, индексные), если они нужны. В свойстве DatabaseName табличного компонента вы можете установить любой необходимый вам адрес, мы использовали папку, выбранную диалогом SaveDialog.
Для кнопки "Открыть таблицу" код будет почти таким же:
//если пользователь не выбрал таблицу, выходим:
if not OpenDialog1.Execute then Exit;
//закроем таблицу, если вдруг уже есть открытая:
Table1.Close;
//вначале устанавливаем адрес базы данных:
Table1.DatabaseName := ExtractFilePath(OpenDialog1.
//теперь устанавливаем имя таблицы:
Table1.TableName := OpenDialog1.FileName;
//открываем таблицу:
Table1.Open;
//запишем имя открытой таблицы:
fMain.Caption := 'Таблица - '+ Table1.TableName;
Откомпилировав программу и поработав с ней, вы обнаружите, что можете создавать и открывать сколь угодно много таблиц программно. При этом на каждую таблицу создается по два файла (если вы используете поле Memo). Попробуйте таким же образом создать таблицу типа Paradox.
В задачу данного раздела входит создание таблицы Paradox с различными типами полей, с первичным ключом и индексами по текстовому полю как в возрастающем, так и в убывающем порядке. Редактор полей компонента TTable при этом вызывать не нужно, добавлять поля мы тоже будем программно. В целях экономии места проектирование формы приложения не описывается - это несложная задача. Вы можете создать главную форму такой же, как в предыдущем примере, только кнопка там будет одна. При нажатии на эту кнопку мы должны открыть таблицу, если она существует, или создать и открыть новую таблицу. Располагаться таблица должна в той же папке, откуда запущено приложение. Файл с таблицей Paradox назовем Proba.db, файлы с Memo и индексные файлы сгенерируются автоматически, также с именем Proba, но с разными расширениями.
На форму добавьте компонент TTable с вкладки BDE, свойству Name которого присвойте значение TMy (вместо Table1), а свойству TableType значение ttParadox. Если у вас в приложении есть сетка DBGrid и (или) навигатор DBNavigator, то добавьте также компонент DataSource, который необходимо подключить к таблице TMy, а сетку и навигатор - подключить к DataSource. Здесь следует иметь в виду одну деталь: описание методов создания полей и индексов хранится в модуле DBTables, который подключается к вашей форме сразу, как вы установите компонент TTable. Если же вы используете модуль данных, и устанавливаете табличный компонент там, то и создавать таблицу нужно тоже в этом модуле, а в главной форме лишь вызывать процедуру создания таблицы. Но в нашем простом примере модуля данных нет, модуль DBTables указан в разделе Uses главной формы, и никаких проблем возникнуть не должно.
Код нажатия на кнопку выглядит так:
{Если таблицы нет - создаем и открываем ее, если есть-
просто открываем}
procedure TfMain.Button1Click(Sender: TObject);
begin
//если таблица есть - открываем ее и выходим:
if FileExists(ExtractFilePath(
then begin
TMy.DatabaseName := ExtractFilePath(Application.
TMy.TableName := 'Proba.db';
TMy.Open;
Exit;
end; //if
{Если дошли до этого кода, значит таблицы еще нет.
Указываем данные таблицы:}
TMy.DatabaseName := ExtractFilePath(Application.
TMy.TableType := ttParadox;
TMy.TableName := 'Proba';
{Создаем поля:}
with TMy.FieldDefs do begin
//вначале очистим:
Clear;
//добавляем поле-счетчик типа автоинкремент:
with AddFieldDef do begin
Name := 'Key';
DataType := ftAutoInc;
Required := True;
end; //with
//добавляем текстовое поле:
with AddFieldDef do begin
Name := 'Name';
DataType := ftString;
Size := 30;
end; //with
//добавляем поле дата:
with AddFieldDef do begin
Name := 'Date';
DataType := ftDate;
end; //with
//добавляем логическое поле:
with AddFieldDef do begin
Name := 'MyLog';
DataType := ftBoolean;
end; //with
//добавляем целое поле:
with AddFieldDef do begin
Name := 'MyInt';
DataType := ftInteger;
end; //with
//добавляем вещественное поле:
with AddFieldDef do begin
Name := 'MyReal';
DataType := ftFloat;
end; //with
//добавляем денежное поле:
with AddFieldDef do begin
Name := 'MyCurr';
DataType := ftCurrency;
end; //with
//добавляем поле Memo:
with AddFieldDef do begin
Name := 'MyMemo';
DataType := ftMemo;
Size := 20;
end; //with
end; //with
{Создаем ключ и индексы:}
with TMy.IndexDefs do begin
Clear;
//делаем первичный ключ:
with AddIndexDef do begin
Name := '';
Fields := 'Key';
Options := [ixPrimary];
end;
//делаем индекс в возрастающем порядке:
with AddIndexDef do begin
Name := 'NameIndxASC';
Fields := 'Name';
Options := [ixCaseInsensitive];
end;
//делаем индекс в убывающем порядке:
with AddIndexDef do begin
Name := 'NameIndxDESC';
Fields := 'Name';
Options := [ixCaseInsensitive, ixDescending];
end;
end; //with
//создаем таблицу:
TMy.CreateTable;
//и открываем ее:
TMy.Open;
end;
Разберем приведенный код. Первый блок выполняет проверку на наличие таблицы. Таблица ищется в папке, откуда была запущена программа. Если таблица найдена, то компоненту TMy присваиваются свойства DatabaseName (папка, где располагается таблица) и TableName (имя таблицы). В нашем случае таблица называется Proba.db, но вы можете усложнить программу, используя диалог OpenDialog, как в прошлом примере. В этом случае пользователь сможет выбрать не только имя таблицы, но и ее расположение. Далее таблица открывается, а оператор Exit досрочно завершает выполнение процедуры.
Если выполнение процедуры продолжается, значит, таблица не была найдена. В этом случае мы заполняем свойства компонента-таблицы DatabaseName, TableType и TableName необходимыми значениями.
Далее начинаем добавлять поля. Чтобы уменьшить код, мы используем оператор with. Напомню, что этот оператор создает блок кода, который относится к указанному в with объекту. Так, вместо
with TMy.FieldDefs do begin
Clear;
можно было бы написать
TMy.FieldDefs.Clear;
В случае одиночного оператора это допустимо, но в случае множественных команд ссылаться в каждой строчке на объект будет утомительно. Свойство FieldDefs таблицы содержит описание полей этого набора данных. Таким образом, мы начинаем с того, что очищаем это описание.
Далее у нас идет метод AddFieldDef, предназначенный для добавления поля в описание. Опять же, чтобы не ссылаться каждый раз на этот метод, мы используем вложенный оператор with для каждого добавляемого поля.
В простейшем случае в блоке добавления нового поля требуется указать только два свойства объекта-поля: Name (имя поля) и DataType (тип поля). С именем все понятно, а что касается типа поля, то он определяется свойством DataType класса TField. Чтобы получить подробную справку по возможным типам полей, установите курсор в редакторе кода на слове DataType и нажмите <Ctrl+F1>, чтобы вызвать контекстную справку. В списке тем выберите ту тему, которая относится к классу TField, а в открывшейся справке щелкните по ссылке TFieldType (относится к Delphi 7, хотя возможно, имеется и в предыдущих версиях). Откроется страница с подробным описанием типов полей. При использовании этого метода следует сверяться, имеется ли выбранный тип поля в таблицах используемого формата.
Помимо этих двух свойств, при необходимости могут использоваться и другие:
Required - Логическое свойство. Если равно True, то значения поля должны быть уникальными (не могут повторяться). В нашем примере такое свойство имеется у поля, которое мы будем использовать как первичный ключ.
Size - Указывает размер поля. Используется в основном, со строковыми и Memo- полями.
После того, как в список полей были добавлены все необходимые поля, начинаем создание первичного ключа и индексов. Если за список полей отвечает свойство FieldDefs таблицы, то за список индексов отвечает свойство IndexDefs, а за добавление нового индекса - метод AddIndexDef. По аналогии с полями, используем оператор with для уменьшения кода. Для каждого индекса требуется указать по три свойства: Name (имя индекса), Fields (имя поля, по которому строится индекс) и Options (параметры индекса). Параметры индекса указаны в таблице 9.2:
Таблица 9.2. Параметры типов индекса | |
Тип |
Описание |
ixPrimary |
Первичный индекс (ключ). Не применяется с таблицами типа dBase. |
ixUnique |
Уникальный индекс. Значения этого поля не могут повторяться. |
ixDescending |
Индекс в убывающем (обратном) порядке. |
ixExpression |
Ключевой индекс для таблиц dBase. |
ixCaseInsensitive |
Индекс, нечувствительный к регистру букв. |
ixNonMaintained |
Этот тип используется редко. Он подразумевает, что при редактировании пользователем значения индексируемого поля, индексный файл автоматически не обновляется. |
Как видно из примера, свойству Options можно присвоить не один параметр, а список параметров:
Options := [ixCaseInsensitive, ixDescending];
Далее все просто: указав необходимые поля и индексы, методом CreateTable формируются физические файлы таблицы. Сама таблица имеет расширение *.db, файл с полем Memo - *.mb, остальные файлы содержат созданные индексы.
Для сортировки данных используем индексы. У нас их два -'NameIndxASC' (в возрастающем порядке) и 'NameIndxDESC' (в убывающем порядке). Чтобы сортировать данные, например, в убывающем порядке, нужно указать имя соответствующего индекса в свойстве IndexName компонента-таблицы:
TMy.IndexName := 'NameIndxDESC';
Если же мы хотим снять сортировку, то достаточно просто присвоить этому свойству пустую строку:
TMy.IndexName := '';
Описываемый выше пример взят из справочника Delphi и приведен с небольшими доработками. Пример описывает практически все аспекты создания таблицы; по аналогии вы сможете создавать таблицы любой сложности.
Создание таблицы выполняется S