На прошлых лекциях мы изучили немало способов создания и обработки таблиц. В большинстве случаев, база данных и таблицы в ней проектируются и создаются заранее, например, такими утилитами, как Database Desktop, или СУБД . Однако иногда приходится создавать таблицы программно, то есть, не во время проектирования приложения, а во время его работы. Предположим, каждый пользователь программы должен иметь свою собственную таблицу в базе данных, или даже свою собственную БД. Сделать это заранее программист не может, ведь неизвестно, сколько пользователей на одном ПК будут работать с программой, и какие у них будут имена.
К сожалению, в большинстве учебной литературы информация о программном создании таблиц или вовсе отсутствует, или очень скудна - описывается только какой то один способ создания только одного типа таблиц. А ведь программисту, в зависимости от обстоятельств, может понадобиться создание разного типа таблиц, разными способами. В данной лекции мы попробуем восполнить этот пробел и разберем три способа программного создания как простых, так и
Наиболее простой способ создания таблицы без индексов предлагает . Плюсы данного способа в простоте выполнения, в возможности создания таблиц как текстового типа, так и dBase, Paradox или FoxPro.
Суть данного способа заключается в предварительном создании объектов-полей в TTable. Это также означает, что еще на этапе проектирования можно настроить формат объектов-полей по своему усмотрению. Рассмотрим этот способ на примере. Создайте новое приложение. Форму как всегда назовите fMain, сохраните модуль под именем Main, а проект в целом назовите как угодно. На форму установите простую панель, очистите ее свойство Caption, а свойству Align присвойте значение alTop. В левой части панели установите рядом две простые кнопки, а в правой - компонент TDBNavigator с вкладки TDBGrid, в ее свойстве Align выберите значение alClient. У кнопок измените свойство Caption: на первой кнопке напишите "Создать таблицу", на второй - "Открыть таблицу".
Также нам потребуется еще четыре не визуальных компонента. Прямо на сетку, или в любое другое место установите компонент TTable с вкладки , компонент TDataSource с вкладки , и компоненты TSaveDialog и TOpenDialog с вкладки Dialogs.
Подготовим Filter обоих компонентов строку
Таблицы dBase|*.dbf
Таким образом, мы указали, что диалоги будут работать только с таблицами типа dBase. Кроме того, у обоих диалогов измените свойство DefaultExt, указав там:
dbf
Это свойство указывает расширение файла по умолчанию, если пользователь не назначит расширения сам.
В свойстве DataSet компонента DataSource1 выберите таблицу Table1. В свойстве DataSource сетки DBGrid1 и навигатора DBNavigator1 выберите имеющийся DataSource1. Теперь при открытии таблицы она будет отображаться в сетке, а навигатор позволит управлять ей.
Теперь сложнее - настраиваем компонент Table1. Табличный компонент TTable имеет одно важное свойство TableType, с которым раньше нам не приходилось сталкиваться; компонент такого свойства не имеет. Это свойство указывает на тип используемой или создаваемой таблицы. Свойство может иметь следующие значения:
| Значение | Описание |
|---|---|
| ttASCI | Таблица содержится в формате обычного текстового файла. Строки и поля разделяются специальными символами - разделителями. Имя файла таблицы имеет расширение *.TXT |
| ttDBase | Таблица содержится в формате dBase, файл по умолчанию имеет расширение *.DBF |
| ttDefault | Компонент определяет тип таблицы по расширению имени файла таблицы. При создании таблицы, если не указано расширение имени файла, принимается тип Paradox. |
| ttFoxPro | Таблица содержится в формате FoxPro, файл по умолчанию также имеет расширение *.DBF |
| ttParadox | Таблица содержится в формате Paradox, файл по умолчанию имеет расширение *.DB |
Если выбран тип таблицы (не ttDefault ), то будет использован этот тип вне зависимости от расширения указанного имени файла таблицы.
В свойстве TableType компонента Table1 выберите значение ttDBase, то есть, таблица будет работать только с типом dBase. Далее дважды щелкните по компоненту, открыв New Field (Новое поле). В поле Name впишите имя поля, например, FCeloe. В поле Type выберите тип поля Integer. В поле Memo или . Убедитесь, что переключатель установлен на Data, это создаст пустое поле указанного типа. Нажав кнопку "ОК" добавьте объект-поле в
Таким же образом создайте еще несколько разнотипных полей. Каждому полю присвойте уникальное имя (ведь в таблице не может быть двух полей с одинаковым именем!). Важно, чтобы вы добавляли только те типы полей, которые поддерживаются выбранным типом таблиц, в нашем случае это dBase. При добавлении типа Memo укажите размер от 1 до 255, например, 50. В этом случае в файле таблицы *.dbf будет сохранен текст поля в 50 символов. Текст, который не уместится в этот размер, будет сохранен в файле Memo с таким же именем, но с расширением *.dbt.
Делать табличный компонент активным на этапе проектирования не нужно. Итак, не имея базы данных, не имея физической таблицы, мы заранее установили тип таблицы и нужные нам поля. Как вы, наверное, догадываетесь, мы также имеем возможность сразу настроить нужные нам форматы для каждого поля, изменяя такие его свойства, как , , и др.
Далее нам осталось непосредственно создать и открыть таблицу. Дважды щелкните по кнопке "Создать таблицу", сгенерировав для нее событие. В процедуру этого события впишите код:
//если пользователь не выбрал таблицу, выходим: if not SaveDialog1.Execute then Exit; //закроем таблицу, если вдруг уже есть открытая: Table1.Close; //вначале устанавливаем адрес базы данных: Table1.DatabaseName := ExtractFilePath(SaveDialog1.FileName); //теперь устанавливаем имя таблицы: Table1.TableName := SaveDialog1.FileName; //физически создаем таблицу: Table1.CreateTable; //и открываем ее: Table1.Open; //запишем имя открытой таблицы: fMain.Caption := 'Таблица - '+ Table1.TableName;
Комментарии к каждой строке достаточно подробны, чтобы вы самостоятельно разобрались с кодом. Метод CreateTable() компонента-таблицы создает файл таблицы, и дополнительные файлы ( Memo, индексные), если они нужны. В свойстве табличного компонента вы можете установить любой необходимый вам адрес, мы использовали папку, выбранную диалогом SaveDialog.
Для кнопки "Открыть таблицу" код будет почти таким же:
//если пользователь не выбрал таблицу, выходим: if not OpenDialog1.Execute then Exit; //закроем таблицу, если вдруг уже есть открытая: Table1.Close; //вначале устанавливаем адрес базы данных: Table1.DatabaseName := ExtractFilePath(OpenDialog1.FileName); //теперь устанавливаем имя таблицы: Table1.TableName := OpenDialog1.FileName; //открываем таблицу: Table1.Open; //запишем имя открытой таблицы: fMain.Caption := 'Таблица - '+ Table1.TableName;
Откомпилировав программу и поработав с ней, вы обнаружите, что можете создавать и открывать сколь угодно много таблиц программно. При этом на каждую таблицу создается по два файла (если вы используете поле Memo ). Попробуйте таким же образом создать таблицу типа Paradox.
В задачу данного раздела входит создание таблицы Paradox с различными типами полей, с первичным ключом и индексами по текстовому полю как в возрастающем, так и в убывающем порядке. TTable при этом вызывать не нужно, добавлять поля мы тоже будем программно. В целях экономии места проектирование формы приложения не описывается - это несложная задача. Вы можете создать главную форму такой же, как в предыдущем примере, только кнопка там будет одна. При нажатии на эту кнопку мы должны открыть таблицу, если она существует, или создать и открыть новую таблицу. Располагаться таблица должна в той же папке, откуда запущено приложение. Файл с таблицей Paradox назовем Proba.db, файлы с Memo и индексные файлы сгенерируются автоматически, также с именем Proba, но с разными расширениями.
На форму добавьте компонент TTable с вкладки , свойству Name которого присвойте значение TMy (вместо Table1 ), а свойству TableType значение ttParadox. Если у вас в приложении есть сетка и (или) навигатор , то добавьте также компонент DataSource, который необходимо подключить к таблице TMy, а сетку и навигатор - подключить к DataSource. Здесь следует иметь в виду одну деталь: описание методов создания полей и индексов хранится в модуле DBTables,
который подключается к вашей форме сразу, как вы установите компонент TTable. Если же вы используете модуль данных, и устанавливаете табличный компонент там, то и создавать таблицу нужно тоже в этом модуле, а в главной форме лишь вызывать процедуру создания таблицы. Но в нашем простом примере модуля данных нет, модуль DBTables указан в разделе Uses главной формы, и никаких проблем возникнуть не должно.
Код нажатия на кнопку выглядит так:
{Если таблицы нет - создаем и открываем ее, если есть-
просто открываем}
procedure TfMain.Button1Click(Sender: TObject);
begin
//если таблица есть - открываем ее и выходим:
if FileExists(ExtractFilePath(Application.ExeName) + 'Proba.db')
then begin
TMy.DatabaseName := ExtractFilePath(Application.ExeName);
TMy.TableName := 'Proba.db';
TMy.Open;
Exit;
end; //if
{Если дошли до этого кода, значит таблицы еще нет.
Указываем данные таблицы:}
TMy.DatabaseName := ExtractFilePath(Application.ExeName);
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 присваиваются свойства (папка, где располагается таблица) и TableName (имя таблицы). В нашем случае таблица называется Proba.db, но вы можете усложнить программу, используя диалог OpenDialog, как в прошлом примере. В этом случае пользователь сможет выбрать не только имя таблицы, но и ее расположение. Далее таблица открывается, а оператор Exit досрочно завершает выполнение процедуры.
Если выполнение процедуры продолжается, значит, таблица не была найдена. В этом случае мы заполняем свойства компонента-таблицы , TableType и TableName необходимыми значениями.
Далее начинаем добавлять поля. Чтобы уменьшить код, мы используем оператор with. Напомню, что этот оператор создает блок кода, который относится к указанному в with объекту. Так, вместо
with TMy.FieldDefs do begin Clear;
можно было бы написать
TMy.FieldDefs.Clear;
В случае одиночного оператора это допустимо, но в случае множественных команд ссылаться в каждой строчке на объект будет утомительно. Свойство
Далее у нас идет метод with для каждого добавляемого поля.
В простейшем случае в блоке добавления нового поля требуется указать только два свойства объекта-поля: Name (имя поля) и DataType (тип поля). С именем все понятно, а что касается типа поля, то он определяется свойством класса TField. Чтобы получить подробную справку по возможным типам полей, установите курсор в редакторе кода на слове и нажмите <Ctrl+F1>, чтобы вызвать контекстную справку. В списке тем выберите ту тему, которая относится к классу TField, а в открывшейся справке щелкните по ссылке TFieldType (относится к Delphi 7, хотя возможно, имеется и в предыдущих версиях). Откроется страница с подробным описанием типов полей. При использовании этого метода следует сверяться, имеется ли выбранный тип поля в таблицах используемого формата.
Помимо этих двух свойств, при необходимости могут использоваться и другие:
True, то значения поля должны быть уникальными (не могут повторяться). В нашем примере такое свойство имеется у поля, которое мы будем использовать как первичный ключ.
Memo - полями.
После того, как в список полей были добавлены все необходимые поля, начинаем создание первичного ключа и индексов. Если за список полей отвечает свойство with для уменьшения кода. Для каждого индекса требуется указать по три свойства: Name (имя индекса), Fields (имя поля, по которому строится индекс) и Options (параметры индекса). Параметры индекса указаны в таблице 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 и приведен с небольшими доработками. Пример описывает практически все аспекты создания таблицы; по аналогии вы сможете создавать таблицы любой сложности.
Создание таблицы выполняется SQL -запросом SQL -запросов. Запрос, который возвращает набор данных и начинается оператором SELECT, выполняется простым открытием компонента-запроса. При этом выполняется запрос, который содержится в свойстве SQL компонента.
С модифицирующими командами дело обстоит иначе. Команда SQL, которая называется INSERT, DELETE, UPDATE относятся к SQL -запрос свойству SQL, а затем вызвать метод
Синтаксис создания таблицы несложный:
CREATE TABLE <TableName> (<ColumnName> <DataType> [<Size>], …)
Здесь, TableName - имя таблицы; ColumnName - имя столбца; - тип данных и SQL могут отличаться. Поэтому запрос, прекрасно работающий в одной СУБД, может вызвать ошибку в другой. Чтобы избежать ошибок, рекомендуется везде использовать типы ANSI, являющиеся стандартом SQL. Увы, но этих типов очень немного. Рассмотрим их:
| Тип | Описание |
|---|---|
| CHAR (CHARACTER) TEXT | Строковые типы данных. Обычно имеют размер до 255 символов. Требуют указания размера. |
| INT (INTEGER) | Целое число. Размер не указывается. |
| SMALLINT | Короткое целое. Размер не указывается. |
| FLOAT REAL | Вещественные числа. Размер не указывается. |
Как видите, многих типов просто нет. Вместо логического типа, вероятно, придется использовать строковый тип с размером в один символ; при этом 'Y' или '1' будут означать истину, а 'N' или '0' - ложь. Программисту придется самостоятельно делать проверку на это значение. Нет типа Memo. Нет автоинкрементного типа. Однако стандартные типы непременно будут корректно работать в любой СУБД.
Ниже приведен пример создания и открытия простой таблицы. В приложении должен иметься компонент ADOQuery, а если есть сетка и навигатор, то и DBSource. Для подключения к нужному провайдеру данных желательно использовать компонент TADOConnection. В его свойство ConnectionString нужно прописать строку подключения, например:
Provider=MSDASQL.1;Persist Security Info=False;Data Source=Файлы dBASE
Эту строку можно ввести программно, или создать подключение при проектировании (я так и сделал). Поставщик данных в примере оставлен по умолчанию - Microsoft OLE DB Provider for ODBC Drivers, а в качестве источника данных (вкладка "Подключение" редактора связей TADOConnection ) используются файлы dBase. Не следует забывать и про свойство LoginPrompt, которое следует переводить в False, чтобы программа не запрашивала имя пользователя и пароль при каждом подключении. А также нужно сразу открыть TADOConnection, установив его свойство Connected в True. В свойстве Connection компонента TADOQuery следует выбрать ADOConnection1.
Пример реализован, как событие нажатия на кнопку:
procedure TfMain.Button1Click(Sender: TObject);
var
s: String;
begin
{Создаем текст запроса}
s := 'CREATE TABLE MyTab(Key1 INT, Name CHAR(20), '+
' MyFloat FLOAT, MyDate DATE)';
{Создаем таблицу}
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add(s);
ADOQuery1.ExecSQL;
{Открываем таблицу}
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('SELECT * FROM MyTab');
ADOQuery1.Open;
Как видите, создается четыре поля - целый тип, строковый размером 20 символов, вещественный и тип Дата. Последний тип не входит в стандартное описание ANSI -типов, тем не менее, работает в большинстве СУБД. Можете также поэкспериментировать и с типом BOOLEAN (Логический).
Итак, в переменную s мы вносим строку записи SQL -запроса. Затем очищаем свойство SQL, на случай, если там уже имелся запрос. Далее этот запрос мы заносим в свойство SQL, и методом
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.