73949

Основы работы с базами данных: создание псевдонима, создание таблицы, изменение структуры таблицы

Лекция

Информатика, кибернетика и программирование

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

Русский

2014-12-23

308 KB

0 чел.

Лекция 9.  Основы работы с базами данных: создание

псевдонима, создание таблицы, изменение структуры таблицы

4.1. Основные понятия

На сегодня среда Delphi является одним из самых распространенных средств создания приложений баз данных.

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

Системы управления базами данных (СУБД) - это программные средства, предназначенные для создания, наполнения, обновления и удаления баз данных.

Информация в БД хранится в виде совокупности связанных таблиц. Каждая таблица представляет собой совокупность строк и столбцов. Строки соответствуют экземпляру объекта, конкретному событию или явлению. Столбцы таблицы - атрибутам (признакам, характеристикам, параметрам) объекта, события, явления. В терминах БД столбцы таблицы называются полями, а строки - записями.

Базы данных, между отдельными таблицами которых существуют связи, называются реляционными. Реляционная модель была предложена в 1970-е годы Тедом Коддом.

Связанные отношениями таблицы взаимодействуют по принципу главная-подчиненная. Главную таблицу называют родительской, подчиненную дочерней. Одна и та же таблица может быть главной по отношению к одной таблице БД и дочерней по отношению к другой таблице.

4.2. Создание псевдонима базы данных

При работе с таблицами локальных БД (в число которых входят таблицы СУБД Paradox и dBase) сама база данных размещается на диске и хранится в виде набора файлов. Для хранения одной таблицы создается отдельный файл. Обращение к БД из утилит и программы осуществляется по псевдониму базы данных. Псевдоним должен быть зарегистрирован в файле конфигурации конкретного компьютера при помощи утилиты BDE Administrator. Для присвоения псевдонима необходимо запустить утилиту BDE Administrator (пункт меню Пуск/Программы/Borland Delphi 5/ BDE Administrator). В главном меню утилиты необходимо выбрать элемент Object | New. В появившемся окне задается тип создаваемой БД - Standard.

После этого в левом поле окна администратора БД (рис. 4.1) появится строка с именем STANDARD1, стандартным именем для псевдонима. Это имя целесообразно изменить на имя псевдонима создаваемой БД.

В правом поле указаны параметры БД. Необходимо изменить параметр PATH, который указывает путь, в котором располагается БД.

  Рис. 4.1

Далее необходимо запомнить определение псевдонима. Для этого в левом окне администратора БД необходимо щелкнуть по имени псевдонима правой кнопкой мыши и в коротком меню выбрать опцию Apply и подтвердить выбор в появившемся диалоговом окне. На этом создание псевдонима БД завершается.

4.3. Создание таблиц базы данных

Для создания таблицы необходимо сформировать ее структуру, т.е. задать совокупность полей таблицы и определить их типы. Для создания таблиц базы данных необходимо запустить утилиту Database Desktop (DBD). После запуска утилиты необходимо установить псевдоним той базы данных, с таблицами которой предполагается работать. Для этого нужно выбрать элемент главного меню File | Working Directory и в выпадающем списке Aliases выбрать имя псевдонима, после чего нажать ОК. Database Desktop – мощное средство, обеспечивающее различные способы работы с таблицами БД. Рассмотрим лишь некоторые возможности. 

4.3.1. Объявление полей

Для создания таблицы БД нужно выбрать элемент главного меню File | New | Table. В появившемся окне Create Table задать тип создаваемой таблицы (по умолчанию Paradox 7) и нажать ОК. После этого появится окно определения структуры таблицы БД (рис. 4.2)

Рис. 4.2

Каждая строка соответствует полю таблицы. Назначения столбцов:

  •  Field Name – имя поля; необходимо для обеспечения доступа к полю. Имена полей в таблице должны быть уникальны.
  •  Type – тип поля. Тип определяет совокупность операций, которые можно производить со значениями поля.
  •  Size – размер поля (для строковых полей).
  •  Key – содержит звездочку «*», если поле входит в состав первичного ключа. Первичный ключ состоит из одного поля или нескольких полей, однозначно идентифицирующих запись. Это означает, что в таблице не может быть двух записей с одними и теми же значениями ключевых полей. Ключ может состоять из любого количества подряд идущих полей, начиная с первого. Подробнее способы использования ключевых полей рассматриваются в лекции 6.

Типы полей, используемых в СУБД Paradox, представлены в Tаблице1:

Таблица 1

Тип поля и обозначение

Хранимые значения

Alpha

A

Символьные значения длиной до 255 символов

Number

N

Числовые значения с плавающей точкой в диапазоне –10307 … +10308. Точность до 15 значащих цифр

Money

$

Аналогичен типу Number, но предназначен для хранения денежных сумм. Число знаков после запятой по умолчанию равно двум. При показе значения выводится знак денежной единицы

Short

S

Целочисленные значения в диапазоне

-32768 … 32767

LongInteger

I

Целочисленные значения в диапазоне

-2147483648 … 2147483647

BCD

#

Числовые значения, в том числе и дробные, в двоично-десятичном формате

Date

D

Значения даты

Time

T

Значения времени

Timestamp

@

Значения даты и времени

Memo

M

Строковые значения длиной более 255 символов. Максимальная длина не ограничена

Formatted Memo

F

Форматированный текст произвольной длины, в котором отдельные фрагменты текста могут использовать разные шрифты, цвета и стили

Graphic Fields

G

Графические изображения в форматах BMP, PCX, TIF, GIF, EPS, которые при хранении преобразуются в формат BMP. Хранятся отдельно от основной таблицы БД

OLE

O

Информация в форматах, поддерживаемых технологией OLE

Logical

L

Логические значения (True и False)

Autoincrement

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

Binary

B

Двоичные значения произвольной длины. Хранятся отдельно от основной таблицы

Bytes

Y

Произвольные двоичные значения. Хранятся вместе с таблицей БД

Для любого поля можно определить требование обязательного его заполнения значением. В этом случае для поля включается переключатель Required Field.

Строки ввода, расположенные ниже, служат для наложения ограничений на значение поля:

  •  Minimum value – определяет минимальное значение поля;
  •  Maximum value – определяет максимальное значение поля;
  •  Default value - определяет значение поля по умолчанию;
  •  

Pictureопределяет шаблон изображения поля.

Рис. 4.3

На рис. 4.3 приведен пример использования ключевого поля при создании таблицы. В данном примере ключевым полем будет являться Идентификационный номер (поле Key отмечено *). Выбор этого поля ключевым определяется тем, что в данной таблице не должно быть двух записей имеющих одинаковые идентификационные номера.

4.3.2. Изменение языкового драйвера

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

Для этого необходимо в комбинированном списке Table Properties щелкнуть элементу Table Language, после чего щелкнуть по кнопке Modify  и  в появившемся  окне Table Language (рис. 4.4.) указать драйвер Pdox ANSI Cyrillic или Paradox Cуrr 866. 

                                               Рис. 4.4

4.3.3. Определение индексов

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

Для создания дополнительных, вторичных, индексов в комбинированном списке Table Properties необходимо выбрать элемент Secondary Indexes. Для того чтобы определить новый индекс, необходимо нажать кнопку Define. В появившемся диалоговом окне (рис. 4.5) в поле Fields содержится список всех полей таблицы. Окно Indexed Fields предназна-чено для хранения полей, входящих в создаваемый индекс. Нужные поля необходимо перенести в это окно с помощью стрелки «».                            

                     Рис. 4.5

В появившемся диалоговом окне задается имя индекса. Не рекомендуется составлять название индекса только из имен полей.

4.3.4. Определение ссылочной целостности между таблицами

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

Для установки ссылочной целостности в списке Table Properties выбирают элемент Refrential Integrity и нажимают Define. В появившемся диалоговом окне (рис. 4.6) в списке Fields показаны поля выбранной таблицы, а в списке Tables – остальные таблицы базы данных.

Сначала указывают поле связи для выбранной таблицы. Для этого в списке Fields выбирают поле и нажимают кнопку с изображением стрелки вправо. Название поля будет записано в поле Child Fields. Затем в поле Tables выбирают другую таблицу и нажимают кнопку с изображением стрелки влево.

Рис. 4.6

В поле Parents Key будут показаны поля из первичного ключа таблицы. Переключатели Update rules определяют вид каскадных воздействий на первую таблицу при изменении значения поля связи во второй таблице или при удалении в ней записи:

  •  Cascade – разрешены каскадные изменения (изменения или удаления в записях дочерней таблицы при одновременном изменении (удалении) записи родительской таблицы) и удаления подчиненных записей в дочерней таблице;
  •  Ptohibit - запрещены изменения полей связи или удаление записи в родительской таблице, если для данной записи есть связанные записи в дочерней таблице.

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

4.3.5. Изменение структуры таблицы

Структуру созданной таблицы можно изменить. Для этого необходимо выбрать элемент меню Tools | Utilities | Restructure, выбрать таблицу и произвести необходимые изменения в структуре таблицы. Можно добавлять, удалять поля, изменять их типы и имена. В некоторых случаях система попросит подтвердить выполнение действий.

4.4. Открытие и сохранение таблицы

Для изменения данных, хранящихся в таблице, таблицу необходимо «открыть». Открытие таблицы происходит с помощью подменю File | Open. Внесение изменений (добавление/удаление записей, изменение значений полей конкретных записей и т.д.) происходит только в режиме редактирования. Для перехода в режим редактирования необходимо нажать клавишу F9. Сохранение изменений в таблице происходит по выбору пунктов меню File | Save или File | SaveAs. Перед сохранением изменений необходимо выйти из режима редактирования, повторно нажав клавишу F9.

4.5. Дополнительные утилиты

Рассмотрим некоторые дополнительные возможности, которые среда Database Desktop предоставляет для работы с таблицами. Эти возможности доступны через пункт меню Tools | Utilities:

Add – добавить записи из одной таблицы в другую (структуры должны совпадать);

Copy – копировать одну таблицу в другую;

Delete – удалить таблицу;

Empty – опустошить таблицу (удалить все записи);

Info Structure – показать структуру таблицы;

Rename – переименовать таблицу;

Sort – отсортировать таблицу по значениям каких-либо полей;

Restructure – изменить структуру таблицы;

Subtract – удалить из таблицы записи, совпадающие с записями другой таблицы (записи должны совпадать).


Лекция 5. Основные классы, обеспечивающие доступ к таблицам БД: назначение, свойства, методы

5.1. Взаимодействие классов, обеспечивающих доступ к таблицам

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

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

Набор данных БД (физическая таблица БД или результат запроса) Объект класса TTable или TQuery  Объект класса TDataSource  Объект класса TDBGrid или класса TDBЕdit

Поясним предложенную схему. Данные из таблицы БД или результат запроса по таблицам БД представляются объектами классов TTable или TQuery соответственно. Классы TTable и TQuery связываются с объектом класса TDataSource, а уже объект класса TDataSource непосредственно связывается с визуальными компонентами DBGrid или DBЕdit, обеспечивающими отображение данных и возможность внесения изменений. На рис. 5.1 представлена форма с необходимыми компонентами для представления информации из одной таблицы БД.

Рис. 5.1

Рассмотрим подробнее атрибуты, методы и события, связанные с данными классами.

  1.  Класс TTable обеспечивает доступ к конкретной таблице БД в целом. Это наиболее важный и сложный класс и будет далее рассмотрен подробно.

  1.  Класс TDataSource обеспечивает связь визуальных компонентов (TDBGrid или TDBЕdit) со множеством данных БД. Связь осуществляется через класс TDataSet, поэтому основной атрибут класса  DataSet, в котором задается имя объекта, непосредственно связанного с набором данных БД. Класс TDataSet – предок класса TTable, объекты которого представляют конкретные таблицы БД. Для доступа к результатам запросов (см. лекцию 7) используются объекты другого наследника TDataSet – класса TQuery. Наиболее интересное событие класса TDataSource – OnDataChange, которое происходит при изменении связанных с объектом данных, позволяет их отслеживать, обрабатывать, сообщать о них пользователю.

  1.  Класс TDBGrid («сетка») обеспечивает возможность отображения и редактирования данных в виде таблицы, строки которой соответствуют записям таблицы БД, а столбцы – полям записи. Свойство DataSource содержит имя компонента-источника TDataSource, который ссылается на соответствующую таблицу. Изменяя значение свойства DataSource во время выполнения, можно использовать один и тот же компонент TDBGrid для показа содержимого различных наборов данных.

Для определения состава столбцов в TDBGrid используется редактор столбцов (Columns Editor). В окне редактора устанавливаются значения свойств объектов-столбцов. Текущие значения свойств определяют способ отображения столбцов в сетке. Если в процессе выполнения приложения программно изменять то или иное свойство столбца, то эти изменения немедленно отобразятся. Например, в ходе выполнения можно менять ширину столбца (свойство DisplayWidth связанного со столбцом объекта TField), его видимость (Visible), возможность редактирования значения столбца (ReadOnly), порядковый номер (Index), заголовок столбца (DisplayLabel).

К основным событиям данного класса можно отнести следующие: OnCellClick – возникает при щелчке мыши на ячейке; OnDblClick – возникает при двойном щелчке мыши; OnTitleClick  возникает при щелчке по заголовку; OnColEnter – возникает сразу после того, как ячейка становится активной («получает фокус»); OnColExit – возникает перед тем, как ячейка перестает быть активной («теряет фокус»).

Стандартно реализованы следующие способы работы пользователя с информацией из таблиц.

- Пользователь может работать в каждый момент времени только с одним полем одной записи таблицы. Эта запись называется текущей и помечена в левом столбце значком ►. Ячейка таблицы, с которой работает пользователь в данный момент времени, называется активной и выделяется цветом.

- Переход вверх и вниз между записями и по текущей записи осуществляется соответствующими стрелками, клавишей Tab или с помощью курсора мыши. При переходе вниз от последней записи автоматически создается новая запись, помечаемая значком *.

- При внесении изменений в текущее поля происходит переход в режим редактирования.

- Внесение изменений в таблицу БД и выход из режима редактирования происходит после перехода к другой записи. Отказаться от изменений и выйти из режима редактирования можно по клавише Esc.

  •  Удалить текущую запись можно, нажав одновременно клавиши Ctrl и Del.

  1.  Класс TDBЕdit обеспечивает возможность отображения и редактирования одного поля текущей записи таблицы. Функции данного класса аналогичны функциям класса TEdit, но источником данных и их приемником в этом случае служит поле таблицы. Свойство DataSource содержит имя компонента-источника, который ссылается на соответствующую таблицу, а свойство DataField – имя соответствующего поля. При вводе значения в компонент автоматически отслеживается его совместимость с типом поля таблицы. Ввод неправильных значений блокируется, и выдается сообщение об ошибке. Например, произойдет ошибка, если в компонент, связанный с полем числового типа или типа дата-время, попытаться ввести произвольный текст.

Основные свойства, методы и события этого класса аналогичны свойствам, методам и событиям класса TEdit с учетом специфики класса TDBЕdit.

5. Класс TDBNavigator позволяет осуществлять навигацию по записям таблицы, переводить таблицу в состояние вставки, изменения, добавления записи, запоминать изменения. Свойство DataSource содержит имя компонента-источника, который ссылается на соответствующую таблицу. Свойство VisibleButtons состоит из множества свойств с логическими значениеми, каждое из которых соответствует некоторой кнопке навигатора: nbFirst – перейти к первой записи; nbPrior – перейти к предыдущей записи; nbNext – перейти к следующей и т.д. Кнопка отображается на Навигаторе, если соответствующее ей свойство имеет значение Тrue. Наиболее часто используется событие OnClick, которое возникает при щелчке мыши на кнопке Навигатора.

5.2. Классы TField и TTable: основное назначение и свойства

5.2.1. Класс TField: основное назначение и свойства

Класс TTable обеспечивает доступ к конкретной таблице БД в целом, а класс TField обеспечивает программисту разнообразные возможности для работы с составляющими таблицы  полями:

  •  изменение значения поля текущей записи;
  •  преобразование значения поля текущей записи от одного типа данных к другому;
  •  проверка данных, вводимых пользователем в поле таблицы (для проверки ошибок ввода);
  •  определение способов отображения или редактирования полей таблицы;
  •  определение вычисляемых (calculated) полей на основе реальных полей БД;
  •  определение связанных (lookup) полей (полей из другой таблицы БД).

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

AsBoolean, AsCurrency, AsDateTime, AsFloat, AsInteger, AsString, AsVariant - позволяют считывать значение из поля текущей записи или записывать в него значение с учетом указанных преобразований.

DataSet – связанная таблица или запрос.

EditMask – маска для форматирования значения поля.

FieldName – имя поля.

FieldNo – порядковый номер поля в связанной таблице или запросе.

LookupDataSet, LookupKeyFields LookupResultFields – только для связанных полей: таблица-справочник, список полей-ключей исходной таблицы, список полей-результатов таблицы-справочника (см. Лекция 6).

ReadOnly - определяет, можно ли поле редактировать (False) или нет (True).

Value – позволяет считывать значение из поля текущей записи или записывать в него значение.

Visible – определяет, можно отображать поле в визуальных компонентах (True) или нет (False).

К основным методам, знание которых необходимо при первоначальном изучении, относятся: аssign – копирует значения из поля связанного множества данных в свойство Value; сlear – очищает значение поля.

Из событий, связанных с классом TField, выделим событие OnChange, возникающее после изменения значения поля.

5.2.2. Класс TТable: основное назначение

Класс TTable наследует классу TDataSet и обеспечивает связь таблиц БД через объекты класса TDataSource с визуальными компонентами.

Объект класса представляет совокупность записей (набор данных, НД) из определенной таблицы БД. Класс выполняет следующие «роли»:

  •  открытие и закрытие доступа к физической таблице БД;
  •  отбор записей по заданному критерию (установка фильтров);
  •  поиск записей;
  •  установка индексов для последовательности перехода по таблице БД и ускорения поиска;
  •  «навигация» по таблице БД;
  •  добавление, удаление записей;
  •  доступ к значениям полей текущей записи таблицы;
  •  обеспечение связи с другими таблицами БД.

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

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

В дальнейшем будем предполагать, что компонент Table1 представляет таблицу с полями БД: Name (A), Name_Subject (A) и Mark (S), представляющую таблицу оценок по различным предметам, полученных студентами во время сдачи экзаменов в сессию.

5.2.3. Основные свойства класса TTable

Рассмотрим некоторые свойства, необходимые для реализации простейших приложений. Некоторые из них доступны только в режиме программирования (они помечены индексом p), остальные доступны и в режиме разработки (в Инспекторе Объектов), и в режиме программирования. Значения, доступные в Инспекторе Объектов, могут быть изменены программно. Если эти значения программно не изменяются, то они сохраняются в процессе выполнения приложения. После завершения работы приложения восстанавливаются значения, заданные в Инспекторе Объектов.

Active – открывает (True) или закрывает (False) доступ к НД.

DatabaseName – содержит псевдоним БД.

TableName – имя представляемой компонентом таблицы БД, устанавливается в режиме разработки для обеспечения связи с таблицей.

ReadOnly - определяет, позволяет ли объект класса TTable только считывать данные из таблицы БД или также и редактировать их. В первом случае свойство имеет значение True, а во втором  False.

Filter, Filtered – обеспечивают установку фильтра на физическую таблицу БД с целью отбора записей, удовлетворяющих заданным условиям. Filtered определяет установку критерия (True), определенного в Filter, или отменяет фильтр (False). Значение свойства Filter – строка следующей структуры: <имя поля><знак сравнения><значение>.

Например, для отбора из таблицы только таких записей, значения поля Mark в которых больше 4, необходимо выполнить следующие операторы:

Table1.Filtered:=true;

Table1.Filter:='Mark>4';

Для отмены фильтра достаточно выполнить оператор:

Table1.Filtered:=false;

Строковые конcтанты заключаются в апострофы, при этом используется соглашение, что два апострофа подряд внутри строки задают апостроф как символ. Например, оператор Table1.Filter:='Name='''+ 'Иванов''' задаст как критерий отбора условие: Name='Иванов'.

В критерии отбора можно задавать и несколько условий, соединенных логическими операторами: Table1.Filter:='Mark>4 and Name='''+'Иванов'''.

Fields p – позволяет обратиться к значениям полей НД по номеру поля.

Свойство Fields имеет тип TFields, который представляет собой массив значений типа TField. Поля нумеруются начиная с 0, в порядке их следования в таблице БД, если для компонента Table не созданы поля специально (см. далее Доступ к значениям полей по имени).

Например, для вывода на экран значения поля Name текущей записи можно воспользоваться следующим оператором:

ShowMessage(Table1.Fields.Fields[0].AsString) или, короче,

ShowMessage(Table1.Fields[0].AsString).

Обозначение свойства Fields можно опускать.

IndexName – содержит имя используемого индексного файла для таблицы БД и рассматривается далее (см. Лекция 6).

Recnop - определяет номер текущей записи таблицы. Значение свойства доступно только при выполнении приложения и только для считывания. Свойство не учитывает установленный на таблицу фильтр. Следующий оператор в окне сообщений выводит номер текущей записи для таблицы БД, представленной компонентом с именем Table1:

ShowMessage(IntToStr(Table1.Recno)).

RecordCountp – определяет количество записей в таблице. Значение свойства доступно только при выполнении приложения и только для считывания. Свойство учитывает установленный на таблицу фильтр, т.е. вычисляет количество отфильтрованных записей. Следующий оператор в окне сообщений выводит количество записи в таблице БД, представленной компонентом с именем Table1:

ShowMessage(IntToStr(Table1.RecordCount)).

Свойства MasterFields, MasterSource необходимы для реализации одновременного отображения нескольких таблиц и будут рассмотрены позднее в Лекции 6.

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

Eofp – принимает значение True, когда открывается пустая таблица, осуществляется непосредственный переход к последней записи таблицы или попытка перейти от последней записи таблицы к следующей, в остальных случаях имеет значение False.

Эти свойства обычно используются для просмотра записей таблицы от последней к первой или обратно.

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

//Открытие таблицы

Table1.Active:=true;

while not Table1.Eof do

// Пока не дошли до конца таблицы

 begin

   <доступ к текущей записи таблицы>;

   <переход к очередной записи таблицы>

 end;

5.2.4. Основные методы класса TTable

Рассмотрим основные методы класса TTable, необходимые для реализации простейших приложений, и способы их использования.

1) Доступ к таблице БД

Связь между компонентом и реальной таблицей БД обеспечивается методом Open. Доступ к записям таблицы БД через связанный с таблицей компонент возможен только после выполнения этого метода.

Open – открывает доступ к таблице БД через компонент (свойство Active таблицы получает значение True). Обращение имеет вид: Table1.Open.

Close – закрывает доступ к таблице БД через компонент (свойство Active таблицы получает значение False).

2) Перемещение по записям таблицы

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

First – текущей становится первая запись таблицы;

Last – текущей становится последняя запись таблицы;

Next – текущей становится следующая запись таблицы;

Prior – текущей становится предыдущая запись таблицы.

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

Table1.First;

while not Table1.Eof do    // Пока не дошли до конца таблицы

 begin

   <доступ к текущей записи таблицы>;

   // Переход к очередной записи таблицы

   Table1.Next

 end;

Последовательность переходов осуществляется в соответствии с первичным или установленным вторичным индексом (см. Лекция 6).

3) Режим редактирования таблицы

Для внесения изменений в таблицу БД, связанную с компонентом, используется метод Edit: Table1.Edit. После этого становится возможным изменение значений полей текущей записи таблицы БД. Такой режим называется режимом редактирования. Для выхода из режима редактирования используются методы Post (выход из режима редактирования с внесением произведенных изменений в текущую запись таблицы) или Cancel (выход из режима редактирования без внесения произведенных изменений). Для перехода к другой записи таблицы необходимо выйти из режима редактирования!

4) Доступ к значениям полей по имени

С помощью метода FieldByName компонента Table возможен доступ к полю физической таблицы по имени. Этот способ часто бывает удобнее, чем через свойство Fields, т.к. позволяет не задумываться о последовательности полей в таблице.

Заголовок метода имеет вид:

function FieldByName(const FieldName: string): TField;

В параметре FieldName задается имя поля таблицы БД, к которому происходит доступ.

Метод возвращает значение класса TField.

Пусть таблица БД, представляемая компонентом Table1, содержит поля: F_Date (D) и F_Text (A), а переменные PDate и PText содержат введенные пользователем новые значения полей.

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

Table1.Edit;

//Изменение значений полей

Table1.FieldByName('F_Date').AsDateTime:=PDate;

Table1.FieldByName('F_Text').AsString:=PText;

if MessageDlg('Внести изменения?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then

//пользователь подтверждает внесение изменений в таблицу БД

 begin

   Table1.Post;

   ShowMessage('Изменения внесены!')

 end

else

//пользователь отменяет внесение изменений в таблицу БД

 begin

   Table1.Cancel;

   ShowMessage('Изменения отменены!')

 end;

После выполнения метода Post изменения будут внесены в текущую запись таблицы БД и «откат» (возврат предыдущих значений) будет невозможен. После выполнения метода Cancel поля текущей записи таблицы БД получат прежние значения.

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

Table1.First;

while not Table1.Eof do

// Пока не дошли до конца таблицы

 begin

//Доступ к значениям полей текущей записи таблицы

   ShowMessage('Дата: '+Table1.FieldByName('F_Date').AsString+' 'Текст: '+ Table1.FieldByName('F_Text').Value);

// Переход к очередной записи таблицы

   Table1.Next

 end;

Существует еще один способ программного доступа к значениям полей текущей записи: по физической таблице БД сформировать массив полей и связать его с компонентом Table1. Для этого необходимо щелкнуть дважды по компоненту Table1, нажать правую кнопку мыши и в меню выбрать пункт меню Add all fields.

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

ShowMessage('Дата: '+Table1F_Date.AsString+' 'Текст: '+ Table1F_Text.Value);

В некоторых ситуациях такой способ доступа удобен, а в других просто необходим (их мы рассмотрим далее).

5) Добавление, удаление записей

Добавление записей в таблицу БД через компонент Table происходит с помощью методов:

Append – добавляет пустую запись в конец таблицы;

Insert – вставляет пустую запись перед текущей записью таблицы.

Оба метода автоматически включают режим редактирования новой записи. Для выхода из режима редактирования необходимо выполнить один из двух рассмотренных ранее методов (Post или Cancel).

Например,

Table1.Append;

<внесение данных в поля новой записи>;

Table1.Post;

Порядок расположения новой записи в таблице зависит от связанных с таблицей индексов (см. Лекция 6).

Удаление текущей записи из таблицы БД через компонент Table происходит с помощью метода Delete: Table1.Delete.

IsEmpty – проверяет, содержит ли таблица, по крайней мере, одну запись, возвращает значение Тrue при наличие записей и False в противном случае.

Например:

if Table1. IsEmpty then

 ShowMessage('Таблица не содержит данных!')

else

...<обработка данных таблицы>


Лекция 6. Индексирование таблиц. Поиск в таблицах. Вычисляемые и связанные поля

6.1. Индексирование таблиц

Каждая таблица СУБД Paradox может иметь один первичный индекс (Primary Key), его называют также ключом. Первичный индекс может состоять из одного первого поля или нескольких подряд идущих полей, начиная с первого. Для формирования первичного индекса необходимо при создании таблицы в Database Desktop для соответствующих полей в столбце Key поставить знак «*» (например, с помощью клавиши «пробел»). Первичный индекс выполняет несколько функций.

1) Первичный индекс задает сортировку записей таблицы: порядок следования записей в таблице определяется по значениям первого ключевого поля, для записей с одинаковыми значениями первого ключевого поля – по значениям второго ключевого поля и т.д. Рассмотрим, например, таблицу со следующей структурой

Наименование поля

Тип

Ключ

Примечание, поясняющее назначение поля

Course_Stud

S

*

Текущий курс студента

Name_Stud

A 20

*

ФИО студента

Date_Sem

D

*

Дата завершения сессии

Name_Subj

A 20

*

Наименование дисциплины

Date_Exam

D

Дата сдачи экзамена

Mark

S

Оценка

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

2) Первичный индекс позволяет эффективно, используя специальные алгоритмы поиска в отсортированных наборах данных, осуществлять поиск записей в таблице по значениям ключевых полей (см. Поиск, функции FindKey, Locate).

3) Первичный индекс позволяет при необходимости поддерживать целостность и однозначность данных таблицы БД: ключевые поля двух записей таблицы не могут содержать одинаковые значения! В данной таблице может храниться для каждого студента для каждой сессии только одна оценка по каждой дисциплине. При попытке внести в таблицу еще оценку будет выведено сообщение Key violation (нарушение уникальности ключа). В этом случае необходимо либо отменить изменения, либо изменить вводимые данные. Принимать решение о ключевых полях должен программист, основываясь на функциях разрабатываемой им системы. Если, например, необходимо в данной таблице хранить информацию обо всех «попытках» студента сдать экзамены, то ключевым должно быть и поле Date_Exam.

4) Первичный индекс позволяет поддерживать связь один-ко-многим между таблицами. Эта связь позволяет эффективно работать одновременно с двумя связанными содержательно таблицами (см. Мультиформы). Наличие ключевых полей позволяет однозначно определять запись главной таблицы (master table), с которой могут быть связано несколько записей подчиненной таблицы (detailed table).

Первичный индекс в СУБД Paradox представляется файлом с именем <имя таблицы>. px.

Каждая таблица СУБД Paradox может иметь несколько вторичных индексов. Вторичный индекс может также состоять из одного или нескольких полей (вне зависимости от порядка полей в таблице БД). Вторичный индекс выполняет функции сортировки, повышения скорости поиска записей по указанным значениям полей, может поддерживать уникальность записей с индексными полями.

Вторичные индексы создаются в Database Desktop. Для создания вторичного индекса необходимо в режиме создания или переструктурирования таблицы:

  •  

выбрать в окне Table properties (свойства таблицы) значение Secondary Indexes (вторичные индексы);

  •  нажать кнопку Define (определить);
  •  выбрать в появившемся окне (рис. 6.1)  поля таблицы БД, участвующие в формировании индекса, и определить их порядок;
  •  задать при необходимости опции Unique (уникальность значений полей индекса), Maintained (автоматическое перестраивание индекса), Case sensitive (учет регистра), Descending (убывающий порядок сортировки);           Рис. 6.1
  •  ввести имя индекса;
  •  сохранить таблицу.

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

<имя таблицы>.IndexName:=<строка, содержащая имя индекса>.

Например, Table1.IndexName:='Ind_Mark' (в предположении, что для таблицы БД, связанной с компонентом Table1, существует вторичный индекс с именем Ind_Mark). Отменить программно установленный вторичный индекс можно с помощью оператора <имя таблицы>.IndexName:= ''.

Если вторичный индекс не установлен, для сортировки и поиска используется первичный индекс.

6.2. Поиск записей

6.2.1. FindKey – ищет в таблице по первичному или вторичному индексам запись, значения полей которой соответствуют значениям, заданным в параметрах. Заголовок метода имеет вид:

function FindKey(const KeyValues: <массив констант или переменных>): Boolean;

В параметре KeyValues через запятую перечисляются константы или переменные, определяющие значения полей поиска. Последовательность полей поиска соответствует полям установленного для компонента Table индекса или ключевым полям физической таблицы БД, если индекс не установлен.

Если нужная запись найдена, FindKey возвращает значение True и делает текущей найденную запись, в противном случае возвращается значение False, и текущей остается та же запись, которая была до поиска.

Пусть таблица БД, представляемая компонентом Table1, содержит три поля: F_Id (S*), F_Date (D*) и F_Text (A). Для поиска в таблице могут использоваться, например, следующие обращения к методу FindKey:

  1.  Table1.FindKey([PId, '1.01.2001', PText), где PId – переменная целого типа, содержащая значение для поиска в поле таблицы F_Id; '1.01.2001' – константа; PText – переменная строкового типа, содержащая значение для поиска в поле таблицы F_Text. Если в таблице БД существует запись, поля F_Id, F_Date и F_Text, которой содержат указанные значения, то эта запись станет текущей.
  2.  Table1.FindKey([PId]), где PId – переменная целого типа, содержащая значение для поиска в поле F_Id. Если в таблице БД существует запись, поле F_Id которой содержит указанное значение, то текущей станет первая такая запись в соответствии с порядком первичного ключа.
  3.  Table1.FindKey([PDate]), где PDate – переменная типа TDate, содержащая значение для поиска в поле F_Date. Для таблицы Table1 должен быть установлен вторичный индекс, в котором первом полем является поле F_Date. Если в таблице БД существует запись, поле F_Date которой содержит заданное в переменной PDate значение, то эта запись станет текущей.

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

// Установка вторичного индекса по полю F_Date

Table1.IndexName:='Index_Date';

//Ввод значения даты для поиска в таблице

PDate:=StrToDate(InputBox('Поиск по дате', 'Дата', ''));

//Поиск записи

if not Table1.FindKey([PDate]) then

 showmessage('Нет такой даты!')

else

 <обработка данных найденной записи>;

Если нет первичного ключа, и не установлен ни один вторичный, то метод не работает!

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

Метод реализован в виде процедуры и имеет следующий заголовок:

procedure FindNearest(const KeyValues: <массив констант или переменных>);

6.2.3. Locate – ищет в таблице запись, значения заданных полей которой соответствуют значениям, заданным в параметрах поиска. Если нужная запись найдена, метод возвращает значение true и делает текущей найденную запись, в противном случае возвращается значение false и текущая запись не изменяется.

Заголовок метода имеет вид:

function Locate(const KeyFields: String; const KeyValues: Variant; Options: TLocateOptions): Boolean;

В параметре KeyFields через точку с запятой перечисляются имена полей поиска.

В параметре KeyValues, если поиск осуществляются по одному полю, указывается константа или переменная, задающая значение поиска. Например, Table1.Locate('F_Date', '1.01.2001', []) или Table1. Locate('F_Date', PDate, []). Если поиск осуществляется по нескольким полям, в этом параметре с помощью конструкции VarArrayOf задается совокупность переменных и констант, определяющих значения для поиска: Table1.Locate('F_Id;F_Text', VarArrayOf([PId, '1.01.2001']), []). Конструкция VarArrayOf позволяет объединить в одну структуру разные типы данных.

Последний параметр Options позволяет осуществлять для строковых полей частичный поиск или поиск без учета регистра. Если значения параметра не задано ([]), ищется запись с полным совпадением значений. Значение параметра loCaseInsensitive предполагает поиск без учета регистра, loPartialKey – поиск по начальным символам. Например, обращение к методу Table1.Locate('F_Text', 'информатика', [loCaseInsensitive]) позволит найти записи со значениями в поле F_Text «информатика», «Информатика», «инФорматика» и т.д. Обращение к методу Table1.Locate('F_Text', 'инфо', [loPartialKey]) найдет записи со значениями в поле F_Text «информатика», «информатизация», «информационные технологии» и т.д. Можно указать оба значения: Table1. Locate('F_Text', 'инфо', [loPartialKey, loCaseInsensitive]).

Если нужная запись найдена, она становится текущей и функция возвращает значение True, в противном случае функция возвращает значение False.

В тексте программы этот метод вызывается оператором Table1.Locate(<параметры>), где Table1 – имя компонента Table, связанного с таблицей БД, в которой происходит поиск.  

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

// В поле таблицы БД, связанной с компонентом Table1, ищется первая запись, которая в поле Name_Product содержит значение ‘молоко’

if  Table1.Locate('Name_Product ', 'молоко ', []) then

// Искомая запись найдена, она становится текущей

     Showmessage('Товар найден!')

else  

// Искомая запись не найдена, текущая запись не изменяется

   Showmessage('Товар не найден!')

6.3. Поля компонента Table

Как уже указывалась (см. Лекция 5), для дополнительных возможностей работы с полями таблицы БД к компоненту Table, представляющему таблицу, можно добавить описания полей таблицы как классов объектов. Для этого следует дважды щелкнуть по компоненту Table, представляющему таблицу, затем на появившемся окне нажать правую кнопку мыши и выбрать команду Add all fields. После этого в блок описаний программного модуля вставляются описания добавленных полей как классов объектов, наследников класса TField. Для доступа к значениям полей таблицы БД, представленных в компоненте Table, можно использовать свойство Value класса TField в виде: <Имя компонента TTable><Имя поля>.Value. Возвращаемое значение имеет тип Variant и преобразуется, если это возможно, к требуемому типу.

Например, для вывода в окне сообщения значения оценки товара из текущей записи таблицы Students.db достаточно выполнить оператор:

ShowMessage('Оценка: '+Table1Mark.Value);

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

  •  представление значения в нужном формате и выравнивании (свойства Alignment, DisplayFormat, EditMask);
  •  формирование значения по умолчанию (свойство DefaultExpression);
  •  формирование требования на обязательное значение (свойство Required установлено в Тrue).

Кроме этого, с помощью компонента Table можно создать поля специального типа, которые не являются полями заданной таблицы БД, но значения которых формируются в процессе работы приложения на основе значений других полей, в том числе из других таблиц БД, и могут отображаться на визуальных компонентах. Это «вычисляемые» (calculated) и «связанные» (lookup) поля.

6.4. Вычисляемые и связанные поля

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

Пусть компонент с именем taMarks представляет таблицу БД Marks.db, с полями: Id типа S* (код оценки) и Name типа A (наименование оценки), а компонент taStudents представляет таблицу БД Students.db, имеющую поле Id_Mark (код оценки). Требуется создать поле Name_Mark для taStudents, в котором отображалось бы наименование оценки, в зависимости от кода оценки в таблице Students.db.

Для создания требуемого lookup поля необходимо:

1. Щелкнуть дважды по компоненту taStudents, нажать правую кнопку мыши и в появившемся коротком меню выбрать команду New Field.

2. В появившемся окне New Field (рис. 6.2) задать значения следующих реквизитов:

Field properties/Nameимя нового поля, Name_Mark;

Field properties/Typeтип нового поля, String;

Field properties/Sizeнаибольшая длина строки, например, 20;

Field type выбрать значение Lookup;

Lookup Definition/Key Fieldsвыбрать из списка полей таблицы taStudents поле Id_Mark (данное поле

используется для связи с

таблицей-справочником);    Рис. 6.2

Lookup Definition/DataSetвыбрать из списка таблицу taMarks (компонент Table, представляющий таблицу-справочник).

Lookup Definition/Lookup Keysвыбрать из списка полей таблицы taMarks поле Id (данное поле используется для связи с исходной таблицей: связываются записи, в которых значения выбранных полей исходной таблицы и таблицы-справочника совпадают).

Lookup Definition/Result Field – выбрать из списка полей таблицы taMarks поле Name.

Значение поля Name таблицы БД Marks.db будет доступно для отображения через компонент taStudents.

Новое поле появляется не в физической таблице БД, а только в компоненте, ее представляющем!

Это поле можно удалить без изменения информации в физической таблице БД. Связь осуществляется только по значению поля Id_Mark.

Вычисляемое поле (calculated fields) позволяет использовать значения полей физической таблицы БД для вычисления значений выражений и их представления в визуальных компонентах, связанных с таблицей. Значение вычисляемого поля формируется заново каждый раз, когда изменяются значения соответствующих полей таблицы. Программный код, реализующий алгоритм формирования значения вычисляемого поля, вставляется в обработчик события OnСalcFields визуального компонента Table, представляющего таблицу.

Для создания вычисляемого поля необходимо:

  1.  Дважды щелкнуть по компоненту Table соответствующей таблицы.
  2.  

Нажать правую кнопку мыши и в появившемся меню выбрать команду New Field (рис. 6.3).

Рис. 6.3

  1.  Ввести наименование вычисляемого поля в строке Field properties/Name.
  2.  Выбрать нужный тип в строке Field properties/Type.
  3.  Выбрать значение Calculated в строке Field type и нажать кнопку OK.   
  4.  Вставить в событие OnСalcFields визуального компонента Table, представляющего таблицу, программный код, определяющий значение вычисляемого поля.

Пусть, например, таблица БД Products.db содержит поля Price тип $ (цена за единицу товара) и Amount тип N (количество закупленного товара в единицах, в которых установлена цена). Требуется создать поле для вычисления стоимости всего приобретенного товара. Для этого необходимо:

  •  ввести имя поля Sum в строку Field properties/Name;
  •  выбрать тип поля Currency в строке Field properties/Type;
  •  выбрать значение Calculated в строке Field type;
  •  вставить в событие OnСalcFields визуального компонента Table1 следующий программный код:

Table1Sum.Value:=Table1Price.Value*Table1Amount.Value

Подведем итоги. Объект класса TTable или TQuery (см. Лекция 7) может содержать совокупность объектов класса TField. Существует три типа объектов:

  •  объект, представляющий реальное поле физической таблицы БД, с которой связан объект TTtable, или поле, указанное в операторе SELECT запроса, связанного с объектом класса TQuery;
  •  вычисляемое поле, представляющее значение некоторого выражения, связывающего поля таблиц или запросов с учетом их типов;
  •  связанное поле, представляющее поле другой таблицы или запроса.

  1.  Мультиформы

Часто возникает необходимость на одной форме отобразить информацию из двух связанных содержательно таблиц: реквизиты студента и его оценки; наименование фирмы-поставщика и список товаров; автор и список его произведений и т.д. Для этого необходимо между таблицами установить связь один-ко-многим. Эта связь подразумевает, что каждой записи главной таблицы (master table) может соответствовать несколько записей подчиненной таблицы (detailed table) и каждой записи подчиненной таблицы соответствует не более одной записи главной таблицы. Соответствие устанавливается по равенству значений выбранных полей двух таблиц.

Для создания такой связи между таблицами необходимо:

  •  для компонента Table подчиненной таблицы выбрать для свойства MasterSource имя источника данных (TDataSource), связанного с главной таблицей;
  •  

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

Рис. 6.4

Такая связь между таблицами позволяет для текущей записи главной таблицы отображать на форме только связанные с ней записи подчиненной таблицы. Обычно для обеспечения удобного интерфейса пользователя на форме представляются «идентификационные» поля главной таблицы (фамилия, наименование, номер счета и т.д.) в виде TDBEdit и поля подчиненной таблицы в виде TDBGrid. Поля, по которым реализуется связь (они имеют одинаковые значения для двух таблиц), целесообразно отображать на форме только один раз для главной таблицы (рис. 6.5).

            Рис. 6.5


Лекция 7.  Запросы.

7.1. Запросы

Аппарат запросов – мощное средство, позволяющее быстро выполнить различные действия над данными таблиц.

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

Рассмотрим некоторые, основные структуры операторов языка SQL.

  1.  Оператор выборки данных SELECT

SELECT  [DISTINCT] *| <список выбираемых полей>

FROM <список таблиц>

[WHERE <условие>]

[ORDER BY <список полей>]

[GROUP BY <список полей>]

Оператор предназначен для формирования набора данных, структура которого определяется список выбранных полей, а записи – указанными условиями.

Символ «*» задает отбор всех полей указанных таблиц.

В списке таблиц указываются имена таблиц, из которых формируется набор данных.

Слово DISTINCT задает  условие, при котором  выбираются только записи с различными значениями.

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

SELECT students.name

FROM students

Результат следующего запроса – все различные фамилии.

SELECT DISTINCT  students.name

FROM students

Ключевое слово FROM позволяет задавать для таблиц  так называемые «алиасы» (псевдонимы), а затем использовать их для доступа к полям.

Например,

SELECT s.name

FROM students s или

SELECT s.name, s.date_birth

FROM students s

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

SELECT s.name AS fio, s.date_birth AS birth

Новые имена для полей можно использовать только в рамках данного запроса, реальные имена полей в таблице не будут изменяться!

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

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

SELECT s.fio, s.adress

FROM students s

WHERE s.course=1

Логическое выражение может быть простым или сложным. В сложном логическом выражении используются логические операции NOT, AND, OR.

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

SELECT s.fio, s.adress

FROM students s

WHERE  (s.course=1) AND (s.group_st=1)

Чаще всего запросы используются для выборки данных из нескольких таблиц.

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

SELECT s.name, m.mark

FROM students s, marks m

WHERE  (s.id_stud=m.id_stud) AND (m.date_sem= ' 01.02.2001')

Можно добавить и наименования дисциплин:

SELECT s.name, m.mark, sb.name

FROM students s, marks m, subjects sb

WHERE  (s.id_stud=m.id_stud) AND (m.id_subj=sb.id_subj)

  1.  Опция ORDER BY в команде SELECT

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

SELECT s.name, m.mark, sb.name

FROM students s, marks m, subjects sb

WHERE  (s.id_stud=m.id_stud) AND (m.id_subj=sb.id_subj)

ORDER BY s.name, sb.name

  1.  Опция GROUP BY в команде SELECT

Использование ключевого слова  GRОUP BY  позволяет группировать записи по одинаковым значениям заданных полей для выполнения так называемых функций агрегации или групповых функций (количество записей в группе, сумма значений заданного поля в группе и т.д.).

Реализованы  следующие функции: SUM (сумма),  COUNT (количество), AVG (среднее), MAX (наибольшее), MIN (наименьшее).

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

SELECT s.name AS Fio, SUM(m.mark) AS SumM

FROM students s, marks m

WHERE (s.id_stud=m.id_stud)

GROUP BY Fio

ORDER BY SumM

Обратите внимание, что после ключевого слова GROUP BY д.б. указаны все поля, заданные до функции агрегации.

  1.  Компонент Query, представляющий запросы

Запросы представляют специальный класс TQuery. Этот класс задается компонентом Query (страница DataAccess). Для использования запроса в приложении необходимо установить на какой-либо форме или модуле компонент Query и задать значения (по крайней мере) свойствам: DatabaseName и SQL.

Для свойства DatabaseName необходимо выбрать из списка алиас БД, с которой происходит работа. Значение свойства SQL – совокупность строк запроса на языке SQL.

Для запуска запроса используется оператор:

<имя запроса>.Open

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

Для этого необходимо:

  1.  установить на форме компоненты DataSource и DBGrid (с именами, например, DataSource1 и DBGrid1);
  2.  свойству DataSet компонента DataSource придать значение имени запроса (например, Query1);
  3.  свойству DataSource компонента DBGrid придать значение имени источника данных (DataSource1);

  1.  Примеры использования аппарата запросов

Пусть даны БД, представляющие информацию о книгах, хранящихся в библиотеке, представляют следующие таблицы: Authers (информация об авторах), Books (информация о книгах), Publ (информация об издательствах), Country (справочник стран), TypeBook (справочник направлений литературных произведений, например, поэзия, проза, критика и т.д.).

Структура таблиц следующая.

Authers

Наименование поля

Тип

Примечание

Id

S*

Код автора

Fio

A 60

Фамилия, имя, отчество автора

Date_Birth

D

Дата рождения

Date_Dearth

D

Дата смерти

Id_Country

S

Код страны проживания

Books

Наименование поля

Тип

Примечание

Id_Aut

S*

Код автора

Id

S*

Код книги

Name

A 255

Название книги

Id_Publ

S

Код издательства

Id_Type

S

Код литературного направления

Year_Publ

S

Год издания

Pages_Book

S

Кол-во страниц

Number

S

Тираж

Publ

Наименование поля

Тип

Примечание

Id

S*

Код издательства

Name

A 60

Название издательства

Id_Country

S

Код страны

Country

Наименование поля

Тип

Примечание

Id

S*

Код страны

Name

A 60

Название страны

TypeBook

Наименование поля

Тип

Примечание

Id

S*

Код типа произведения

Name

A 60

Название типа

Сформируем запросы.

  1.  Список всех авторов по алфавиту, книги которых имеются в библиотеке.

SELECT fio

FROM authers

ORDER BY fio

  1.  Список всех авторов по алфавиту, книги которых имеются в библиотеке с указанием количества книг.

SELECT a.fio, COUNT(b.id)

FROM authers a, books b

WHERE (a.id=b.id_aut)

GROUP BY a.fio

ORDER BY fio

  1.  Список всех авторов по алфавиту, у которых книги выходили в заданном издательстве.

SELECT DISTINCT a.fio

FROM authers a, publ p,books b

WHERE (a.id=b.id_aut) AND(b.id_publ=p.id) AND (p.name= 'САМОЕ ХОРОШЕЕ ИЗДАТЕЛЬСТВО' )

ORDER BY fio

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

SELECT p.name, a.fio, b.name

FROM authers a, publ p, books b

WHERE (b.id_publ=p.id) AND (b.id_aut=a.id) AND (b.year_publ=2001)

ORDER BY p.name, a.fio, b.name

  1.  Все книги данного автора, опубликованные после указанного года

SELECT b.name

FROM authers a, books b

WHERE (b.id_aut=a.id) AND (a.fio='Иванов Иван Иванович') AND (b.year_publ>1975)

ORDER BY b.name

  1.  Максимальный тираж по издательствам в заданном году

SELECT p.name, MAX(b.number)

FROM publ p, books b

WHERE (b.id_publ=p.id) AND (b.year_publ=2001)

GROUP BY p.name

ORDER BY p.name

  1.  Суммарный тираж в страницах за заданный год заданного издательства

SELECT SUM(b.pages_book)

FROM publ p, books b

WHERE (b.id_publ=p.id) AND (b.year_publ=2001) AND (p.name='Несчастный случай')

  1.  Все книги французских авторов, изданных заданным издательством

SELECT a.fio, b.name

FROM authers a, books b, country c, publ p

WHERE (b.id_aut=a.id) AND (a.id_country=c.id) AND (c.name='Франция') AND (p.id=b.id_publ) AND (p.name='Все печатаем')

ORDER BY a.fio,b.name

  1.  Поэтические сборники английских авторов, изданных в заданном году

SELECT a.fio, b.name

FROM authers a, books b, country c, typebook t

WHERE (b.id_aut=a.id) AND (a.id_country=c.id) AND (c.name='Англия') AND (t.id=b.id_type) AND (t.name='Поэзия') AND (b.year_publ=2000)

ORDER BY a.fio,b.name

7.3. Запросы с параметрами

Для обеспечения большей гибкости запросов в тексте запроса могут указываться вместо конкретных значений переменные, которые получают конкретные значения при выполнении запроса. Такие переменные называются параметрами, а соответствующие запросы – запросами с параметрами. Перед переменной, обозначающей параметр в тексте запроса необходимо поставить знак «:», а перед открытием запроса – вызвать специальный метод ParamByName класса TQuery:

<имя объекта класса TQuery (имя запроса)>.ParamByName (<имя параметра>).Value:=<выражение>

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

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

Структура такого запроса следующая:

SELECT b.name

FROM authers a, books b, country c

WHERE (b.id_aut=a.id) AND (a.id_country=c.id) AND (c.name=:param1) AND

(b.year_publ>=:param2)

ORDER BY b.name

Перед обращением к данному запросу необходимо задать значения двух параметров (типы данных: Country – String, Year- Short), а затем выполнить запрос:

Country:=InputBox(‘Наименование страны ’, ‘Введите наименование страны’,’’);

Year:=StrToInt(InputBox(‘Год’, ‘Введите год’,’’));

Query1.Close;

Query1.ParamByName('param1').Value:=Country;

Query1.ParamByName('param2').Value:=Year;

Query1.Open;

7.4. Запросы с операторами DELETE, INSERT, UPDATE

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

Структура этого оператора в простом виде:

DELETE

FROM <имя таблицы БД>

WHERE <условие>

Например, для удаления из таблицы Books всех книг, изданных до 1917 года, необходимо выполнить следующий запрос:

DELETE

FROM books

WHERE books.year<1917

Запрос с оператором INSERT вставляет в таблицу запись с заданными значениями:

INSERT INTO <имя таблицы БД> (<список полей>)

VALUES (<список значений>)

INSERT INTO COUNTRY (ID, NAME)

VALUES (5, ‘Франция)

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

UPDATE <имя таблицы БД>

SET <имя поля>=<выражение>, <имя поля>=<выражение>

WHERE <условие>

Для выполнения этих запросов из среды Delphi вместо метода Open вызывается метод ExecSQL.