Предположим, мы хотим выводить на экран не все записи БД, а лишь удовлетворяющие некоторому условию. Такое действие известно как фильтрация данных. Давайте отобразим только те записи, у которых в поле YEARF хранится значение 2003.
Первый способ – фильтрация на стороне клиента. Делается это так:
WITH DVD DO
BEGIN
Filter:='YEARF=2003';
Filtered:=True;
…
Filtered:=False
END;
В свойство Filter в виде текстовой строки записывается логическое выражение для отбора записей. Свойство Filtered логического типа включает/выключает фильтрацию.
А как отследить ситуацию, когда в БД нет записей, удовлетворяющих заданному условию? Очень просто:
WITH DVD DO
BEGIN
Filter:='YEARF=2003';
Filtered:=True;
IF BOF AND EOF THEN
MessageDlg('Ничего не найдено',
mtInformation,[mOK],0);
…
Filtered:=False
END;
Если свойства BOF (начало БД) и EOF (конец БД) одновременно истинны, это значит, что база пуста.
Второй способ – "на ходу" изменить SQL-запрос и заставить сервер прислать новую выборку данных. Делается это так:
VAR oldSQL:STRING;
BEGIN
WITH DVD DO
BEGIN
oldSQL:=SQL[0];
Close;
SQL[0]:='SELECT * FROM DVD WHERE YEARF=2003';
Prepare;
Open;
…
{ снятие фильтра }
Close;
SQL[0]:=oldSQL;
Prepare;
Open
END;
В переменную oldSQL запоминается текущий SQL-запрос, он хранится в свойстве SQL. Поскольку свойство SQL– это массив строк, мы обращается к его первому элементу с индексом 0. Запрос закрывается, меняется текст SQL-выражения, а затем он снова открывается. Для снятия фильтрации нужно восстановить старый запрос, хранящийся в переменной oldSQL.
Очень важно, что SQL-выражение можно динамически создавать как текстовую строку. Например, пусть пользователь вводит год с клавиатуры при помощи поля ввода Edit1:
SQL[0]:='SELECT * FROM DVD WHERE '+ 'YEARF='+Form1.Edit1.Text;
Сортировка данных очень часто применятся в БД. Проще всего она делается на стороне серверасредствами SQLпри помощи конструкции ORDER BY. Давайте отсортируем БД по русским названиям (поле TITLE_RUSSIAN):
VAR oldSQL:STRING;
BEGIN
WITH DVD DO
BEGIN
oldSQL:=SQL[0];
Close;
SQL[0]:='SELECT * FROM DVD ORDER BY TITLE_RUSSIAN';
Prepare;
Open;
…
{ снятие сортировки }
Close;
SQL[0]:=oldSQL;
Prepare;
Open
END;
Очень важно научиться устанавливать связи между таблицами, что позволяет выполнять нормализацию БД. Давайте добавим в нашу БД по DVD-дискам информацию о том, какая кинокомпания сняла тот или иной фильм. Если просто добавить в таблицу dvd.db текстовое поле, то названия компаний в нем будут повторяться, что означает нарушение принципов нормализации БД. Следовательно, список кинокомпаний нужно вынести в отдельную таблицу comp.db, а в таблице dvd.db оставить поле типа Long Integer, в котором будут храниться числа – ссылки на строки таблицы comp.db (Рис. 28.1).
dvd.db – главная таблица
comp.db – подчиненная таблица
Имя поля
Тип данных
Имя поля
Тип данных
ID
автоинкремент
ID
автоинкремент
NAME_RUSSIAN
текст
NAME
текст
NAME_ENGLISH
текст
NUMBER
целое число
SUBTITLES
булевский
YEARF
целое число
COMPANY
длинное целое
Рис. 32.1 Структуры главной и подчиненной таблиц.
Под ссылкой понимается значение, хранящееся в автоинкрементном поле ID подчиненной таблицы.
Откройте таблицу dvd.db в программе Database Desktop и измените ее структуру, щелкнув по кнопке Restructure. Добавьте поле COMPANY с типом данных Long Integer и сохраните изменения. При помощи той же программы создайте новую таблицу comp.db с полями ID (автоинкремент) и NAME (текст, 250 символов). Не забудьте изменить язык таблицы! Сохраните таблицу в той же директории, что и таблицу dvd.db. В созданную таблицу comp.db добавьте несколько записей с названиями кинокомпаний, а поле COMPANY таблицы dvd.db для всех записей пока занесите значение 1.
Вернитесь в Delphi. В модуль данных добавьте компонент Query, назвав его comp. Установите его свойства Active, DatabaseName, SessionName, RequestLive в те же значения, что и у компонента DVD. В свойство SQLзанесите выражение SELECT * FROM comp.
Разумеется, добавленный запрос надо открывать в начале работы программы, причем обязательно с соблюдением простого правила: все подчиненные таблицы открываются до открытия главной таблицы. Поэтому в обработчик события модуля данных OnCreate добавим следующий код (новые строки выделены жирным шрифтом):