- •230100 Информатика и вычислительная техника
- •Введение
- •1.Функции
- •1.1. Создание пользовательских функций. Передача аргументов
- •1.2. Глобальные и локальные переменные
- •2.Процедуры
- •2.1. Пользовательские процедуры
- •2.2. Упреждающее объявление процедур и функций (forward)
- •3.Концепция типа данных
- •3.1. Абстракции в обработке информации
- •3.2. Понятие типа данных
- •3.3. Иерархия типов данных
- •3.4. Стандартные типы данных
- •3.5. Тип данных Boolean
- •3.6. Тип данных char
- •3.7. Ограниченные типы
- •4.Множества. Массивы
- •4.1. Операции над множествами
- •4.2. Массивы
- •4.3. Утверждения о массивах
- •5.Индуктивные функции на последовательностях (файлах, массивах)
- •5.1. Схема Горнера
- •5.2. Индуктивные функции
- •6.Записи
- •6.1. Представление сложных типов данных в памяти
- •6.2. Упаковка элементов сложных типов данных
- •6.3. Представление записей в памяти
- •7.Процедуры и функции
- •7.1. Создание пользовательских функций. Передача аргументов
- •7.2. Процедуры
- •7.3. Передача параметров по ссылке и значению
- •8.Основы объектно-ориентированного подхода
- •8.1. Основные положения объектно-ориентированного подхода
- •9.Конструкторы и деструкторы. Инкапсуляция
- •9.1. Хранение объектов в памяти. Доступ к свойствам из методов
- •9.2. Принцип инкапсуляции
- •9.3. Поля и свойства
- •10.Наследование и полиморфизм
- •10.1. Принцип полиморфизма
- •10.2. Виртуальные методы
- •10.3. Пример описания объекта
- •10.4. Параметры-процедуры
- •11.Основы программирования графики
- •11.1. Основные понятия компьютерной графики
- •11.2. Получение сведений о режимах экрана. Эффекты прозрачности
- •11.3. Графические построения
- •11.4. Построение графиков функций
- •11.5. Использование компонента tChart
- •11.6. Построение геометрических фигур
- •11.7. Обновление изображения
- •12.Построение динамических изображений
- •12.1. Анимация на основе операции xor
- •12.2. Буферизация фона
- •12.3. Работа с таймером
- •13.Динамические структуры данных
- •13.1. Размещение динамических переменных в памяти
- •13.2. Захват и освобождение динамической памяти
- •13.3. Нетипизированные указатели
- •14.Линейные списки: основные виды и способы реализации
- •14.1. Линейный список как абстрактный тип данных
- •14.2. Операции с динамическими массивами
- •14.3. Сортировка динамических массивов
- •14.4. Деревья
- •14.5. Потоки в памяти
- •15.Сортировка и поиск
- •15.1. Алгоритмы поиска
- •15.1.1Линейный поиск
- •15.1.2Двоичный поиск
- •15.1.3Поиск текстовых строк
- •15.2. Сортировка данных
- •15.2.1Сортировка массивов
- •16.Сортировка файлов. Рекурсия
- •16.1. Рекурсивные определения и алгоритмы
- •16.2. Программирование рекурсивных алгоритмов
- •16.3. Сортировка файлов
- •17.Файлы
- •17.1. Буферизация
- •17.2. Работа с текстовыми файлами
- •17.3. Работа с двоичными файлами данных
- •17.4. Нетипизированные файлы
- •17.5. Файловые потоки
- •18.Работа с файловой системой
- •18.1. Стандартные файловые диалоги
- •18.2. Получение сведений о дисках
- •18.3. Получение сведений о файлах
- •18.4. Сканирование дисков и директорий
- •19.Обработка исключительных ситуаций
- •19.1. Векторы прерываний
- •19.1.1Хранение данных в стеке
- •19.2. Контроль ввода-вывода
- •19.3. Обработка исключительных ситуаций в Delphi
- •20.Отладка программ
- •20.1. Интегрированная среда программирования
- •20.2. Инструменты отладки программ
- •20.3. Типичные ошибки в программировании
- •21.Принципы построения трансляторов
- •21.1. Синтаксис и семантика языков программирования
- •21.2. Структура языков программирования
- •21.3. Структура и организация работы транслятора
- •22.Параллельные процессы
- •22.1. Создание многопоточных приложений
- •22.2. Управление скоростью работы потоков
- •23.Модульные программы
- •23.1. Создание dll-библиотеки на Delphi
- •23.2. Вызов dll
- •23.2.1Статическое связывание
- •23.2.2Динамическое связывание
- •23.3. Отладка проектов с dll
- •23.4. Хранение форм в dll-библиотеках
- •24.Обмен данными между приложениями
- •24.1. Работа с буфером обмена
- •24.2. Основы ole-технологии
- •25.События и сообщения
- •25.1. Отправка и получение сообщений
- •25.2. Предотвращение повторного запуска программы
- •26.1. Основы com-технологии
- •26.2. Вывод отчета при помощи Microsoft Word
- •26.2.1Проверка наличия сом-сервера на компьютере
- •Общее правило: при работе с любым сом-сервером запретите пользователю им пользоваться, пока с сом-сервером работает ваша программа.
- •26.3. Подключение к сом-серверу Word из Delphi
- •26.4. Управление форматированием документа
- •26.5. Работа с таблицами
- •26.6. Запуск Word из внешней программы
- •26.7. Работа с AutoCad по com-технологии
- •27.Принципы организации реляционных баз данных
- •27.1. Основные сведения о базах данных
- •27.2. Проектирование структуры базы данных
- •27.3. Нормализация структур баз данных
- •28.Работа с локальными бд
- •28.1. Драйвер баз данных bde
- •28.2. Создание баз данных
- •29.Программная обработка локальных бд
- •29.1. Редактирование локальных бд
- •29.2. Вывод бд на экран
- •29.3. Цветовое выделение строк бд
- •30.Работа с распределенными бд
- •30.1. Основы языка sql
- •30.2. Понятие алиаса
- •30.4. Подключение к sql-серверу
- •31.Программная обработка данных в архитектуре "клиент – сервер"
- •31.1. Программный доступ к полям бд
- •31.2. Фильтрация и сортировка данных
- •32.Работа с нормализованными бд
- •32.1. Связывание таблиц
- •32.2. Вычисляемые поля
- •33.Субд Interbase
- •33.1. Работа с сервером Local InterBase
- •33.2. Утилита InterBase Server Manager
- •34.Работа с языком xml
- •34.1. Структура xml-документа
- •34.2. Использование xml в среде Delphi
- •34.3. Концепция dom - объектная модель документа
- •34.4. Использование xml
- •35.Основы программирования для Интернет
- •35.1. Работа с протоколом ftp
- •35.2. Передача файлов по ftp
- •Библиографический список
- •Приложение. Зарезервированные слова sql
- •Предметный указатель
31.2. Фильтрация и сортировка данных
Предположим, мы хотим выводить на экран не все записи БД, а лишь удовлетворяющие некоторому условию. Такое действие известно как фильтрация данных. Давайте отобразим только те записи, у которых в поле 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;
32.Работа с нормализованными бд
32.1. Связывание таблиц
Очень важно научиться устанавливать связи между таблицами, что позволяет выполнять нормализацию БД. Давайте добавим в нашу БД по DVD-дискам информацию о том, какая кинокомпания сняла тот или иной фильм. Если просто добавить в таблицу dvd.db текстовое поле, то названия компаний в нем будут повторяться, что означает нарушение принципов нормализации БД. Следовательно, список кинокомпаний нужно вынести в отдельную таблицу comp.db, а в таблице dvd.db оставить поле типа Long Integer, в котором будут храниться числа – ссылки на строки таблицы comp.db (Рис. 32 .125).
dvd.db – главная таблица |
|
comp.db – подчиненная таблица |
||
Имя поля |
Тип данных |
|
Имя поля |
Тип данных |
ID |
а втоинкремент |
|
ID |
автоинкремент |
NAME_RUSSIAN |
текст |
|
NAME |
текст |
NAME_ENGLISH |
текст |
|
|
|
NUMBER |
целое число |
|
|
|
SUBTITLES |
булевский |
|
|
|
YEARF |
целое число |
|
|
|
COMPANY |
длинное целое |
|
|
|
Рис. 32.125 Структуры главной и подчиненной таблиц.
Под ссылкой понимается значение, хранящееся в автоинкрементном поле 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 добавим следующий код (новые строки выделены жирным шрифтом):
// открываем таблицу comp.db
WITH comp DO
BEGIN
Prepare;
Open
END;
// открываем таблицу dvd.db
WITH DVD DO
BEGIN
Prepare;
Open
END
END;
Закрывать каждый запрос при завершении нет необходимости, все запросы закрываются автоматически методом CloseDatasets компонента Database.
Поскольку мы изменили структуру таблицы dvd.db, об этом надо сообщить нашей программе. Проверьте, что в компоненте Database в поле AliasName записано имя алиаса DVD, иначе Delphi не сможет открыть базу. Щелкните правой кнопкой мыши на запросе DVD и выберите пункты меню Fields Editor Add fields. В открывшемся списке появится новое поле COMPANY. Щелкните по кнопке OK для его добавления. Аналогично добавьте поля в запросе comp.
Приступаем к самому важному – связыванию главной и подчиненной таблиц. Принцип связывания таков: в главной таблице создается фиктивное поле, которого в самой таблице нет. В это фиктивное поле программа автоматически заносит значения, извлекаемые из подчиненной таблицы. Снова щелкните правой кнопкой мыши на запросе DVD и выберите пункты меню Fields Editor New field. Открывается окно добавления фиктивного поля (Рис. 32 .126) – самое важное окно во всей работе с БД
Рис. 32.126 Окно создания фиктивного поля.
В поле NAME введите придуманное имя фиктивного поля, которое не должно совпадать с именами настоящих полей в главной таблице. Можно, чтобы не запутаться, всегда начинать имена фиктивных полей с буквы V – виртуальное. В списке Type выберите тип данных, которые будут отображаться в фиктивном поле, а в поле Size введите размер этих данных. Очевидно, тип и размер фиктивного поля должны совпадать с типом и размером поля с данными в подчиненной таблице, в рассматриваемом случае это поле Name в таблице comp.db. Установите переключатель в положение Lookup – это означает, что данные в новом поле будут браться из другой таблицы.
А теперь самое важное: правильно заполнить четыре списка внизу окна:
Key Fields: имя поля в главной таблице, в котором хранятся ссылки на подчиненную таблицу. В данном случае это поле Company.
Dataset: имя подчиненной таблицы. Запрос к таблице comp.db у нас называется comp.
Lookup Keys: имя автоинкрементного поля в подчиненной таблице. В данном случае это поле ID таблицы comp.db.
Result field: имя поля в подчиненной таблице, где хранятся данные, отображаемые в фиктивном поле главной таблицы. В данном случае это поле name в базе comp.
Новое поле нужно вывести на экран. перейдите на главную форму и уже известным способом добавьте в компоненте DBGrid новую колонку, связанную с полем VCOMP. Измените обработчик события OnRezise – в таблице стало на одну колонку больше и надо поменять код на примерно следующий:
procedure TForm1.FormResize(Sender: TObject);
CONST w:ARRAY[0..5] OF REAL=(0.25,0.25,0.1,0.1,0.1,0.2);
VAR i:BYTE;
begin
FOR i:=0 TO LENGTH(w)-1 DO
DBGrid1.Columns[i].Width:=TRUNC((DBGrid1.Width- GetSystemMetrics(SM_CXVSCROLL)-LENGTH(w))*w[i])-1
end;
Все! Запускаем программу и видим очень интересный результат (Рис. 32 .127).
Рис. 32.127 Отображение фиктивного поля.
Мало того, что все работает правильно, так еще в фиктивном поле автоматически появляется раскрывающийся список для его удобного редактирования.