Лекция 29. Введение в базы данных
В этой лекции мы познакомимся с разработкой Баз Данных и изучим многие компоненты, обеспечивающие эту работу. Мы создадим приложение, отображающее данные из демонстрационной базы данных, научимся перемещаться по этой таблице, отображать большие строки и графику.
Базы Данных
Базы Данных – довольно большая и серьезная область программирования. Ни одно предприятие, фирма или организация сегодня не обходятся без программ, обеспечивающих работу с Базами Данных. Что же такое БД (База Данных)?
Представьте себе, например, библиотеку. В любой библиотеке ведется учет книг. Они регистрируются по автору, по содержанию, по издательству, по регистрационному номеру и так далее. Теперь представьте, что библиотекарю требуется создать отчет по количеству книг какого-то конкретного автора. Если вся регистрация хранится только в виде бумажных карточек, то перед библиотекарем стоит довольно непростая задача. Этот автор мог написать не одну книгу, а десяток, каждая книга в библиотеке может быть представлена в 5-10 экземплярах, и еще не факт, что все карточки лежат по порядку. Следовательно, библиотекарю придется перебрать все карточки, чтобы быть уверенным, что отчет правильный. А если этих карточек в библиотеке несколько миллионов?!
Здесь придут на помощь Базы Данных. База Данных – это механизм ввода, сохранения и выборки информации по различным параметрам. Допустим, сейчас библиотекарю велели создать отчет по количеству книг какого-то автора. Библиотекарь этот отчет создал. А на следующий день от него потребовали отчет по количеству книг какой-то тематики, например, отдельно по математике и по физике. Если книги не зарегистрированы в Базе Данных, то библиотекарю проще уволится, чем делать такую непомерную работу. А вот если есть компьютер, и если установлена специальная программа с базами данных, то создать подобный отчет – дело нескольких минут.
В старых языках программирования и СУБД (Систем Управления Базами Данных) под термином База Данных понимался файл, в котором данные хранятся в табличном представлении. Такими СУБД, например, являются dBase, Clipper, FoxPro и т.п.
Сейчас под понятием База Данных понимают, как правило, папку, в которой может храниться большое количество таблиц. Причем эти таблицы обычно связаны друг с другом, и случайное удаление одной таблицы может привести к разрушению всей БД.
Базы Данных могут быть трех различных типов:
Локальные БД. Это приложения, использующие механизм работы с БД, которые находятся на этом же компьютере и не используемые другими компьютерами.
Сетевые БД. По своей сути, они похожи на локальные. Сама База Данных может лежать на общесетевом диске или папке. При этом различные компьютеры в организации работают с этой общей базой данных, то есть все сотрудники организации имеют доступ к этой БД, вносят в нее данные, делают выборку и т.п.
Клиент – Серверные приложения. Это самая "продвинутая" модель работы с БД, и обычно используется в крупных предприятиях, в которых требуется обрабатывать большое количество данных. Суть этой модели в следующем. На главном компьютере (сервере) хранится общая База Данных. Кроме того, на нем запущена специальная программа – серверная СУБД, которая получает запросы от пользователей (клиентов), обрабатывает их и возвращает результат. Такая модель БД резко снижает нагрузку на сеть и увеличивает надежность сохранения данных.
Ведь в случае сетевой БД каждый клиент загружает свою копию общей БД, изменяет ее и затем прописывает изменения в общую БД. А в это же время другой клиент может прописывать свои изменения в эту же БД. Если программист не очень хорошо разработал доступ к БД и индексацию, то эту Базу Данных очень легко разрушить. В клиент – серверной модели это исключено. Серверная СУБД обрабатывает запросы по очереди, и возвращает каждому клиенту свой результат. Причем клиенту возвращается не вся таблица, а именно то, что он запрашивал, то есть, в зависимости от запроса клиента сервером была сформирована выборка из базы данных, которая и передана клиенту.
Изначально среда Delphi не ориентирована на работу с Базами Данных, однако реализация механизмов для работы с БД настолько разнообразна, что делает Delphi одним из самых мощных и удобных сред разработки приложений БД. Среди этих механизмов можно назвать BDE, ODBC, ADO и множество других. Более того, сторонние разработчики также разрабатывают механизмы для доступа к БД, так что Delphi на сегодняшний день может работать почти со всеми существующими форматами БД. На сегодняшний день у Delphi нет сколь-либо серьезных конкурентов для разработки программного обеспечения, использующего базы данных.
Однако для начала разберемся с терминологией.
Поле. Это столбец таблицы, общий для всех записей. Например, поле "Фамилия".
Запись. Строка таблицы, описывающая какой то объект. Например, какой то автор, у которого в поле "Фамилия" записано "Иванов", а в других полях – другая информация, относящаяся к этому автору.
Таблица. Набор записей в Базе Данных.
База Данных. Одна или несколько таблиц, связанных друг с другом.
Теперь представим себе саму таблицу.
Таблица 29.1. Пример таблицы авторов | ||||
№ | Фамилия | Имя | Отчество | Год рождения |
Лермонтов | Михаил | Юрьевич | ||
Пушкин | Александр | Сергеевич | ||
Толстой | Алексей | Константинович | ||
Толстой | Лев | Николаевич |
Здесь столбцы "№", "Фамилия" и так далее являются полями таблицы. Строки – "1", "2" и так далее – записями таблицы. Каждая запись соответствует информации об авторе. Причем обратите внимание, что строки под номером 3 и 4 имеют в поле "Фамилия" одинаковые данные, хотя они относятся к разным авторам. Для этого и было введено поле "№", чтобы однозначно идентифицировать автора. Такое поле называется ключевым, и именно по нему будет производится выборка данных. Таким образом, книги Л.Н. Толстого никогда не попадут в каталог автора А.К. Толстого.
Ключевым называется поле, которое позволяет однозначно идентифицировать запись.
Теперь представьте себе другую таблицу – каталог книг.
Таблица 29.2. Пример каталога книг | |||
№ | Автор | Наименование | Кол-во экз. |
Детство, Отрочество, Юность | |||
Война и мир | |||
Два гусара | |||
Сборник стихотворений |
Здесь поле "№" идентифицирует уже книгу, а не автора. А в поле "Автор" нет фамилии, имени и отчества, зато присутствует номер – идентификатор автора из первой таблицы. Теперь, если связать поле "Автор" этой таблицы с полем "№" предыдущей, мы можем в отчете получить полную информацию и о книге, и об авторе. Такие таблицы называются реляционными, то есть, связанными, и на сегодняшний день являются наиболее распространенными.
Индекс. Это способ фильтрации данных. Если мы сделаем поле "Фамилия" первой таблицы индексным, то сможем сортировать данные по этому полю, что обеспечивает более быстрый поиск данных. Например, если мы не знаем имени и отчества данных, то можем искать автора по фамилии. Указав в строке поиска "Толстой", мы получим книги всех авторов, носящих такую фамилию. Среди этого списка уже проще найти нужную информацию.
BDE
BDE (Borland Database Engine) – механизм доступа к базам данных, разработанный самой корпорацией Borland. Сейчас этот механизм считается устаревшим, однако он обеспечивает наиболее простой доступ к базам данных различных форматов, и начинать знакомство с БД удобней именно с него.
Создайте новое приложение. Мы продемонстрируем работу с БД и использование навигационных методов на демонстрационной таблице, поставляемой вместе с Delphi.
Назовите форму fMain, присвойте ей стиль bsDialog, и позицию по центру рабочего стола. В свойстве Caption напишите "БД Навигатор".
Далее, установите на форму панель GroupBox, в свойстве Caption которого укажите "Навигация".
На эту панель установите 4 кнопки, на которых укажите "|< Начало", "<< Назад", "Вперед >>" и "Конец >|". Это будут кнопки навигации – перемещения по таблице.
Ниже установите еще один GroupBox, в свойстве Caption которого напишите "Закладка". В таблице можно установить закладку на любой записи, а потом перескочить на нее из любого места. В этой панели мы будем добавлять закладку, удалять ее и перескакивать на нее.
Еще ниже поместите обычную панель, и удалите из нее текст. Установите на нее компонент Label, в свойстве Caption которого укажите "Позиция:". Теперь нужно, чтобы эта надпись всегда была посередине. Поэтому свойство AutoSize переведите в False, а свойствоAlignment – в taCenter. Растяните Label, чтобы она занимала почти всю ширину панели. Здесь вместе с надписью "Позиция:" будет выходить номер записи в таблице.
Теперь перейдите на вкладку Data Controls. Здесь содержатся компоненты отображения данных из БД. Найдите DBGrid и поместите ее на форму ниже панели. Сетка DBGrid очень похожа на сетку StringGrid, которую мы изучали, но предназначена для отображения и редактирования данных из таблицы БД. Сразу свойству ReadOnly (только для чтения) присвойте True, чтобы пользователь не мог испортить демонстрационную таблицу своим редактированием данных.
Чтобы получить доступ к БД, нужно еще кое что. На вкладке BDE есть компонент Table, который обеспечивает доступ к таблице средствами механизма BDE. Компонент не визуальный, поэтому можете бросить его на любое место, например, поверх сетки. Теперь в свойстве DatabaseName выберите демонстрационную базу данных DBDEMOS, которая поставляется вместе с Delphi. В свойстве TableName необходимо указать саму таблицу, к которой мы желаем получить доступ. Выберите там biolife.db.
Мы уже выбрали базу данных, то есть набор таблиц, и выбрали таблицу. Однако, чтобы вывести в сетку данные из таблицы, требуется компонент управления данными таблицы. Найдите на вкладке Data Access компонент DataSource. Этот компонент обеспечивает связь базы данных из таблицы Table с навигационными компонентами, такими, как DBGrid. Бросьте его рядом с Table. В свойстве DataSet компонента нужно указать, с какой же именно таблицей мы желаем работать. В данном примере у нас одна таблица, но ведь может быть и десяток! Выберите там Table1.
Теперь выделите сетку. Ей нужно указать, какой компонент будет управлять этой сеткой. В свойстве DataSource укажите наш DataSource1. Все, теперь мы сделали все приготовления. Единственное, что осталось сделать – открыть файл с таблицей. Выделите компонент Table1, и в свойстве Active укажите True. Этим самым мы заставим таблицу открыться.
Внимание! Работа с базой данных отличается от работы с файлами другого типа. Когда ваша программа работает, например, с текстовым файлом, она открывает этот файл, считывает его содержимое в оперативную память ПК и закрывает его. Пользователь работает уже не с файлом, а с его содержимым в оперативной памяти. Когда он дает команду сохранить результаты работы, программа вновь открывает файл и перезаписывает в него данные из оперативной памяти.
С базами данных все иначе. Как только вы открыли таблицу – указали True у компонента Table1 в свойстве Active, или же программно дали команду:
Table1.Active := True;
Или
Table1.Open;
то тем самым вы открыли файл. Файл будет открыт на протяжении всего сеанса, и все изменения данных будут немедленно сохраняться в нем! Приведенные выше команды открытия таблицы идентичны, вы можете пользоваться любым из этих способов.
Если вы все сделали правильно, то должны получить что-то вроде этого:
Рис. 29.1. Внешний вид приложения
Навигация
Для перемещения по записям таблицы существуют такие методы:
- First – переход на первую запись.
- Last – переход на последнюю запись.
- Next – переход на следующую запись.
- Prior – переход на предыдущую запись.
Создадим обработчики нажатия на кнопки в панели "Навигация". В обработчике кнопки "Начало" напишем
Table1.First;
В обработчике кнопки "Назад" напишем
Table1.Prior;
В обработчике кнопки "Вперед" напишем
Table1.Next;
В обработчике кнопки "Конец" напишем
Table1.Last;
Сохраните проект, откомпилируйте и посмотрите, как он работает. Указатель позиции должен перемещаться, когда пользователь нажимает на кнопки. Кроме того, перемещаться можно будет с помощью самой сетки DBGrid.
Типы данных
Листая таблицу, вы видели такие данные, как MEMO и GRAPHIC, а сами данные не отображались. Дело в том, что таблицы имеют разные типы данных. Бывают числовые типы, строковые, типы "Дата". Обычно, в строковый тип можно ввести текст длиной не более 255 символов. Если же вам требуется поместить в таблицу более длинный текст, например, аннотацию к книге, то можно воспользоваться типом MEMO. При этом создается новый файл, в котором хранится сам текст, а в таблице указана ссылка на этот текст. Длина текста в MEMO неограниченна. Для отображения MEMO потребуется специальный компонент.
Поле GRAPHIC хранит изображения – картинки, фотографии. Для их отображения также нужен специальный компонент.
Улучшим наш пример, создав форму, в которой, как в карточке, мы сможем видеть все данные текущей записи. Однако для начала познакомимся с DataModule. Это модуль, который не имеет формы. Его очень удобно использовать в многооконных проектах, где окна работают с общими данными. Для нас общие данные – это компоненты Table и DataSource.
Прежде всего, закройте таблицу, указав False в ее свойстве Active.
Выберите команду File-> New -> Data Module. У вас появится новое окошко, но это не форма. Измените имя этого окна на fDM, чтобы не нужно было писать длинного обращения к компонентам. Теперь вернитесь на главную форму и выделите компоненты Table иDataSource. Выберите команду Edit -> Cut (вырезать). Затем перейдите в окно fDM, и выберите команду Edit -> Paste (вставить). Если у вас эти компоненты были в нижней части формы, то они могут оказаться вне зоны видимости окна fDM. Это не страшно – прокрутите окно, либо увеличьте его размеры, чтобы видеть компоненты, а затем перетащите их в верхнюю часть окна. После чего можно уменьшить размеры fDM. Сохраните окно в модуле DM.pas.
Далее переходим на главную форму. Эта форма должна видеть окно fDM, чтобы работать с компонентами, установленными в нем, поэтому выберите команду File -> Use -> Unit и там выберите DM.
Теперь выделите сетку. В ее свойстве DataSource нужно выбрать наш DataSource, который выглядит уже как fDM.DataSource1. Теперь откройте таблицу, указав True в ее свойстве Active. Как видите, данные по-прежнему отображаются, хотя компоненты доступа хранятся в другом модуле.
Теперь мы готовы к тому, чтобы создать новое окно для просмотра данных. Создайте новую форму, назовите ее fViewer, и сохраните в модуле Viewer. Не забудьте выбрать команду Use -> Unit и там – DM, ведь новая форма также будет работать с компонентами Tableи DataSource. В свойстве Caption напишите "Карточка".
Теперь перейдите на вкладку DataControls. Найдите там компонент DBEdit. От обычного Edit он отличается тем, что поддерживает связь с базой данных. Бросьте на форму, один под другим, 6 таких компонентов. Ниже бросьте DBMemo, а справа от DBEdit – DBImage. У вас должна получится форма примерно такого вида:
Рис. 29.2. Внешний вид формы карточки
Слева от компонентов доступа к данным установите соответствующее количество Label, и пропишите пояснения к полям, как на картинке выше.
Выделите все компоненты доступа (только все DBEdit, DBMemo и DBImage). Свойство ReadOnly у них установите в True, чтобы пользователь не испортил данные демонстрационной таблицы. Далее, в свойстве DataSource выделенных компонентов нужно выбрать нашfDM.DataSource1. Теперь придется с каждым компонентом работать отдельно. Выделите верхний DBEdit, и в свойстве DataField (поле) выберите "Species No". Все компоненты DBEdit, сверху – вниз, должны быть привязаны к следующим полям:
Species No
Category
Common_Name
Species Name
Length (cm)
Length_In
Компонент DBMemo должен быть привязан к полю Notes, а компонент DBImage – к полю Graphic. Кстати, у DBMemo установите вертикальную полосу прокрутки, чтобы можно было листать слишком большие примечания.
Собственно, карточка готова. Осталось только вызывать ее из главной формы. Если вы еще не выполнили для главной формы команду File -> Use Unit, и не выбрали там модуль Viewer, то сделайте это сейчас. Затем выделите сетку и сгенерируйте для нее событиеonDblClick, где пропишите вызов окна – карточки:
fViewer.ShowModal;
Теперь пользователь, щелкнув дважды по какой либо записи, вызовет карточку, где будут отражены данные этой записи. Однако перед компиляцией проекта нужно кое-что исправить. Мы запрограммировали наши 4 кнопки перемещения, когда еще компонент Tableбыл на главной форме. Однако теперь он в окне DM, поэтому добавьте fDM перед обращением к таблице во всех 4 кнопках, как в примере:
fDM.Table1.First;
Сохраните проект, скомпилируйте, и посмотрите, как он работает. На следующей лекции мы продолжим работу над этим проектом.