DataCol: Integer Column: TColumn Параметры: Rect – координаты ячейки DataCol – номер столбца Column – ссылка на столбец State – состояние ячейки.


Чтобы посмотреть этот PDF файл с форматированием и разметкой, скачайте его и откройте на своем компьютере.
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ

РОССИЙСКОЙ ФЕДЕРАЦИИ

Федеральное государственное автономное образовательное

учреждение высшего образования

«Южный федеральный университет»








А. П.
Мелехов


Э
лектронное учебно
-
методическое пособие

«Работа с базами данных в СУБД InterBase/
Firebird
»













Ростов
-
на
-
Дону

201
7



2



Печатается по решению

кафедры вычислительной математики и математической физики и Совета
РИСО

механико
-
математического факультета ЮФУ протокол № 1 от 24 мая 201
7

г.


Работа выполн
ена в ра
мках
б
азов
ой

част
и

государственного задания Министерства образ
о-
в
а
ния и на
у
ки РФ
,

т
ема: Фундаментальные и прикладные задачи математического модел
и
р
о-
вания
,


1.5169.2017/8.9


Аннотация

Электронное учебно
-
методическое пособие предназначено для практического освоения
работы с базами данных на примере СУБД InterBase/Firebird. В пособии послед
овательно
описаны и представлены на примерах все основные этапы создания базы данных и разрабо
т-
ки пользовательского приложения для работы с базой данных. В первой части демонстрир
у-
ется работа с СУБД с помощью языка запросов SQL и утилит IBExpert и IBConso
le. Рассма
т-
ривается процесс создания структуры БД, внесения данных в базу данных, создание запросов
с помощью языка SQL. Вторая часть посвящена разработке приложений баз данных для
СУБД InterBase/Firebird в Delphi. Приводится описание стандартных компонент

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

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

01.03.02 «Прикладная математика и информ
а-
тика»

Института математики, механики и компьютерных наук им. И.И. Воровича

ЮФ
У.


3


Содержание

I
. Создание и работа с базами данных в СУБД InterBase/
Firebird
..........

4

1.

Соединение с сервером, создание базы данных

....................................

4

2.

Создание таблиц БД

............
................................................
....................

8

3.

Домены …………………………………..
......................................
..........


1
2

4.

Первичные ключи

…………………………
…..
……………………..
....

13

5.

Генераторы


………………………………
….

.
…………………
.....


1
4

6.

Индексы

.................................................
.........................................
.
....
.
....
.

1
5

7.

Внешние ключи, создание связи между таблицами
....................
.
.
.
..
.
...
.

1
7

8.

Выборка данных из таблиц, оператор
SELECT
....................
.
.....
.
.
......
.
..
.

1
8

9.

Модификация

записей

.....................
................................................
.........


24

II
.
Разработка приложений баз данных InterBase/
Firebird

на Delphi
.....
.
..

26

10.


Подключение к БД из
Delphi

........
..............................
.......................
.
....

2
6

11.

Наборы данных
TDataSet

(
TTable

и

TQuery
)

..........................
.
..............


29

12.

Объект поле (
TField
), формирование текстового

представления поля, проверка правильности вводимого

в поле значения

.......................
...............................................
..................

4
0

13.

Создание вычисляемых полей и полей выбора

...................................

4
2

14.

Источник данных
TDataSource

……
............
....................
.......................

4
6

15.

Визуальные
компоненты для работы с БД

............................................

4
7

16.

Компонент Database, управление транзакциями
..................
................


5
0

17.

Реляционный способ доступа к БД
....................................
.............
........

5
4

Треб
ования к курсовому проекту

....................................................
..............
.


59

Литература
……………………………

...................................................
..........
.

6
0



4


I
. Создание и работа с базами данных в СУБД InterBase/
Firebird


Соединение

с
сервером
, создание базы данных


(
I
)

Соединение с

сервер
ом

InterBase

7
.5

(
пример работы с
локаль
ны
м

сервер
ом
)
.

С
ервер
InterBase

входит в дистрибутив
Turbo

Delphi
, устанавливается отдельно от
него
.

Прежде чем работать с сервером, его нужно
запустить, выбрав пункт меню:

Меню


Программы


Borland InterBase 7.5



InterBase Server Manager

или
,
запустив

непосредственно

из

папки:


C:
\
Program Files
\
Borland
\
InterBase
\
bin
\
IBMgr.exe


В открывшемся окне нужно нажать кнопку
Start
.
После этого сервер
запу
ститься

и к
нему можно

будет

обращаться

как с локального компьютера, так и по сети.

Замечание.

Обычно,
сервер устанавливается на отдельном компьютере, выделенном
специально под сервер

БД
,

на котором
он
постоянно запущен.

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

БД.
Непосредственного доступа к фа
й
лу БД они не имеют.

При разработке базы данных часто

сервер устанавливается

непосредственно на компьютере
,

на котором

Вы работаете.


(
I
I
)

Соединение с сервером

Firebird

(
пример работы с
удаленным

сервер
ом
)
.

Если уст
а-
новлен

и

запущен

сервер
Firebird 2.5

на удаленном компьютере
.

Папка на

сервере, предн
а-
значенная для хранения файлов баз данных
, например, называется
: “
D
:
\
public
”.
На локальном
компьютере установлен клиент
Firebird 2.5

(способен связываться по сети с сервером и о
т-
правлять
SQL
-
запросы на сервер).

В примерах далее будет показана установка соединения

с

БД в этих двух случаях:
(
I
)

InterBase

7.5

(локальный)

или

(
II
)

Fire
bird 2.5

(удаленный)
.

На компьютерах в

классе
у
становлено

также

несколько утилит

для

более удобного

доступа к серверу
:
IBConsole



стандартная утилита, входящая в поставку
InterBase
. А

также
несколько

бесплатных утилит
:

IBExpert,
IBEasy
+
и
F
lamerobin
.

Они примерно
одинаковы по
возможностям.

Примеры
буду
т

приводить
ся

с использованием
программы
IBExpert

(C:
\
Program
Files
\
HK
-
Software
\
IBExpert
\
ibexpert.exe)
.
В

этой

программе

можно

установить

интерфейс на
5


русском языке
:

Options


Environment

Options


Preferences


Interface

Language


Russian


OK
.

Также приведено для сравнения использование стандартной программы
IBConsole
.

1)
Запустите
IBExpert


и установите русский язык, в качестве языка интерфейса.

2) Создаем новую БД на сервере

2.1.
Выберете пунк
т меню:
База данных


Создать базу …

2.2.
Установите в открывшемся окне следующие параметры
:

Сервер
:
(
I
)
локаль
ный



можно также выбрать удаленный сервер с именем
localh
os;




(
I
I
)

удаленный
.

Имя сервера
:
имя сетевого компьютера.


Файл

БД
:
(
I
)

C
:
\
InterBaseBD
\
имя файла.
gdb

(
путь
, где будет храниться база данных

и имя
новой БД
)
.


(
I
I
)


D
:
\
public
\
имя файла.
gdb

(полный путь на сервере и имя новой БД)

Э
ту папку нужно создать на диске
:

путь, указываемый к файлу БД, должен
существовать.
Ф
айл БД будет создан, после закрытия этого окна.


(
I
)
gds
32.
dll



динамическая библиотека

доступа к данным в

Inte
rBase
.

(
I
I
)
fbclient.dll



динамическая библиотека доступа к данным в
Firebird
.


Имя пользователя:

SYSDBA

(
встроенный
пользователь


администратор
)

6


Пароль
:

masterkey

(пароль по умолчанию

встроенного пользователя
)

Замечание.

Пользователь

SYSDBA


является встроенным администратором

в

InterBase

и
Firebird
.
Его паролем после установки сервера является

masterkey

.

У этого по
льзователя
неограниченные права на
сервере БД.

Если сервер используется в сети
,

рекомендуется м
е-
нять ему этот пароль
. Мы не будем этого

делать
. Имя файла БД
выбирайте

так, чтобы можно
было
понять,

чей он, например, используйте свою фамилию в названии файла.

Диалект БД
:

можно выбрать любой. Диалект 3 расширение диалекта 1. Не все, что есть в
диалекте 3, может поддерживаться, например, при доступе к БД из
Delphi
.

Размер страницы

БД
:

единица чтения да
нных с диска и пересылки по сети. Рекоменду
ется

как можно больше (но тоже может не поддерживаться старыми технологиями доступа).

Кодировка
:
win
1251


3) Регистрация БД на сервере

3.1.

Выберете пункт меню: База данных


Зарегистрировать базу
.

Е
сли
Вы не убра
ли гало
ч-
ку в предыдущем окне, это

окно

запустится

само

сразу после предыдущего.


3.2.
В этом окне выберите те же самые параметры, что и в предыдущем.

Описание базы данных
:

Заголовок

(
псевдоним
)

создаваемой БД в окне
IBExpert
.

4) После этого можно
подключиться к БД
:

Выберете пункт меню: База данных


Подключиться к базе
.


Замечание.

Если использовать другие утилиты,
то нужно

выполнять примерно те же самые
действия
.

В некоторых утилитах сначала регистрируется сервер (локальный или удален
ный)
и только

после этого на сервере

создается

БД

или регистрируется, если она уже существов
а-
7


ла
.

Для создания БД
также
можно использовать утилиту
isql
.
exe

(консольное
приложение,

устанавливаемое вместе с
InterBase

и
Firebird
)
,
в которой пишутся
sql
-
запросы к серверу
БД.


В стандартной программе
IBConsole

эти же действия выполняются практически также
:


Локальный сервер уже зарегистрирован
. Если нужен удаленный сервер, то выбираем пункт
меню
:

Server



Register


и регистрируем его.


Для соединения с сервером выбираем из контекстного меню заголовка сервера пункт
Login

или просто дваж
ды щелкаем на заголовке сервера
:


Создаем новую БД
:

выбираем пункт меню
:

Database



Create

Database

и заполняем поля в
следующем окне. В поле
Filename
(
s
)

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

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

8




С
оздание

таблиц

БД

С помощью
программы
IBExpert

можно создавать

любые структуры БД
.
IBExpert

п
о-
зволяет пользователю самостоятельно писать
SQL
-
запросы к серверу и создавать запросы с
помощью мастеров (и
формирует

на их основе

SQL
-
запрос
ы).

Всегда можно посмотреть
созданный

программой

IBExpert

SQL
-
запрос.

Чтобы открыть

редактор
SQL
-
запрос
ов, нужно выбрать пункт меню:

Инструменты


SQL

Редактор.

Запустить мастер
можно
, например, из контекстного меню
:




В стандартной программе
IBConsole

эти же действия выполняются тоже просто
. Чт
о-
бы открыть редактор
SQL
-
запрос
ов, нужно выбрать значок

на панели инструментов. З
а-
9


пустить мастер можно из контекстного меню в правом окне, когда в левом активна строка

таблиц


Tables

:



Язык
SQL

(
Structured

Query

Language



структурированный язык запросов
)

Для работы с

базами

данными используется язык
SQL
.
Существуют три

принятых

стандарта
языка доступа к данным
SQL
:
SQL
89,
SQL
92
и
SQL
3.

Разработчики СУБД по
д-
держивают

какую
-
то свою версию языка
SQL
, придерживаются одного из трех стандартов,
из них
не все
реализуют, добавляют
свое
, меняют некоторые обозначения
.

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

С помощью

языка

SQL

можно определять структуры БД,
а также запрашивать и
н-
формацию из

БД. Поэтому его

раз
дел
яю
т

на

два

под
множества
:
язык

определения

данных

(
DDL
,
Data

Definition

Language
)
и

язык

манипулирования

данными

(
DML
,
Data

Manipulation

Language
).

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

таблиц, инде
к-
сов, ключей и т.п
. В
о в
тор
ую группу



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

записей.


Строчные и прописные символы в языке
SQL

не различаются, но команды
SQL

пр
и-
нято писать прописными

буквами
.
Запросы можно писать в одну или несколько строк. Мо
ж-
но выполнять сразу несколько запросов
SQL
. Точку с запятой в конц
е запроса ставить не
обязательно.

В качестве раз
делителей используются пробелы,

запятые
, круглые скобки.

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

Квадратные скобки
[]
в
примерах
далее означают необязательные части
, фигурные скобки

{
вариант
1 |

вариант
2}



выбор из нескольких вариантов
.



Определение

данных

1) Создание таблицы


Для создания таблицы служит оператор
CREATE


TABLE
, который имеет следующий
формат

(неполное описание
, только обязательная часть
)
:

CREATE


TABLE


имя
таблицы



(
имя поля



тип
�,

10






имя

поля

тип

);

Пример
.

Создание таблицы с именем
NewTable
, содержащей три поля.

CREATE

TABLE

New
Table

(Number INTEGER,




Name
VAR
CHAR (
20),




Birthday

DATE);


Типы

полей


Типы данных
InterBase

7.5
и для сравнения

Firebird 2.5






Целочисленные

типы
:
SMALLINT

(2
байта
)
,
INTEGER

(4
байта
)
,

BIGINT

(
8

байт
,
тип

Firebird

2.5
,
такого типа
не
т

в

InterBase
)
.

Логический тип
:
BOOLEAN

(
наоборот, есть только в
InterBase
, в старых версиях тоже не
было этого типа
)

Вещественные

типы
:

FLOAT

(4
байта
;

не рекомендуется использовать, слишком маленькая
точность
)
,
DOUBLE

PRECISION

(8

байт
)
.

Типы данных с фиксированной точкой
:

NUMERIC
,
DECIMAL
.
Количество цифр от 1 до 18,

знаков после запятой
:

от
0 до 18.

Пример.
NUMERIC
(15,2)

Дата и время
:
DATE

(дата)
,
TIME

(время)
,
TIMESTAMP

(дата + время).

Символьные типы
:
CHAR
,
VARCHAR
. От 1

до 32768 символов. Тип
CHAR

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

Бинарный тип
BLOB

предназначен для хранения данных

переменного размера
:
большой
текст, картинка и т.п.


В
InterBase

также есть массивы, хотя они не входят в стандарт
SQL

и не поддерживаются
многими технологиями доступа

к БД
.

Пример.


INTEGER
[10]


одномерный массив от

1 до

10

SMALLINT
[
-
5:5]


одномерный массив от
-
5 до 5

CHAR
[5, 5]



двумерный массив с обоими индексами от1 до 5
.


Замечание.

Более подробные сведения о типах можете посмотреть в книге
[
4
]



«
Борри Х.
Firebird
: руководство разработчика баз данных
»

или в файлах документации на английском
языке.

11


Задание.

Создайте
таблицу,

как с помощью
SQL
-
запрос
а
, так и с помощью мастера.
На з
а-
кладке «Скрипт» можно посмотреть сгенерированный мастером запрос.

При определении полей таблицы можно добавлять различные
опции.

1.
Можно задать з
начение по умолчанию
:

Пример.


pole
1
INTEGER

DEFAULT


100


по умолчанию присваивается значение 100



pole
2

INTEGER

DEFAULT

NULL



пустое

значение

pole
3

VARCHAR(10)

DEFAULT

USER



имя

пользователя

2. Можно потребовать
обязательность заполнения
:

Пример.


pole
1
INTEGER

NOT

NULL

3
. Можно
проверять вносимые

значени
я

с помощью директивы
CHE
C
K
.

У этой директивы
много вариантов
:


VALUE operatorop-;৤r;§to;&#xr-80; vav-9; -5l;l


| VALUE [NOT] LIKE va&#x-4va;l00;l [ESCAPE
va�l]

| VALUE [NOT] IN ( [, …])

| VALUE IS [NOT] NULL

| VALUE [NOT] CONTAINING vava4;&#xl000;l

| VALUE [NOT] STARTING [WITH] vava4;&#xl000;l

| (search_conditse3; -5r;Çh_;&#x-9c4;&#xondi;&#xt-3i;&#xon00;ion)

| NOT search_conditse-;ڤr;Çh_;&#x-9c4;&#xondi;&#xt-3i;&#xon00;ion

|
search_co
ndit�ion OR
search_condit�ion

| search_condits-1;๊r-6;Äh_;Äon; it-;ion;ion AND
search_
condit�ion

operatoope;ra7;&#xto-1;r00;r = {= | |  -9;&#x|10 ;&#x-900; | = |=4 ;&#x-9|1;� 00; = | ! |  -9;&#x|10 ;&#x-9!0;! | 䀀 | !=}

Используется константа
VALUE
, которая обозначает проверяемое поле.

Пример
.


pole
1
INTEGER

CHE
C
K

(
pole
�1
0
)



pole
2

INTEGER

CHECK

(
VALUE�=2
)

AND
(
VALUE=5
)

pole
3

VARCHAR(1
)

CHECK

(VALUE
I
N ('
a
', '
b
', '
c
'));


2)
У
даление

таблицы

DROP

TABLE


имя таблицы

;

3) И
зменение состава полей таблицы

ALTER

TABLE


имя таблицы


ADD



имя поля



тип
�,


/*
добавить

поле

*/

DROP



имя поля

;



/*
удалить поле
*/

Пример
.

ALTER

TABLE

NewTable

ADD

num

NUMERIC
(
5,2
)
;



12


Домены

Домен
ы



это тип
ы

данных, определ
яемых пользователя
м
и
.
Домен определяется

на
основе существующих типов и ограничений. Можно определить

свой

домен и далее при о
п-
ределении
полей

использовать его вместо типа данных.
Домены н
ельзя
использовать при
опис
ании

перемен
ных

в хранимых процедурах и триггерах.

Домен создается с помощью следующей
к
оманды:

CREATE

DO
M
AIN

домен

[AS]

тип

данных


[DEFAULT
литерал

| NULL |

USER}]

[NOT NULL]

[СНЕСК ограничения домена
]

[CH
{
набор символов
|

NONE}]

[COLLATE порядок сортировки];

Обязательная часть определения домена



имя нового домена и его

базовый

тип.
Все о
с-
тальные части в его определении не обязательны.

Н
еобязатель
ные

час
ти домена
:

DEFAULT



задаем значение по умолчанию

NOT NULL




тре
бование обязательного заполнения поля

СНЕСК



ограничения, накладываемые на данные в столбце

CH



набор символов, рекомендуется

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

COLLATE



порядок сортировки, рекомендуется
win
1251

(
по умолчанию для набора симв
о-
лов
win
1251)

или
pwx
_
cyrl
.


Пример
.
Создание

доменов


1) CREATE

DO
M
AIN
D_ID
I
NTEGER

NOT NULL
;

2) CREATE

DO
M
AIN
D_FIO VARCHAR(30)
NOT NULL
;

3)
CREATE

DO
M
AIN
D_MARK SMALLINT DEFAULT 2


CHECK

((
VALUE
�=2)
AND

(
VALUE
=5));

и таблиц

с использованием доменов
:

CREATE

TABLE

Student

(
NumberStud

D_ID
,




FIO


D_FIO
,




kurs

SMALLINT,



gruppa SMALLINT
);


CREATE

TABLE

Session

(
ID D_ID
,


NumberStud

D_ID
,





VAR
CHAR
(20),

13





Mark

D
_
MARK
);

Переопределить домен можно с помощью команды

ALTER DO
M
A
I
N.
Оператор м
о-
жет быть использован для изменения любо
г
о
параметра сущ
ествующе
г
о домена
, кроме
уменьшения типа (см.
[4,

стр. 162
]
) и обязательности заполнения поля
.

Оператор DROP DO
M
AIN удаляет из базы данных существующее описание домена
при условии, что домен не используется в каком либо описании столбца базы данных.

Первич
ные
ключи

Первичный ключ в таблице


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


номер записи, который не повт
о-
ряет
ся и требует минимального объема памяти, что обеспечивает максимальную скорость
работы с ним. Создать первичный ключ можно сразу при создании таблицы или добавить
позже. Приведем пример создания первичного ключа (первичным ключом у нас будет поле
ID) при с
оздании таблицы:

CREATE

TABLE

Table
New

(

ID INTEGER NOT NULL
,



NAME VARCHAR(80),



CONSTRAINT pkTable PRIMARY KEY (ID)
);



Для

создания

первичного

ключа

в

таблице

T
able
New

требуется, во
-
первых, чтобы п
о-
ле
ID

было не пустым


колонка ID получает дополнительное определение NOT NULL.

Создание первичного ключа задается предложением вида
:


CONSTRAINT <имя

ключа> <тип

ключа> (<поля

входящие в

ключ>).

Добавить/удалить первичный ключ в таблицу, когда она уже
существует и заполнена
данными, можно воспользовавшись командой ALTER TABLE. При этом, если поле

ID
, в
ы-
бранное для первичного ключа не будет удовлетворять требованиям, например, не у всех з
а-
писей поле будет заполнено или будут повторы, то создать ключ не у
дастся. Обычно, стру
к-
тура БД определяется заранее, и чаще всего первичный ключ создается вместе с таблицей.
Пример

добавления

первичного

ключа в существующую таблицу
:

ALTER

TABLE

TableNew


ADD

CONSTRAINT

pkTable

PRIMARY

KEY

(
ID
);


При этом в таблицу Tabl
e
New

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

14


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

ALTER TABLE Table
1

DROP CONSTRAINT pkTable;


При этом ключ с именем pkTabl
e будет удален из базы данных.

Г
енераторы

Как было сказано выше, на практике часто ключом является счетчик (
суррогатный
ключ)



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


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

Некоторые СУБД имеют специальный

тип счетчик, при добавлении в таблицу новой
записи значение поля с этим типом автоматически увеличивается на величину приращения,
обычно на единицу. В InterBase нет поля типа счетчик, однако есть возможность реализовать
подобное поведение. Для создания по
ля, которое бы заполнялось автоматически при доба
в-
лении записи в таблицу, используется совокупность средств: первым из них является генер
а-
тор. Генератор


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

Генератор создается с помощью следующих операторов:

CREATE GENERATOR g
en
1
;


en
1

TO 0;


В этом примере в первой строчке в базе данных создается генератор с именем g
en
1, а
во второй этому генератору присваивается значение
0
.

Чтобы получать и изменять значения генераторов, существует встроенная в

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

Current_value = GEN_ID (
gen1
,

1)

Как можно этим воспользоваться для задания значения
суррогатного
ключа
?


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

GEN_ID(<имя генератора>,1) и полученное значение подставляется в
сформированную запись. Происходит вставка в таблицу, при этом мы получаем гарантир
о-
ванно уникальный первичный ключ.

15


Второй способ


формирование первичного ключа на стороне сервера


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

Замечани
е.

Генераторы мы будем использовать при изучении триггеров и хранимых проц
е-
дур.

И
ндексы

Индекс


это упорядоченный указатель на записи в таблице. Индекс состоит из пар
значений "значения индексных полей
/
поля"


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


значит входящее в индекс).
Индексы обычно создаются для полей часто участвующих в запросах, так как они сущес
т-
венно ускоряют запросы за счет быстрого поиска.

Индексы используются в трех основных случаях:

1.

Ускорение выполнения запросов. Индексы создаются для полей, которые использ
у-
ются в условиях поиска SQL
-
запросов.

2.

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

которое б
у-
дет вставлено. Для поиска записи используется особая разновидность индекса


ун
и-
кальный индекс.

3.

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

Синтаксис

создания

индексов
:

CREATE [UNIQUE] [ASC[ENDING] | DESC
[ENDING]]



INDEX



имя

индекса



ON



имя

таблицы


(
поле
1

[,

поле2

...]);



Параметры
:

16


UNIQUE



уникальный индекс, не может быть повторений. Уникальный индекс в

InterBase

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

ASC
[
ENDING
]


упорядочен по возрастания (по умолчанию)

DESC
[
ENDING
]



упорядочен по убыванию


имя

индекса






имя создаваемого индекса


имя

таблицы





таблица, в которой создается индекс

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

Приведем пример создания индекса, с минимальным набором параметров
:


CREATE INDEX my_index ON Table
1

(ID)


В

этом

примере

создается

индекс

с

именем

my
_
index

для

таблицы

Table
1
,
с

индекс
и-
рованным

полем

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

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

1.

При помощи команды ALTER INDEX.

2.

При уничтожении индекса командой DROP INDEX и повторном создании командой
CREATE INDEX.

3.

При резервном копировании и восстановлении из резервной копии с и
спользованием
инструмента gbak.

Использование команды ALTER INDEX имеет следующий формат:

ALTER INDEX
IndexN
ame {ACTIVE | INACTIVE};

Здесь
IndexN
ame



имя индекса, а ACTIVE и INACTIVE


два состояния индекса, в
которые его можно перевести при помощи команды ALTER INDEX. Параметр ACTIVE о
з-
начает, что индекс активен и может применяться во всех запросах и процедурах. Установка
индекса в INACTIVE (неактив
ен) приводит к отключению его использования. Для пер
е-
стройки индекса требуется выполнить две команды:

ALTER

INDEX

IndexN
ame

INACTIVE
;

ALTER

INDEX

IndexN
ame

ACTIVE
;


Синтаксис

команды

DROP INDEX:

DROP INDEX имя_индекса;

17


Внешние ключи
, создание связи между
таблицами

Связь между таблицами в
InterBase

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


поле связи в главной таблице, ее ключевое поле, не может быть
удалено
/
изменено без удаления
/
изменения поля свизи в записях подчиненной таблице
;

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

Рассмотрим наложение ограничения внешнего ключа на примере двух таблиц, соде
р-
жащих информацию о накладных. Для этого создадим таблицу
In
voice



таблицу для хран
е-
ния заголовка накладной и таблицу
G
oods



таблицу для хранения информации о товарах,
входящих в накладную.



CREATE TABLE

I
nvoice

(

ID
_

Invoice

INTEGER NOT NULL Primary Key
,



Date

I
nvoice

DATE
,



Num

I
nvoice

INTEGER
,



Note

I
nvoice

VARCHAR

(255));


Созданная выше таблица
I
nvoice



главная таблица, ключевое поле
ID
_

I
nvoice

будет
являться ее полем связи. Таблица
G
oods
, созданная ниже,


подчиненная
.

Для создания связи
обязательно в подченненой таблице должно быть ключевое поле

ID_
G
oods

и поле связи


FK_

I
nvoice
, которое в дальнейшем свяжем с
ID
_

I
nvoice
.

CREATE TABLE
G
oods

(

ID_

Goods

INTEGER NOT NULL PRIMARY KEY
,



FK_

Invoice

INTEGER NOT NULL
,



G
oods
Name VARCHAR (255),



A
mount

DOUBLE PRECISION,



P
osition

INTEGER
);


Добавляем внешний ключ (создаем связь между таблицами) в уже существующую
таблицу с помощью следующей команды:

ALTER TABLE
G
oods




ADD CONSTRAINT
I
nvoice
_
G
oods

FOREIGN KEY(FK_

I
nvoice
)

REFERENCES

I
nvoice

(
ID
_

I
nvoice
)


Полный

синтаксис

ограничения

внешнего

ключа

(
с

возможностью

создавать

огран
и-
чения

на

основании

нескольких

полей
)
приведен

ниже
:

[
CONSTRAINT

имя

внешнего

ключа
]
FOREIGN

KEY

(столбец [, столбец …
]
)


REFERENCES

родительская

таблица (столбец [, столбец

…])


18



|

CASCADE

|


|




[ON UPDATE (NO ACTION

|

CASCADE

|


|



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

Эти опции
позволяют определить различные действия при изменении или удалении
значения внешнего ключа. Если не применять этих опций, то по умолчанию будет реализ
о-
ванна опция
NO

ACTION
.

Более подробную информацию смотрите в книгах
[3, 4]

и в док
у-
ментации
InterBase/Fir
ebird
.


Выборка данных из таблиц, оператор
SELECT

1)
Синтаксис команды

SELECT


[
DISTINCT
] {

*
|
<список полей>
}

FROM


список таблиц


[
WHERE



условия отбора

]

[
ORDER

BY



список полей для сортировки

]

[
GROUP

BY


список

полей для группировки



[
HAVING


условия группировки

]
]

[
UNION


вложенный оператор
SELECT

]
;

Результатом является выборка данных из БД.

Замечания.

а) обязательными являются только

первые две строки


список полей и список



таблиц;

б)
DISTINCT



запрещены повторяющиеся записи
;


в)

*



выбрать все поля.

Пример
.

Выбрать все записи из одной таблицы
:

SELECT

*

FROM

Student
;

Пример
.
Выбрать два поля из одной таблицы

(
задает также и порядок полей
)
:

SELECT

NumberStud
,
FIO

FROM

Student
;

В списке полей выше используется сокращенный вариант
списка полей. Те же самые з
а-
просы в полном варианте имеют

вид
:

Пример
.

Выбрать все записи из одной таблицы
:

SELECT

Student
.*

FROM

Student
;

Пример
.
Выбрать два поля из одной таблицы
:

SELECT

Student
.
NumberStud
,
Student
.
FIO

FROM

Student
;

19


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

В строке
FROM

можно использовать вариант
:

FROM


имя таблицы

[
AS
]


новое имя таблицы



Это новое имя таблицы (обычно сокращение от всего имени) можно использовать в др
у-
гих местах оператора
SELECT

вместо настоящего имени таблицы.

Пример
.

Выбрать все записи из одной таблицы
:

SELECT

St
.*

FROM

Student

AS St
;

Пример
.
Выбрать два поля из одной
таблицы
:

SELECT

St
.
NumberStud
,
St
.
FIO

FROM

Student

St
;


Замечание
.

г
)
можно получать вычисляемые поля
:

Пример
.

Создание двух вычисляемых полей

SELECT

NumberStud

+ 1, “


” ||
FIO

FROM

Student
;


2
)
Условия отбора записей

Для задания условий отбора записей в
SQL

используется ключевое слово
WHERE

опер
а-
тора
SELECT
.

Допустимые

операции
: =�, , , , -;退=, =, &#x-500; (
или

!=), !�, !

Пример
.

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

SELECT

*

FROM

Session

WHERE

mark
=5
;

2.1)

LIKE




сравнение по частичному совпадению, используется сравнение с шаблоном
;

%


замещение любого числа символов (количество

=
0
)

_


замещение одного символа

Пример
.

Все

начинающиеся на


А
”:

SELECT

*

FROM

Student WHERE

Fio LIKE “A%”;

Пример
.

Есть

буква


а

или


А
”:

SELECT

*

FROM

Student WHERE

UPPER(Fio) LIKE “
%
А
%”;


2.2)
IS

[
NOT
]
NULL



проверка на пустое
/
непустое значение
;

Пример
.

Все записи с незаполненной оценкой

SELECT

*

FROM

Session

WHERE mark IS NULL
;


20


2.3) [
NOT
]
IN



проверка

на

вхождение
:

Пример
.




(

алгебра

,

мат
.
ан
.
’)


2.4)



проверка на вхождение в диапазон
;

Пример
.

… WHERE

BirthDay

BETWEEN “1.0
1.
1990

AND


31.12.1990



2.5)
AND
,
OR
,
NOT



логические операции. Можно объединять несколько условий, испол
ь-
зуя логические операции и круглые скобки.


Пример
.

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

SELECT

*

FROM

Session

WHERE (
(
mark
=
4
)

OR (mark
=
5)) AND (Fio LIKE “A%”)
;


3)
Сортировка записей.

Можно

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

Для задания сортировки используется
ORDER

BY
.


DESC



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

SELECT





ORDER

BY


поле
1� [
DESC
],



поле
N
� [
DESC
];

Пример
.
Выбрать все поля из таблицы, показать в отсортированном виде
:

SELECT *

FROM Student

ORDER BY
kurs DESC, group, Fio;

4
)
Группирование

записей.

Записи набора данных могут быть сгруппированы по некоторому признаку. Группу обр
а-
зуют записи с одинаковым значением в полях, перечисленных в списке операнда
GROUP


BY
. При группировании записей часто используются агрегатные (или статистич
е-
ские) функции
:
AVG
,
MAX
,
MIN
,
SUM
,
COUNT
.


Пример
.
Показать среднюю оценку для каждого студента
:

SELECT

NumberStud
,
AVG
(
Mark
)

FROM

S
ession

GROUP

BY

NumberStud

Пример
.
Показать среднюю оценку для каждого студента 4
-
го курса
:

SELECT

NumberStud
,
AVG
(
Mark
)

FROM

S
ession

WHERE kurs=4

GROUP

BY

NumberStud

Пример
.
Показать для каждой оценки сколько раз
она встречается
:

21


SELECT

Mark
,
COUNT
(*)

FROM

S
ession

GROUP

BY

Mark

Замечание
.

В строке
SELECT

такого запроса могут появляться только поля из списка
GROUP

BY
, или
поля с агрегатными

функци
ям
и.

Совместно с
GROUP

BY

можно использовать операнд
HAVING
, с помощью которого
задаются дополнительные условия группирования записей. Условия записываются также как
и в случае
WHERE
.


Пример
.
Показать среднюю оценку для студентов, у которых она больше или равна 4,
кроме того, у них должно быть больше 5 оценок
:

SELECT

NumberStud
,
AVG
(
Mark
)

FROM

S
ession

GROUP

BY

NumberStud

HAVING

(AVG
(
Mark
)
�=4)AND(COUNT(Mark)�5)

Пример
.
Показать для каждой оценки сколько раз она встречается, если она встреч
а-
ется чаще десяти раз
:

SELECT

Mark
,
COUNT(*
)

FROM

S
ession

GROUP

BY

Mark

HAVING

COUNT
(*)�10

5
)
Соединение таблиц.

В набор данных можно включать поля из разных таблиц.

5.1
)

Пример
.
Выбрать поля из двух таблиц
:

SELECT

*

FROM

Student
,
Session
;

Замечание
.
При таком запросе получится декартово произведение

записей

таблиц
,
колич
е-
ство записей будет равно произведению количества записей в исходных таблицах
.

Существует также внутреннее и внешнее соединение таблиц.

5.2
)
Внутреннее соединение
:

Внутреннее соединение задается с помощью следующей конструкции
:

SELECT



FROM


Таблица
1

INNER

JOIN


Таблица
�2

ON


условия отбора


Пример
.

SELECT

*

FROM Student INNER

JOIN

Session

ON Student.NumberStud=Session.NumberStud


ORDER

BY

FIO
;

Есть также

старый вариант внутреннего соединения
:

Пример
.

22


SELECT *

FROM Student, Session

WHERE
Student.NumberStud=Session.NumberStud

ORDER

BY

FIO
;

Для соединения таблиц используется поле связи
NumberStud
, которое есть в обеих табл
и-
цах. Будет отображено ровно столько записей, сколько выполнится равенств внутри
WHERE
.
Т.е. если у одного студента (одна запись в таблице
Student
), есть, например, четыре оценки (4
записи в таблице
Session
), то четыре записи и будут отображены. Но (!), если у студента нет
ни одной оценки, то данные о нем вообще не попадут в конечную выборку.

Именно этим
последним свойством внутреннее соединение отличается от внешнего.

5.3)
Вн
ешнее

соединение
:

Внешнее соединение задается с помощью следующей конструкции
:

SELECT



FROM


Таблица
�1 [

Вид соединения

]

[
OUTER
]

JOIN


Таблица
�2

ON


условия отбора


Н
а месте вид соединения могут стоять слова
LEFT

или
RIGHT
, причем первое из них я
в-
ляется умалчиваемым, поэтому его можно не писать. Оно означает, какая из двух таблиц я
в-
ляется главной в этом объединении


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

Кл
ю-
чевое слово
OUTER

является необязательным.

Условия отбора указываются также как и во внутреннем соединении.

Пример
.

SELECT *

FROM Student LEFT JOIN Sessi
on

ON

Student.NumberStud =Session.NumberStud

ORDER BY FIO
;


6)
Вложенные запросы

6.1) [
NOT
]
IN



в проверке

на вхождение

список з
начений за словом
IN

не обязательно
является

перечислением каких
-
то значений, он может формироваться на основе другого з
а-
проса.

Пример
.
Показать

ФИО

студентов

имеющих двойки

SELECT

Fio

FROM Student

WHERE Student.
NumberStud

IN


(SELECT Se
ssion.NumberStud


FROM Session



WHERE
Mark
=2)

Пример
.
Коррелированный запрос. Выборка студентов сдававших один экзамен н
е-
сколько
раз.

23


SELECT

*

FROM S
ession

S1

WHERE S1
.
NumberStud


IN


(SELECT S
2
.
NumberStud


FROM
S
ession S2



WHERE
S
1
.
NumberStud =


S
2
.
NumberStud

AND
S
1
.


=
S
2
.

AND
S
1
.
ID


&#x-500;
S
2
.
ID
)
;

6.2) [
NOT
]
EXISTS



[
не
]
существование


Пример
.
Однофамильцы

SELECT *

FROM
Student St
1

WHERE EXISTS


(
SELECT
*


FROM Student St2



WHERE
S
t1
.
Fio =


S
t2
.
Fio

AND
S
t1
.
NumberStud&#x-500;
S
t2
.
NumberStud
)
;

6.3)
UNION

позволяет объединять несколько запросов в один. У запросов
должно быть
одинаковое количество столбцов и их тип.

Пример
.
Объединение курса, группы и оценки в один столбец

SELECT

kurs
FROM
Student

UNION


SELECT
group FROM Student


UNION


SELECT
mark FROM Session

Модификация

записей

Модификация заключается в редактировании, добавлении и удалении записей. Язык
SQL

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

1)

Редактирование записей.

Редактирование

записей представляет собой изменение полей в группе записей. Выпо
л-
няется следующим

оператором
:

UPDATE


имя таблицы






имя поля
�=
выражение
�,




имя поля
�=
выражение


[
WHERE


условия отбора
�];

Присваивает новые значения полям, которые удовлетворяют условию
WHERE
.

24


Замечание.

Команда является опасной, способна изменить
/
уничтожить все
данные в та
б-
лице
!

Условие отбора
WHERE

является необязательной частью
, но если ее пропустить, то
присвоятся значения во всех записях таблицы
!

Пример
.
Перевод студента с номером
123456

в третью группу.

UPDATE Student


WHERE NumberStud
=123456;

Для того

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


Пример
.
Переход всех на следующий курс.

UPDATE Student


kurs

=
kurs

+ 1;

Пример
.
Переход всех у кого нет двоек на следующий
курс.

UPDATE Student


WHERE NOT
EXISTS


(
SELECT
*


FROM Session

S


WHERE
S
tudent
.
NumberStud =
S.
NumberStud

AND
S.
mark=2
)
;


2
)
Вставка записей
.

Вставка записей осуществляется с помощью оператора
INSERT
, который имеет два
формата
:

для вставки одной записи и для вставки группы записей.

а) Вставка одной записи.

INSERT

INTO


имя таблицы


[
(

список полей

)
]

VALUES

(
список значений
�)
;

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

Пример
.
Вставка в таблицу одной записи: добавление одного студента.

INSERT

INTO

Student


(
NumberStud
,

FIO
,

kurs,

gruppa
)

VALUES

(10, ‘
Иванов И.И.

, 1, 1
);

б
)
Вставка

группы

записей
.

В данном случае вставляются значения отобранные оператором
SELECT
. Количество
вставляемых записей равно количеству отобранных оператором
SELECT

строк.

INSERT

INTO
имя таблицы


(

список полей

)

25


оператор
SELECT
;


Пример
.
Вставка нескольких записей
:

добавление записей в таблицу «Сессия» для
всех студентов 4
-
го курса.

INSERT

INTO
Session


(
NumberStud
,

)


SELECT

St.NumberStud, ‘
Базы

данных



FROM Student St


WHERE

St
.
kurs
=4;


3
)
Удаление записей
.

Удаляет записи, которые удовлетворяют условию отбора.

DELETE

FROM


имя таблицы


[
WHERE


условия выбора
�];

Замечание.

Условие отбора
WHERE

является необязательной частью
, но если ее пропу
с-
тить, то будут удалены все записи
!





26


II
.
Разработка приложений баз данных InterBase/
Firebird

на Delphi


Подключение к БД из
Delphi

Б
иблиотек
и доступа
InterBase

Информацию о библиотеках доступа см. в книгах
[3, 4]

и в документации
InterBase/Firebird
.

В этом пункте приводится краткое описание, осн
ованное на этих источн
и-
ках.


Для доступа к БД
InterBase
/
Firebird

из сред разработки приложений, например,
Delphi
,
Visual

Studio
,
Java

и др., можно использовать низкоуровневый интерфейс
InterBase API
:

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


библиотеки доступа.

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

Для InterBase можно

выделить около пяти таких подходов: это работа с базой данных через BDE (
Borland

Dat
a-
base

Engine
), использование ODBC, применение OLE DB (ADO), работа через dbExpress и
библиотеки прямого доступа.

В

бесплатной версии
Turbo

Delphi

нет компонент с прямым д
оступом к
InterBase
.
П
о-
этому мы будем использовать более старую стандартную технологию доступа к
InterBase



BDE
.
Она не учитывает всех особенностей

InterBase
, но набор основных компонент совпад
а-
ет и базовые возможности у них одинаковые, нет специфических
для
InterBase

возможностей.


Создание

псевдонима

в

BDE

Для доступа к базе данных мы будем использовать библиотеку доступа
BDE

(
Borland

Database

Engine
)
.
Перед тем как подключаться в
Delphi

к базе данных, используя драйверы
BDE
, нужно создать псевдоним
(
Alias
)

базы данных в утилите
BDE

Administrator

(
C:
\
Program
Files
\
Common Files
\
Borland Shared
\
BDE
\
bdeadmin.exe
)
.

27



Для создания псевдонима нужно
:

1)

Выбрать пункт меню
Object → New

2)

В открывшемся окне выбрать
INTRBASE

(как показано на рисунке выше).

3)

В левом окне выбрать имя псевдонима


это имя будет использоваться в
Delphi

4)

В правом окне заполнить параметры
:

LANGDRIVER
=

Pdox

ANSI

Cyrillic

(
поддержка русского языка
)

SERVER

NAME
=


имя сетевого компьютера с сервером
:
D
:
\
public
\
имя


файла


(здесь
заполняе
тся имя сервера и через двоеточие имя файла и путь к нему на сервере
;

если
сервер локальный, то

localhost
:
путь и имя файла

)

USER NAME=SYSDBA

5)

И сохранить псевдоним
,

выбрав пункт меню
Object → Apply

Подключение

в

Delphi

InterBase/Firebird

BDE

Delphi


файл БД





псевдоним
BDE





Компоненты
:




Для соединения с БД используются следующие компоненты
:


Компонент
Database


(страница
BDE

палитры компонентов). Осуществляет связь с БД,
может управлять транзакциями. Параметры
:

AliasName
=

выбрать из списка псевдоним
BDE

DatabaseName
=
внутренний псевдоним в
Delphi

Connected
=
True



если устанавливается, значит есть подключение к БД.


28


Компоненты
Table



или
Query

.
Table

способен соединяться с одной таблицей,
Query



получает набор данных н
а основе
SQL

запроса.

Выберите любой из них и задайте параметры
:

DatabaseName
=
внутренний псевдоним в
Delphi
, который был задан выше

TableName
=
выбрать из списка имя таблицы (у компонента
Table

или)

SQL
=
SQL
-
запрос (у компонента
Query
)

Active
=
True


Компонент источник данных
DataSource

(страница
DataAccess

палитры компонентов)



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

Параметры
:

=
выбрать из списка набор данных


И выбрать какой
-
нибудь визуальный компо
нент на странице
DataControls

палитры комп
о-
нентов, например,
DBGrid



отображение данных в виде таблицы


Параметры
:

DataSourse
=

выбрать из списка

источник данных


Замечание

1
.

Это стандартный минимальный набор компонентов для связи с БД. Компонент
Database

является необязательным. Если он не добавлен, то он автоматически создается
De
l-
phi

и

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

Замечание

2
.

Кроме этих компонентов, есть компонент
Session

, который также являе
т-
ся необязательным, но создается автоматически
Delphi

при

установке соединения. Он позв
о-
ляет задавать параметры соединения.

Замечание

3
.

При использовании

технологии прямого доступа н
а странице

InterBase

пали
т-
ры компонентов есть аналогичные компоненты доступа, как и на странице
BDE
, плюс еще
один компонент
IBTransaction



который позволяет явно управлять транзакциями в
InterBase
.

Компоненты аналогичны, но на странице
BDE

используется более старая универсальная те
х-
нология доступа
BDE
, а на странице
InterBase

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


29


Наборы

данных


(
TTable

и

TQuery
)

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

выбираться могут не все данные одной таблицы. Класс
TDataSet

явл
я-
ется родительским классом для всех наборов данных. Его потомками в частности являются
классы
TTable

и

TQuery
. Он

содержит в себе

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

Компонент
TTable

выбира
ет

данные только из одной таблицы. Для доступа к ней и
с-
пользуются свойства
DatabaseName



расположение БД


и
TableName



имя табли
цы.


Компонент

TQuery

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

задает

расположение БД
, а набор данных формируется на основе запроса
SQL
,
записанного в его свойстве с именем

SQL
.

Формируется набор данных при открытии его методом

Op
en

или после присваивания
свойству
Active

значения
True
.

Метод
Close

или
Active
:=
False

закрывают набор данных.

Наборы данных могут находиться в различных режимах. Текущий режим набора да
н-
ных определяется свойством
State
:
dsInactive



неактивный,

dsBrowse



просмотр,
dsEdit



редактирование,
dsInsert



вставка,
dsSetKey



поиск

и др
.

Навигационный способ доступа к данным

заключаетс
я в обработке каждой отдел
ь-
ной записи набора данных
.

Достоинством его является простота программирования работы с
БД. Недостатком



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

от него
реляционный способ доступа к данным

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

Рассмотрим здесь навигационный способ доступа к данным.


Навигаци
я по набору данных

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

TDBGrid

выделяет
текущую запись цветом. Для перемещения по записям используются визуальные компоне
н-
ты
TDBGrid

и
T
DBNavigator
.




30


Для перемещения по записям применяются сл
едующие методы набора данных.

Метод/Свойство

Описание

First

перейти на первую запись в наборе данных

Next

на следующую

Last

на последнюю

Prior

на предыдущую

MoveBy
(
Distance:integer
)
:integer

перемещение с шагом
Distance
, как вперед, так и назад,
результат


на сколько позиций в действительности пер
е-
местился указатель

RecNo

номер текущей записи, нумеруются с 1

RecordCount

количество записей

BOF:Boolean

признак начала набора данных

EOF:Boolean

признак конца набора
данных


Замечание.
При

изменении порядка сортировки или включения фильтрации измен
я-
ется порядок записей.


Пр
имер

1. Обход всех записей в наборе данных.

procedure

TForm1.Button
1
Click(Sender: TObject);

var

i, kol
:

integer;

begin


kol := 0;


Table1.First;


for

i := 1
to

Table1.RecordCount
do begin



if

Table1.FieldByName(
'
kurs
'
).AsInteger
=4
then


kol

:= kol + Table1.FieldByName(
'
kurs
'
).AsInteger;



Table1.Next;


end
;


Label1.Caption := IntToStr(kol);

end
;

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

набора данных
DisableControls
, а в конце цикла включить

EnableControls
.

При длительной обработке желательно пользователю показывать информацию о ходе
процесса, например, с помощью компонента
TProgress
Bar
. Также во время обработки пр
о-
грамма перестает реагировать на сообщения. Для избежания этого, а также для возможности
прерывания процесса пользователем
,

можно использовать метод
Application
.
ProcessMessages
.

31


Пр
имер

1
а
. Обход всех записей в наборе
данных.

procedure

TForm1.Button
1
Click(Sender: TObject);

var

i, kol
:

integer;

begin


Button1.Enabled

:= False;


Table1.
DisableControls
;


kol := 0;


Table1.First;


while

not

Table1.
EOF

do begin


Application.ProcessMessages
;



if

Table1.FieldByName(
'
kurs
'
).
AsInteger
=4
then


kol

:= kol + Table1.FieldByName(
'
kurs
'
).AsInteger;



Table1.Next;


end
;


Label1.Caption := IntToStr(kol);


Table1.
Enable
Controls
;


Button1.Enabled := True;


Beep
;

end
;


Модификация набора данных

представляет собой редактирование,
добавление и
удаление его записей
.

Свойство
ReadOnly

(
п
о умолчанию
равно
False
) управляет возможностью изменения
набора данных.

Для компонента
TQuery
, кроме этого, определяют возможность редактир
о-
вания еще два свойства
:
Reque
s
tLive

(
п
о умолчанию
False
)

и
доступное только для чтения

CanModify

(
True

для простейших операторов
SELECT
).

Визуальные компоненты автоматически переводят набор данных в состояние реда
к-
тирования при начале ввода данных пользователем, в случае, если свойство
AutoEdit
=
True

(
по умолчанию
)
. При нажатии клавиши
Enter

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

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

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


Метод/Свойство

Описание

Edit

переводит набор данных в режим редактирования, текущая запись до
с-
тупна для редактирования

Insert

переводит набор данных в режим вставки, добавляет новую пустую з
а-
32


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

Append

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

Post

принять изменения, перейти в режим просмо
тра

Cancel

не применять изменения, перейти в режим просмотра

SetFields

установить значения полей записи

InsertRecord

объединяет в себе три метода
Insert
,
SetFields

и
Post

AppendRecord

объединяет в себе три метода
Append
,
SetFields

и
Post


удалить текущую запись


Пр
имер

2
.

Редактирование текущей записи.

procedure

TForm1.Button2
Click(Sender: TObject);

begin


Table
1
.
Edit
;
//
переходим в режим редактирования


{
Изменение

значений
: }



Table
1
.FieldByName(
'
NumberStud
'
).AsString

:=

'
123
'
;

Table
1
.FieldByName(
'
FIO
'
).AsString

:=

'
Иванов

И
.
И
.'
;


Table
1
.FieldByName(
'
kurs
'
).As
Integer

:=

4
;

Table
1
.FieldByName(
'

gruppa
'
).As
Integer

:=

3
;



Table
1
.
Post
;
//
принять изменения

end
;


Пр
имер

3.
Удаление

текущей

записи
.

procedure

TForm
1.
Button
2
Click
(
Sender
:
TObject
);

begin

//
просим подтверждения удаления записи

if

Application
.
MessageBox
(
'
Удалить

запись
?'
,
'
Удаление
...'
,



MB_OKCANCEL + MB_ICONQUESTION)=IDOK
then


Table
1.
;
//
удаляем

запись

end
;


Пр
имер

4
.

Добавление записи.

На форме отображаются данные из двух таблиц
:
«Студент»
(
Table
1
), «Сессия» (
Table
2
). Пользователь выбирает текущую запись в таблице «Студент».
При нажатии на кнопку отображается новая форма, в которой отображен текущий студент, а
также оставлено поле для в
вода оценки и предмета. Пользователь вводит оценку и закрывает
форму кнопкой «
Сохранить
»
.
После этого в таблицу «Сессия» добавляется новая запись.

На форме размещается кнопка Button3 (
Caption
=


Добавить

), создана форма
FormAdd
, на которой пользователь
вводит оценку.

procedure

TForm
1.
Button
3
Click
(
Sender
:
TObject
);

begin

//
FormAdd

-

форма для ввода

значений новой записи
.

33


//
За
полняем данные на форме перед ее отображением
,


//
данные

берем

из

таблицы
:


Form
Add
.Label1
.
Caption

:=
Table
1.
FieldByName
(
'
FIO
'
).
AsString
;



{
пустые

поля оценка и предмет
:}


Form
Add
.
LabeledEdit1.Text := '';


Form
Add
.
LabeledEdit
2.
Text

:= '';


{
Показываем

пользователю

форму

FormAdd
;

при закрытии формы функция
FormAdd.ShowModal
возвращает, какая из
кнопок была нажата (
mrYes




Сохранить

)
}


if

Form
Add.
ShowModal

=

mrYes

then


begin


Table
2
.
Append
;
//
добавить

запись


{
Запись

значений

в

таблицу
: }


Table
2.
FieldByName
(
'
'
).
As
String

:=


Form
Add
.
LabeledEdit
2.
Text
;


Table2
.FieldByName(
'Nu
m
b
er
Stud
'
).
AsInteger

:=


Table1.FieldByName(
'Nu
m
b
er
Stud
'
).AsInteger;


Table
2
.FieldByName(
'Mark'
).AsString:=


Form
Add
.
LabeledEdit1.Text;


Table
2
.
Post
;
//
подтвердить

запись


end
;

end
;


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

Каждое поле набора данных
представляет собой отдельный столбец, для работы с к
о-
торым служит класс
TField

и объекты производных от него типов, например
,

TIntegerField
,
TFloatField

или

TStringField
.

Поля

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

Доступ к полю по имени осуществляется с помощью методов
FieldByName

и
FindField
.

В случае несуществующего имени поля первый метод генерирует исключител
ь-
ную ситуацию, второй


возвращает
Nil
.

Доступ к полю по номеру

осуществляется с пом
о-
щью свойства
Field
s
[
i

].

Значение текущей записи поля можно получить с помощью свойств
Value
:
Variant
,
AsInteger
:
Integer
,
AsString
:
String


и т.п. Тип вариант (
Variant
) автоматически приводится к
требуемому типу. Свойства
As
***
приво
дят значение к указанному в них типу явно. Также
значение текущей записи можно получить с помощью свойства
Field
Values
[‘
имя поля
’] :
Variant
.
Это свойство является

умалчиваемым, поэтому можно к нему обращаться без уп
о-
минания имени свойства.

Пр
имер

5.

procedure

TForm
1.
Button
4
Click
(
Sender
:
TObject
);

var
i, j
: Integer;

34




S
1, S2
: String;

begin

S1 := Table
1
.FieldByName(
'
FIO
'
).AsString
;


{1

способ
}

S2 := Table
1
.FieldByName(
'
FIO
'
).Value;




{1

способ
}

i

:= Table
1
.FindField(
'
kurs
'
).AsInteger;



{
2

способ
}

j

:= Table
1
.Fields[0].AsInteger;




{
3

способ
}

i

:= Table
1
.FieldValues[
'
kurs
'
]
;




{
4

способ
}

i

:= Table
1
[
'
kurs
'
]
;







{
4
а

способ
}

end
;


Компонент
TQuery

В
Delphi

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

является аналогом компонента
TTable
.
Его

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

Его
с
войство
D
atabaseName

задает

расположение БД
, а набор данных формируется на
основе запроса
SQL
, записанного в его свойстве с именем

SQL
.

Формируется набор данных
при открытии его методом

Open

или после присваивания свойству
Active

значения
True
.

М
е-
тод
Close

или
Active
:=
False

закрывают набор данных.

Можно также с помощью этого компонента отправлять на выполнение запросы
SQL

без получения выборки (операторы редактирования, добавления, удаления). Запрос в этом
случае также записывается в его свойстве
SQL

и

вызываетс
я метод
ExecSQL
.

Набор данных, содержащийся в
TQuery
,

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

(
п
о умолчанию
True
) управляет возможностью изменения набора данных.

Для компонента
TQuery
, кроме
этого, определяют возможность редактирования еще два свойства
:
Reque
s
tLive

(
п
о умолч
а-
нию
False
)

и доступное только для чтения

CanModify
.


Свойство
CanModify

имее
т значение
True

только при выполнении следующих усл
о-
вий
:



данные выбираются только из одной таблицы
;



не используется
DISTINCT

и статистические функции
;



нет соединения таблиц
;



нет вложенных запросов
:



нет группировки
;



нет сортировки по неиндексным полям.




35


SQL
-
запросы в
Delphi

Запрос можно сформировать при разработке приложения и в процессе выполнения
приложения.

Пр
имер

1
.

Формирование простейшего
SQL
-
запроса

в процессе выполнения прил
о-
жения
.

На форме находится
TQuery
,
связанные с ним

TDataSource
,

TDBGrid

и

кнопка


О
б-
новить

. Ниже

приведен

код

ее

обработчика

OnClick
.

procedure
TfmMain.Button1Click(Sender: TObject);

begin

Query
1.
Close
;

//
отключаем набор данных

Query
1.
SQL
.
Clear
;

//
очищаем поле
SQL

Query
1.
SQL.Add(‘SELECT * FROM Student’);
//
формируем

Query
1.
SQL.Add(‘ORDER BY Fio’);
//
новый

SQL
-
запрос
;

Query
1.
Open
;

//
отправляем запрос

SQL

и получаем новый набор


//
данных
;

end
;

Запрос с параметрами

Delphi

позволяет добавлять в
SQL
-
запросы параметры. Перед параметром в запросах
ставится
двоеточие
.

Пример
.
Запрос с параметром


pMark


SELECT

*

FROM

Student


WHERE

Mark
=
:
pMark
;

Для параметра обязательно нужно указать тип
:
свойство
Params
[
n
].
DataType
.

Знач
е-
ние ему можно присваивать на этапе выполнения программы
:

Пример
.

Query
1
.ParamByName(‘
pMark’).AsInteger := StrToInr(Edit1.Text);

Замечание.

Для увели
чения скорости выполнения запросов используется метод
Pr
e-
pare



проверяет синтаксис
SQL
-
запроса. После его выполнения, если
SQL
-
запрос не менялся

(
Prepared
=
True
)
, синтаксис проверяться больше не будет.


1.

Сортировка.

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


IndexName



имя индекса или
IndexFieldName



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

Пример

1
.


IndexName=’indFIO’

IndexFieldName=’kurs;group;FIO’

Замечание
.

Индексы
должны быть созданы перед их использованием, например, с помощью
программы
DatabaseDesktop
.

По

умолчанию

записи

в

таблице

отсортированы

по

ключевому

36


полю
.
Установить

сортировку

по

ключевому

полю программно

можно

только с помощью
свойства
IndexFieldName
, т.к. в
Paradox

индекс по ключевому полю не имеет имени.


2.

Поиск
.
Функция


function

Locate(
const

KeyFields: String;
const

KeyValues: Variant;

Options
:
TLocateOptions
):
Boolean
;

устанавливает текущей первую запись, удовлетворяющую условию поиска. Если запись на
й-
дена, возвращает
True
,

в противном случае
False
.

Список полей, по которым ведется поиск,
за
дается в параметре
KeyFields
, поля разделяются точкой с запятой. Параметр
KeyValues

указывает значения полей для поиска.
Options



опции (
loCaseInsensitive



регистр букв не
учитывается,
loPartialKey



допускается частичное совпадение значений).

Пр
имер

2.
На форме присутствуют компоненты
Button
1 (
Caption
=’
Поиск
’)
,

CheckBox
1 (
Caption
=’не

учитывать регистр’), CheckBox2 (Caption=’не точный поиск’)

и

Edit1

(
Text



строка поиска)

procedure

TfmMain.Button1Click(Sender: TObject);

var

t : TLocateOptions;

begin


t

:= [];

{
без


учета

регистра
}


if

CheckBox1.Checked
then

t := t + [loCaseInsensitive];

{ не точный поиск
;

учит
ы
ваются

только первые символы}



if

CheckBox
2.
Checked

then

t

:=
t

+ [
loPartialKey
];


tbStudent.Locate(
'FIO'
,Edit1.Text,t);

end
;

В

случае поиска по нескольким полям для формирования вариантного массива с н
е-
сколькими
значениями

полей

используется функция

VarArrayOf
:

Locate('kurs;group', VarArrayOf([Edit1.Text, Edit2.Text
]),
[]);



3.

Поиск
.

Функция


function
Lookup(
const

KeyFields
: String;
const

KeyValues: Variant;

const

ResultFields: String): Variant;

ищет

значения

KeyValues

полей

KeyFields

и

в

случае

удачного

поиска
,
возвращает

значения

полей

соответствующие

ResultFields
.
В случае неудачного поиска возвращает
NULL
.

Пр
имер 3.
На форме присутствуют компоненты
Button
2

(
Caption
=’
показать курс студента
’)

и

Edit1

(
Text



строка поиска)

procedure
TfmMain.Button2Click(Sender: TObject);

var
V

: Variant;

begin

37



V

:= tbStudent.Lookup(
'FIO'
,Edit1.Text,
'kurs'
);


if
VarIsNull(
V)

then
Label1.Caption :=
'поиск не дал результата'


else
Label1.Caption :=
'курс: '

+ IntToStr(V
);

end
;


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


var

V
:
Variant
;
A
:
integer
;
B
:
String
;




if

not

VarIsNull
(
V
)
then

begin


A

:=
V
[0];


B

:=
V
[1];


ShowMessage(
'
Результат
: '

+ IntToStr(A
)

+
‘ ’

+ B)
;

end
;


4
.
Поиск по индексным полям.

Для набора данных
Table

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

предн
а-
значен для поиска на точное соответствие, а
FindNearest

для поиска на частичное совпадение.

function

FindKey(
const
KeyValues:
array of const
): Boolean;

procedure

FindNearest(
const

KeyValues:

array of const
);

Пример

4.

procedure

TForm1.Button3Click(Sender: TObject);

begin


Table1.IndexName := '

indFIOKursGruppa
';


Table1.FindNearest([Edit1.Text, Edit2.Text, Edit3.Text]);

end
;


5
. Фильтрация по выражению.

Фильтрация



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

типа
String
.
В фильтр мо
гут входить следующие элементы
:
имена полей таблиц, литералы, опер
а-
ции сравнения, арифметические операции, круглые скобки.

Пример

5
.


Filter


:= ‘
Salary=2000
’;

Filter


:= ‘(Post
=
’’
Директор
’’)or(Post
=
’’
Зам
.
директора
’’)’;

Filter


:=’(Fio>=’’
а
’’) and (Fio<
=’’
б
’’)’

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

38


Для активизации и деактивизации фильтра применяется свойство Filtered типа
Bool
e-
an
.
Параметр
ы фильтрации задаются с помощью свойства
FilterOptions
:

foCaseInsensitive



регистр букв не учитывается
;

foNoPartialCompare



выполняется проверка на полное соответствие.


6
. Фильтрация по диапазону.

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

знач
е-
ние

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

или
IndexFieldNames
.


procedu
re

SetRange(
const
StartValues, EndValues:
array of
const
);

Выполнить фильтрацию

procedure

CancelRange;

Отменить фильтрацию


Пример
6
.

Фильтровать

записи

по
фамилии, в зависимости выбран
CheckBox
1
.
Checked

или
нет. Показать, начиная со значения

установленного в
Edit
1.
Text

и до конца
.

procedure

TfmMain.CheckBox
1
C
lick(Sender: TObject);

begin


if

CheckBox
1
.
Checked
then


begin


Table1.
CancelRange;


Table1
.IndexName :=
’indFIO’;


Table1
.SetRange([Edit
1
.Text],['
яяя
’]);


end


else

Table1
.CancelRange;

end
;


7
. Навигация с псевдофильтрацией.

Система
Delphi

предоставляет возможность перемещения по набору данных,

как по
отфильтрованному, при выключенной фильтрации. Методы навигации
:

FindFirst
,
FindLast
,
FindNext

и
FindPrior
.




39


8
.
Переход по закладкам.


Закладка


специальная пометка записи, имеет тип
TBookmark
, указатель на запись
набора данных.

Функция

Описание

function

GetBookmark: TBookmark;

Создание закладки. Возвращает ссылку на т
е-
кущую запись.

procedure

GotoBookmark(Bookmark:
TBookmark);

Переход на установленную закладку.

procedure

FreeBookmark(Bookmark:
TBookmark);

Удаление закладки. Очищает память и устана
в-
ливает значение
Bookmark

в
nil
.

function

BookmarkValid(Bookmark:
TBookmark): Boolean;

Проверяет, задана закладка или нет.


Пр
име
р

7
.

Создаем закладку на текущую запись, просматриваем все записи, и восстанавл
и-
ваем текущую запись.

bm : TBookmark;



procedure
TfmMain.Button1Click(Sender: TObject);

begin

//
создаем

закладку


bm

:=
Table
1.
;

//
отключаем

визуальные

компоненты


Table
1.
DisableControls
;


Table1
.First;


while not
Table1.Eof

do


begin


//

Обработка записей


Table
1.
Next
;


end
;

//

переход

на

закладку

bm


if
Table1.BookmarkValid(bm)

then
Table1.GotoBookmark(bm);

//

Освобождение

закладки

bm


if
Table1.BookmarkValid(
bm)

then
Table1.FreeBookmark(bm);

//
включаем

визуальные

компоненты


Table
1.
EnableControls
;

end
;




40


Объект поле (
TField
), ф
ормирование текстового

представления поля, проверка правильности вводимого в поле значения


Каждое поле набора данных представляет
собой отдельный столбец, для работы с к
о-
торым служит класс
TField

и объекты производных от него типов, например
,

TIntegerField
,
TFloatField

или

TStringField
.

Тип выбирается

автоматически

Delphi

в зависимости от типа
столбца в БД.
Поля

создаются у набора д
анных либо автоматически
Delphi

(называется
д
и-
намическим созданием полей
)
,
либо программистом (
статическое создание полей
) с пом
о-
щью
редактора полей

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

появляется возможность создания вычисляемых полей,
полей выбора и полей не связанных с БД.

Редактор полей



открывается либо из контекстного меню набора данных (например,
TTable
), пункт меню

Fields

Editor

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

полей
, пункты меню

Add

Fields

или


Add

all

Fields


В инспекторе объектов можно задать заголовок поля

(надпись)
DisplayLabel
, длину
пол
я

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

Далее рассматриваются события

связанные с полями
TField
.

Событие
OnGetText

возникает перед выводо
м значения поля на экран
.

Пример 1. Формирование текстового представления поля.

В обработчике
OnGetText

можно задать представление, в котором данные будут в
ы-
водиться на экран. В случае DisplayText=True


для просмотра, DisplayText=False


для р
е-
дактирования. В примере ниже в режиме просмотра вместо цифр будет выводиться текст.

procedure

TForm
1.
Table
2
(
Sender
:
TField
;
var

Text
:
string
;


DisplayText: Boolean);

begin

{
Sender



ссылка на объект
-
поле. В переменную
Text

передается пре
д-
ставление значения поля на экране.}

if

DisplayText

then

41



case

Sender.AsInteger
of


2: Text := '
неудовл
.';


3: Text := '
удовл
.';


4: Text := '
хорошо
';


5: Text := '
отлично
';


else

Text := Sender.AsString;


end
{case}

else

{
DisplayText

= False}


Text := Sender.AsString;

end
;

Замечание
.

Для задания формата вывода данных существует еще два свойства:
DisplayFormat



для режима просмотра и
EditFormat



для режима редактирования.

Пример 2. Объект
TDateField



поле для работы со значениями типа дата.

1) Формат вывода даты:

Свойство

DisplayFormat

:= ‘
d

mmm

yyyy

(
ddd
)’;

DisplayWidth

:= 14; (установить ширину поля).

Пример вывода: “1 янв 2005 (Сб)”;

2) Существует также свойство

EditMask



маска для ввода да
нных

Пример маски для ввода даты
:
EditMask

:=

!99/99/9900;1;*

;


Событи
я

OnSetText

или
OnValidate

возникают при попытке записать данные.

Но действуют они по разной схеме:




в обработчике мы либо сами записываем новое значение, либо игнорир
у-
ем его, и тогда в поле остается старое значение;

OnValidat
e



в обработчике мы можем прервать запись нового значения вызвав и
с-
ключительную ситуацию, и тогда набор данных остается в режиме редактирования пока мы
не введем правильного значения. Если мы не п
рерываем обработчик, то новое значение пр
и-
нимается
.


Пример 3. Проверка правильности ввода данных.

1) В обработчиках
OnSetText

или
OnValidate

можно проверять вводимые пользователем зн
а-
чения. В двух примерах ниже проверяется, принадлежит ли оценка интервалу 1..5, и в случае
неправильного ввода, выдается сообщение.

procedure

cons
t Text:
string
);

begin

{
Sender



ссылка на объект
-
поле. Введенное пол
ьзователем значение пер
е-
дается через переменную
Text
. В случае если
Text

удовлетворяет условиям
проверки, нужно присвоить полю новое значение: Sender.AsString :=
T
ext.
В случае неправильного ввода выдается сообщение об ошибке и автоматич
е-
ски сохраняется ст
арое значение.}


if

�(StrToInt(Text)=1)
and
(StrToInt(Text)=5)
then

42



//установка значения в случае правильного ввода


Sender
.
AsString

:=
text

else



// вывод сообщения об ошибке


Application
.
MessageBox
('Оценка должна быть от 1 до 5',


'Ошибка ввода',MB_OK +
MB_ICONERROR);

end
;


procedure

TForm1.Table2MarkValidate(Sender: TField);

begin

{
Sender



ссылка на объект
-
поле. Введенное пользователем значение с
о-
держится в поле Sender.
Value
. В случае ввода, не

удовлетворяющего усл
о-
виям проверки, нужно прервать выполнение процедуры, вызвав исключител
ь-
ную ситуацию, например, вызвав функцию Abort. Таблица будет оставаться
в режиме редактирования, пока пользователь не введет правильное знач
е-
ние, или не нажмет
Escap
e

(отказ от изменения данных и восстановление
старого значения).}


if

not
�((Sender.AsInteger=1)
and
(Sender.AsInteger=5)) then


begin


Application.MessageBox('Оценка должна быть от 1 до 5',


'
Ошибка

ввода
',
MB
_
OK
+
MB
_
ICONE
RROR
);


Abort;
// прерываем запись значения поля


end
;

end
;

2) Можно использовать также для проверки правильности ввода данных свойства:
CustomConstraint

(условие) и
ConstraintErrorMessage

(сообщение об ошибке), например:

CustomConstraint := ‘(Mark>
=2) and (Mark<=5)’;

ConstraintErrorMessage

:= ‘
Оценка

должна

быть

от

1
до 5

;.

Замечание.

Эти свойства игнорируются, если есть обработчики
OnSetText

или
OnValidate
.


Создание вы
числяемых полей и полей выбора

1.

Создание вычисляемого поля.


Вычисляемые п
оля


поля, не хранящиеся в БД, а вычисляемые в программе. Их зн
а-
чения зависят обычно от значений других полей БД. Например, в БД задана стоимость тов
а-
ра и его количество, а вычисляется стоимость=цена*количество.

Наборы данных в
Delphi

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

Это не единственный способ создания
вычисляемых полей. Можно также задать вычисляемое поле в
SQL
-
запросе при создании
таблицы, или можно их создавать в запросах
SELECT
.
Во всех этих случаях вычисляемое
поле не хранится в базе данных, а вычисляется при необходимости. Если вычисляемое поле
43


создается с помощью операторов
SQL
, то вычисляет значения сервер, если же оно создается
в
Delphi
, то вычисление происходит в программе в

обработчике набора
данных
OnCalcFields
.

Вычисляемые поля создаются с помощью
редактора полей

набора данных.
Редактор
полей

открывается либо из контекстного меню набора данных (например,
TTable
), пункт м
е-
ню

Fields

Editor

, либо двойным щелчком на наборе д
анных.


В контекстном меню р
едактор
а

полей
, нужно выбрать пункт

New

Field

.

После этого
откроется окно изображенное на рисунке
:




В этом окне

заполн
яются следующие параметры вычисляемого поля
:

Name

Имя

создаваемого вычисляемого поля

Component

Имя объекта
TField
, связанного с вычисляемым полем (формируется
автоматически
Delphi
).

Type

Тип
вычисляемого поля

Size

Размер. Заполняется только для строкового типа.

Field type

=Calculated (
вычисляемое поле
)

После этого в наборе данных появляется
новое вычисляемое поле. Его значения ну
ж-
но заполнять в обработчике события
OnCalcFields

набора данных
.

Пр
имер

1.

Создание вычисляемого поля. Преобразование даты
р
ождения (поле
данных) в возраст (вычисляемое поле).

Используется набор данных
Table
1
, у которо
го одно из полей имеет имя
Birthday



день рождения
.


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

Name
=
CalcAge

целого типа.
Вычисляемое поле
заполняется при обработке события

OnCalcFields

набора данных
Table
1
:

44


Используемые
ф
ункции

Описание

Date

возвращает текущую дату

DecodeDate(Date,
Year, Month,
D
ay)

переводит первый

п
араметр

типа TDateTime в три числа: год,
месяц, день


procedure


var

YearBirthday, MonthBirthday, DayBirthday,


YearToday, MonthToday, DayToday : Word;


age: Integer;

begin


DecodeDate(Table1.FieldByName(
'Birthday'
).Value, YearBirthday,
MonthBirthday, DayBirthday);


DecodeDate(Date, YearToday, MonthToday, DayToday);


If
(MonthBirthdayMonthToday)
or

((MonthBirthday=MonthToday)
and



(DayBirthday=DayToday))
then



age := YearToday
-

YearBirthday


else

age := YearToday
-

YearBirthday
-

1;

{
заполняем

вычисляемое

поле
: }


Table1.FieldByName(
'CalcAge'
).AsInteger := age;


end
;


2.
Создание
поля

выбора.

Поле выбора


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

Поле выбора также как и вычисляемое п
оле создается с помощью
редактора полей

набора данных. В контекстном меню р
едактор
а

полей
, нужно выбрать пункт

New

Field

.


В открывшемся окне

заполн
яются следующие параметры
:

Параметр

Пояснение

Name

Имя

создаваемого поля выбора

Component

Имя объекта
TField
, связанного с новым полем (формируется авт
о-
матически
Delphi
)

Type

Тип
поля

Size

Размер. Заполняется только для строкового типа.

Field type

=Lookup (
поле выбора
)

Key Fields

Поле связи, значение которого используется для связи с другим н
а-
бором
данных


Набор данных, из полей которого берется подстановочное поле

45







DataSet

Lookup

Keys

Result

Field

Key Fields

Создаваемое новое поле

Связь между
наборами
данных

список, формируется из
значений
Result

Field


Пользователь выбирает значение в списке. С этим значением связано поле
Lookup

Keys
. После выбора происходит присваивание

Key

Fields

:=
Lookup

Keys

и

Поле

выбора

:=
Result

Field


Lookup

Keys


и поле

Result

Field

, отображаемое в выпадающем
списке для выбора пользователем.

Lookup

Keys

Подстановочное поле


поле связи с

Key

Fields

.
Поля

Key

Fields


и

Lookup

Keys


должны совпадать по типу. Обычно поле

Lookup

Keys


является ключевым в главной таблице,

а поле

Key

Fields




полем связи в подчиненной таблице.

После выбора пользователем значения в выпадающем списке, знач
е-
ние

Lookup

Keys


присваивается пол
ю

Key

Fields
”.

Result

Field

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

Key Fields := Lookup Keys и Поле выбора :=Result Field.

Тип создаваемого поля должен совпадать с типом

Result

Field

.





Замечание

1
.

Поля

Lookup

Keys

и

Result

Field

могут совпадать, что позволяет сделать поле
выбора со значениями
,

совпадающими с
Key

Fields
.

Т.е. то же самое поле
Key

Fields
, но у н
е-
го есть список выбора.

Замечание

2
.

Обновляет список выбора метод
RefreshLookupList
.

Замечание

3
.

Создать список выбора у

поля можно иначе, не создавая поля выбора, а с п
о-
мощью визуальных компонент
T
DBLookupListBox

или
T
DBLookupComboBox
.

Пр
имер
2
.

Создание поля выбора.

Используются два набора данных
Table
1

(Студент)

и
Table
2

(Сессия). Поле выбора созд
а-
ется в

Table
2
. Для
нового поля выбора присваиваются следующие значения
:

П
араметр

Значение

Name

LookUpFIO

Component

Table
2
LookUpFIO

46


Type

String

(
должен совпадать с типом
FIO
)

Size

30

(
должен совпадать с типом
FIO
)

Field type

Lookup

Key Fields

NumberStud

(
поле связи с
таблицей Студент
)


Table1

(таблица Студент)

Lookup Keys

NumberStud

(
ключевое поле в таблице Студент
)

Result Field

FIO


Замечание.

Поле
NumberStud

в таблице Сессия можно сделать невидимым (
Vis
i-
ble
:=
False
)
.


Источник данных
TDataSource

Источник данных
TDataSource

используется как промежуточное звено между набор
а-
ми данных и визуальными компонентами. Для указания набора данных, с которым он связан,
служит свойство
. Визуальные компоненты связаны с источником данных через свои
свойс
тва
DataSource
.

Два
свойства
TDataSource

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

Свойство
AutoEdit

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

С помощью свойства
Enabled

можно включать/отключать визуальные компоненты, анал
о-
гично методам набора данных
EnableControls
/
DisableControls
.

События

TDataSource
:

Событие
OnStateChange

генерируется при изме
нении состояния
State

набора данных

(
с
о-
стояние просмотра, редактирования, поиска и т.п.
)
.

Событие
OnDataChange

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


Событие
OnUpdateData

генерируется непосредственно перед записью измененных данных
в БД.


Пример 1.
Событие
OnDataChange

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

procedure

TForm1.DataSource1DataChange(Sender: TObject; Field: TField);

begin


StatusBar1.Panels[0].Text :=
'
Запись

№ '

+ IntToStr(Table1.RecNo);

end
;

47



Пример
2
.
Событие
OnStateChange

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

procedure

TForm1.DataSource1StateChange(Sender: TObject);

begin


case

Table1.State
of


dsInactive


:

StatusBar1.Panels[1].Text :=
'
Отключен
'
;


dsBrowse


:

StatusBar1.Panels[1].Text :=
'
Просмотр
'
;


dsEdit


:

StatusBar1.Panels[1].Text :=
'
Редактирование
'
;


dsInsert


:

StatusBar1.Panels[1].Text :=
'
Вставка
'
;


else




StatusBar1.Panels[1].Text :=
' '
;


end
;


{ dsSetKey, dsCalcFields, dsFilter, dsNewValue,
dsOldValue, dsCurValue, dsBlockRead,


dsInternalCalc, dsOpening}

end;


Визуальные компоненты для работы с БД

Визуальные

компонент
ы для работы с данными расположены на странице
Data

Co
n-
trols

палитры компонентов и предназначены для построения интерфейсной

части прилож
е-
ния
.

Эти компоненты похожи на соответствующие компоненты со страниц

Standard

и

Add
i-
tional

и отличаются только тем, что ориентированы на работу с БД, отображают данные из
БД. Для связи с наборами данных нужно задать свойства
DataSource

и
DataField

(
в случае,
если компонент связывается только с одним полем
)
.

Большинство визуальных компонентов предназначены для работы с одним полем т
е-
кущей записи. К таким компонентам относятся, например, к
омпонент
TDBText



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

к
омпонент
TDB
Edit



редактор, позволяет отображать одно поле текущей записи и р
е-
дактировать его.

Компоненты
TDBGrid

(сетка,

служит для отображения набора данных в табличном
виде
)
и
TDB
Ctrl
Gr
id

(модифицированная сетка)
предназначены для отображения и работы
сразу с несколькими

записями и

полями.

Компонент
TDBNavigator

обеспечивает навигацию
по набору данных.

Некоторые визуальные компоненты предназначены для отображения полей специал
ь-
ного
определенного типа
:
TDBImage



для работы с графическим полем
;
TDBMemo
,
TDBRichEdit



текстовые поля, неформатированные и форматированные.




48


Визуальный компонент
TDBGrid

Визуальный компонент
TDBGrid

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

пункт

Columns

Editor

)
.
Можно настроить вид кажд
о-
го столбца.

Пр
имер

1
.

Поиск столбца в сетке компонента
TDBGrid
. Измененяем шрифт (
Font
) в стол
б-
це и задаем список выбора (
PickList
) на этапе прогона программы.

procedure

TfmMain.Button1Click(Sender: TObject);

var

k
,
i

:
Integer
;

begin


{поиск столбца, соответствующего полю
Mark
: }


k := 0;


while

�DBGrid1.Columns.Items[k].FieldName'Mark'
do

inc(k);


{Изменение шрифта в одном столбце (используется компонент
FontDialog1): }


if

FontDialog1.Execute
then



DBGrid1.Columns.Items[k].Font := FontDialog1.Font;


{Формирование списка вы
б
ора
PickList:

}


DBGrid1.Columns.Items[k].PickList.Clear;
//
очистка


{
заполнение

оценками

от

2
до

5:}


for

i:=2
to

5
do

DBGrid1.Columns.Items[k].PickList.Add(intToStr(i));

end
;


Пр
имер 2
.

Нестандартная прорисовка данных в сетке

TDBGrid
.


DefaultDrawing

=
True



данные выводятся в сетке
TDBGrid

с помощью
процедуры
DefaultDrawColumnCell

(установлено
по
умолчанию
)
;

=
False



заполняется программистом
, используя событие
OnDrawColumnCell
;

DefaultDrawColumnCell

(const Rect: TRect;


DataCol: Integer; Column:
TColumn; State:

TGridDrawState);

метод
TDBG
rid

о
существляет стандартную прорисовку

ячейки

сетки

OnDrawColumnCell

(Sender: TObject;

const Rect: TRect;


DataCol: Integer;


Column: TColumn;

Событие,

при

возникновении

которого
,
можно

осущес
т-
вить

нестандартную

прорисовку.

Свойству

DefaultDrawing

лучше

установить

значение

False
,
в

противном

случае

буде
т

осуществляться

и ста
н-
дартная
прорисовк
а.

49



State: TGridDrawState);

Параметры
:

Rect



координаты

ячейки
;
DataCol



номер столбца
;

Column



ссылка

на

столбец
;
State



состояние

ячейки
.



procedure

TfmMain
.
DBGrid
1
DrawColumnCell
(
Sender
:
TObject
;
const

Rect
:
TRect
;






DataCol
:
Integer
;
Column
:
TColumn
;
State
:
TGridDrawState);

Begin


{
Осуществляем нестандартную прорисовку
;


с помощью параметра процедуры
Column

можно выделить столбец


сетки,


с помощью обращения к полю связанного набора данных


текущую запись (строку)
;

используя оба свойства можно выделить одну ячейку
}

if
(Column.FieldName='Mark
')

and

((tbSessiya.FieldByName('
Mark
').AsInteger
=2
)
then


begin


DBGrid
1
.Canvas.Brush.C
olor := RGB(200,100,0);


DBGrid
1
.Canvas.FillRect(Rect);


DBGrid
1
.Canvas.Pen.Color := RGB(0,70,100);


DBGrid
1
.Canvas.TextOut(Rect.left+2,Rect.Top+2,Column.Field.AsString);


e
nd

{
в противном случае, запускаем стандартную прорисовку
}


else

DBGrid
1
.DefaultDrawColumnCell(Rect,DataCol,Column,State);

E
nd;


Компонент
TDBCheckBox

(перключатель
) удобно использовать для отображения и
редактирования логического поля.

Его можно также применять для работы со строковыми полями (когда возможны
только два строко
вых значения), если воспользоваться
свойствами
ValueChecked

и
ValueUnChecked
.

Пример
.

TDBCheckBox.ValueChecked

:=

’True;T;Yes;Y;
Да
;
Д
’;

TDBCheckBox.ValueUnChecked

:=


False
;
F
;
No
;
N
;
Нет
;
Н
’;

Компонент устанавливается в состояние
Checked
, если значение поля установлено в
одно из перечисленных значений в списке значений
ValueChecked
. Устанавливается в
U
n-
Checked

, если значение поля установлено в одно из перечисленных значений в списке зн
а-
чений
ValueUnChecked
. Устанавливается в неопределенн
ое состояние, если значения нет ни
в одном из списков. Если пользователь устанавливает значение с помощью визуального ко
м-
понента, то поле принимает первое значение из списка.


50


С помощью
компонента
TDBRadioGroup

(
зависимые
пер
е
ключател
и) удобно выб
и-
рать одно из нескольких заданных значений. Свойство
Items



список надписей для отобр
а-
жения, свойство
Values



список значений им соответствующих. Если свойство
Values

не з
а-
дано, то значения берутся из
Items
.

Компоненты
TDBListBox

(
список
)
,
TDComboBox

(
ко
мбинированный или
выпада
ю-
щий

список
)

также позволяют выбирать значения

из нескольких заданных в списке. Комп
о-
нент

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

В компонентах
TDBLookupListBox
,
TDLookupComboBox

создаются списки, сфо
р-
мированные из значений полей набора данных
. Эти компоненты

с
оздают списки выбора
,
также как и

при создании
полей выбора.

Для
работы пользователя с этими компонентами,
кроме задания
значений
свойств
DataSource

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



указывает на источник, из которого б
е-
рутся данные для формирования списка
,
ListField



указывается одно или несколько полей
(‘поле1;поле2’) для отображения в списке выбора,
KeyField



значения этого поля присва
и-
ваются текущему полю данных (
DataField
:=
KeyField
).

Все визуальные компоненты, работающие с одним полем текущей запис
и, могут а
в-
томатически переводить наборы данных в режим редактирования. Но они не могут выпо
л-
нить метод
Post
, т.е. подтвердить изменения. Они также не могут осуществлять переходы к
другим записям или вставку новых записей. Поэтому вместе с ними надо исполь
зовать либо
кнопки, с помощью которых пользователь явно сможет управлять набором данных (подтве
р-
дить изменения, вставить новую запись и др.). Либо использовать компоненты
TDBGrid
,

TDB
Ctrl
Grid

и
ли

TDBNavigator
.

Компонент
TDBNavigator

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


Компонент Database
,


управление транзакциями

Компонент
Database


(страница
BDE

палитры компонентов) осуществляет связь с
БД, может управлять транзакциями. Компонент не обязательно добавлять из палитры
ко
м-
понентов в программу. Если он не добавлен явно программистом, то он автоматически со
з-
дается
Delphi

и

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

Для соедине
ния с БД нужно задать либо псевдоним
BDE

(
свойство
AliasName
)
, либо
имя драйвера (свойство
DriverName
)
.
Если соединение задается с помощью драйвера, то о
с-
тальные параметры

соединения должны быть заданы через свойство
Params
:
место распол
о-
жения файла БД (
se
rver name
) и др. Использовать псевдоним удобней
:

при переносе пр
о-
граммы с одного компьютера на другой, нужно только поменять параметры в псевдониме.

Параметры соединения через псевдоним
:

51


AliasName
=

выбрать из списка псевдоним
BDE

DatabaseName
=
внутренний псевдоним, используется наборами данных в
Delphi
.

Connected
=
True



если устанавливается, значит есть подключение к БД.


По умолчанию при установлении соединения каждый раз запрашивается логин и п
а-
роль. Можно отключить этот запрос, установив свой
ство
LoginPromt
=
False

и добавив в сво
й-
ство
Params

две строки, как показано на рисунке
:


Свойство
KeepConnection

определяет, сохранять ли соединение с БД, если с ней не
связан ни один набор данных. По умолчанию
True
, т.е. сохранять соединение.

Все перечис
ленные параметры можно задать через инспектор объектов или в сл
е-
дующем окне, которое вызывается при двойном щелчке на компоненте
Database
.



Управление транзакциями

Транзакции помогают сохранять БД в целостном и непротиворечивом состоянии. Н
е-
явные
транзакции запускаются каждый раз при изменении данных в БД. Например, при и
с-
пользовании команд
Insert
,
Edit
,

наборов данных запускается неявная транзакция и

при использовании метода

Post

она завершается, а отменяется методом
Cancel
.

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

и завершают ее при подтверждении редактиров
а-
ния с помощью компонента
DBNavigator

или переходе к другой строке в компоненте
DBGrid
.
Это прос
тейшие неявные транзакции, которые позволяют записывать только корректные з
а-
52


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

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

перевела БД из одного ц
е-
лостного состояния в другое целостное состояние.

Компонент
Database

позволяет явно управлять транзакциями. Для этого используются
его методы
:


StartTransaction



начать транзакцию


Commit



подтвердить


Rollback



отменить

Пример
.

Добавление

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


procedure

TForm1.Button
1
Click(Sender: TObject);

begin

Database1.StartTransaction;

//
начать

транзакцию

{
Защищенный

блок

try
-
except
:
если

внутри

него

произойдет

ошибка
,
управление

перейдет

на

строку

за

except

}

try



Table
1.
Append
;
//
добавить

запись

в первую таблицу


//
Запись значений в таблицу
:




Table
1.
Post
;
//
подтвердить

запись



Table
2
.
Append
;
//
добавить

запись

во вторую таблицу


//
Запись значений в таблицу
:






Table
2
.
Post
;
//
подтвердить

запись



Database
1.
Commit
;

//
подтвердить

транзакцию

except


Database
1.
Rollback
;
//
отменить

транзакцию в случае ошибки

end
;

end
;


Свойство

InTransaction

типа
Boolean

позволяет определить, есть ли активная транзакция.

Свойство

TransIsolation

управляет уровнем изоляции транзакций
:

tiDirtyRead



разрешается чтение неподтвержденных изменений, выполненных в других
транзакциях (не работает для
InterBase
)

53


tiReadCommitted




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

tiRepeatableRead


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

Замечание

1
.
Компонент
Database
, использующий технологию доступа

BDE
, подде
р-
живает не все возможности транзакций
InterBase
/
Firebird
.

При использовании

технологии
прямого доступа н
а странице

InterBase

палитры компонентов есть аналогичный компонент
доступа
IB
Database

и еще один компонент
IBTransaction
, которые позволяют явно управлять
транзакциями в
InterBase

и поддерживают все возможности
InterBase
.

Замечание

2
.

Р
еализация транзакций в InterBase отлича
ется от реализации транзакции
в большинстве других СУБД. Это связано с особой архитектурой баз данных InterBase, им
е-
нуемой
Multi

Generation

Architecture

(MGA)


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

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


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

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


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

Далее, транзакция может либо подтвердиться, либо отмениться. При подтверждении
транзакции произойдет следующее: InterBase попытается пометить предыдущую (исходную)
версию записи как удаленную и сделать текущую (измененную в рамках этой завершающе
й-
ся транзакции) версию основной. Если только один пользователь менял запись, то именно
54


та
к все и произойдет


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

Предположим теперь, что после запуска описанной в примере транзакции (назовем ее


1), но до под
тверждения ее результатов запустится транзакция № 2, в которой пользов
а-
тель желает прочитать изменяющуюся запис
ь. Так как неподтвержденные в №

1 изменения
нельзя увидеть (в том числе и в транзакции № 2) по крайней мере до подтверждения этой
транзакции, то
транзакция № 2 увидит предыдущую версию записи!

Как видите, идея

версионности гениально проста


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


читающие пользователи не м
ешают пишущему пользователю.

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


в той
или иной форме.


Реляционный способ доступа к БД

Для клиент
-
серверных баз данных предпочтительным способом доступа является р
е-
ляционный способ, основанный на
SQL
-
запросах к базе данных. Использование компонента
Table

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

использовать компонент
Table
, основную работу перенести на сервер, за
счет хранимых процедур, а в программу получать только часть данных с помощью
SQL
-
запросов.

Работа с компонентом
Query

уже описана раньше, компоненты
StoredProc

и
UpdateSQL

описаны здесь.

Компонент StoredPro
c



вызов хранимой процедуры из
Delphi

Из компонента
Query

можно вызвать хранимую процедуру с помощью SQL
-
запроса.
Если хранимая процедура не возвращает данных, то вызывать ее можно запросом:

EXECUTE PROCEDURE имя процед
уры (параметры)

Для
отправки запроса используется метод
Query
.
ExecSQL
.

Если хранимая процедура возвращает набор данных, то вызвать ее лучше запросом

SELECT *

FROM
имя процедуры (параметры)

55


И использовать надо метод
Query
.
Open
. Результат ее работы сохранитс
я как набор
данных компонента
Query
, его также можно отобразить с помощью визуального компонента,
связанного с
Query
.

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


это компонент
StoredProc
. Этот компонент вызывает только процедуры не возвращ
ающие данных. Для в
ы-
зова требуется задать следующие параметры
:

DatabaseName



выбрать базу данных

StoredProcName



выбрать

из списка имя процедуры

Значения параметров можно задать, используя метод
ParamByName
, запускается хранимая
процедура методом

ExecProc.


Пр
имер

1.
Вызов хранимой процедуры
.

Пусть

определена

хранимая

процедура

CREATE OR ALTER PROCEDURE S
_PROC (


pfio varchar(30),


pkurs integer,


pgruppa integer)

as

begin


INSERT INTO Student

(NumberStud, FIO, kurs, gruppa)

VALUES (gen_
id(gen_student_id,1), :pfio,

:pkurs, :pgruppa);

end


Вызвать эту процедуру можно задав
DatabaseName

и
StoredProcName

в инспекторе
объектов и написав следующий обработчик
:


procedure TForm1.Button
1
Click(Sender: TObject);

begin



StoredProc1.ParamByName('
pFio').AsString := '
Фамилия

И
.
О
.
';



StoredProc1.ParamByName('pKurs').AsString := '
1
';



StoredProc1.ParamByName('pGruppa').AsString := '
1
';



StoredProc
1.
ExecProc
;

end
;

Компонент

UpdateSQL



создание редактируемого набора данных из нер
е-
дактируемого
Query

Набор данных, содержащийся в
TQuery
, чаще всего нельзя редактировать непосредс
т-
венно пользователю с помощью визуальных компонентов. Для того чтобы он был редакт
и-
руемым должно быть выполнено несколько условий. Свойство
ReadOnly

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


определяют возможность редактирования еще два свойства:
RequestLive

(по умолчанию
False
)
и доступное только для чтения
CanModify
.


Свойство
CanModify

имеет значение
True

только при выполнении следующих условий:



данные выбираются только из одной таблицы;



не используется
DISTINCT

и

статистические функции
;



нет соединения таблиц
;



нет вложенных запросов
:



нет группировки
;



нет сортировки по неиндексным полям.


Если набор данных в

Query

является

нередактируемым, его можно сделать редакт
и-
руемым с помощью компонента
UpdateSQL
. Эти два компонента работают в паре, для их
связи нужно в
Query

задать свойство

UpdateObject
.
Компонент
UpdateSQL

добавляет к ко
м-
поненту
Query

три запроса
:
Update
,
Insert

и
. При редактировании данных (изменении,
вставке и удалении
,

соответственно)

в визуальных компонентах, связанных с
Query

запуск
а-
ются эти запросы.

Причем у компонента
UpdateSQ
L

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


После работы мастера

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

находятся

данные из нескольких таблиц, то редактир
о-
вать можно только одну таблицу из них.

Сформировать запросы можно так
:

1.

Выбрать имя таблицы в списке
Table

Name
.

2.


При нажатии на кнопку
Get

Table

Fields
,
загружаются списки всех полей в списки
справа.

3.

В списке
Key

Fields

надо выделить ключевые поля (для однозначной идентификации
записи), а в

списке
Update

Fields

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

4.

И после этого нажать кнопку
Generate

SQL
.


57


Сформированные запросы запускаются при изменении данных в визуальных комп
о-
нентах связанных с
Query
, приставка
OLD

в них означает значение поля до изменения да
н-
ных.

Как в
Delphi

заполнять автоинкрементный ключ

1.

Использование триггера

1)
Можно использовать обычную сетку
DBGrid

или другие визуальные компоненты. Само
ключевое поле, которое заполняет триггер лучше в визуальном компоненте сделать нереда
к-
тируемым (свой
ство
ReadOnly
=
True
) или вообще скрыть его от пользователя.

В наборе данных

у столбца связанного с автоинкрементным ключом надо убрать обязател
ь-
ность его заполнения (свойство
Required
=
False
)
.

Тогда при добавлении новой записи будет
отправляться запрос без ключевого поля и триггер будет его заполнять.

2) Также можно использовать
SQL
-
запрос с пустым ключевым полем, например, таким
:

INSERT

INTO

Student


(
FIO, kurs, gruppa)



VALUES

(‘
Фамилия

И
.
О
.’, 4, 3);

и вызвать его

с помощью компонента
Query
.

Замечание
.
В обоих
этих
случаях
,

если

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

Delphi

и для его отображения нужно обновлять
весь набор данных, что является недостатком
.


2.

Использование хранимой процедуры

3) Можно использовать для заполнения также и хранимую процедуру (см. пример 1 на пе
р-
вой странице). У этого способа тот же самый недостаток


в
Delphi

надо будет обновлять
данные для отображения ключа.

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

можно использовать для вставки н
о-
вой записи.

3.

Вызов генератора из
Delphi

5) Можно вызвать генератор прямо из
Delphi

с помощью следующего запроса
:

SELECT gen_id(gen_student_id,1)

FROM

rdb
$
database

Если этот запрос находится в компоненте
Query
2
, а
Query
1


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


begin


Query2.Open;

58



sInteger;


Query2.Close;

end;

И тогда в визуальных компонентах номер будет отображаться сразу после вставки.

Замечание
.
Можно

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

программе.




59


Требования к курсовому проекту

I.

Создание базы данных (БД).

1.

Выбрать тему для

БД. Нарисовать схему
IDEF
1
X

для БД (использовать как мин
и-
мум

3 связанных между собой таблицы). Определить к какой нормальной форме о
т-
носится схема.

2.

Создать на
компьютере БД, соответствующую схеме. База данных должна иметь
:

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

II.

Создание программы для работы с БД.

Программа должна содержать
:

1.

Добавление, редактирование, удаление записей во всех таблицах.

2.

Поиск, сортировку, фильтрацию, выборку данных, просмотр в режиме связанных
таблиц (с помощью
SQL

запросов к БД).

3.

Вызов хранимых процедур.

4.

Работа с компонентами: Database, Query, StoredProc,

UpdateSQL.

5.

Использование полей выбора или
lookup
-
списков, вычисляемых полей.

6.

Формирован
ие текстового представления полей
,

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





60


Литература

1.

Д.

Кренке


Теория и практика построения баз

данных. 9
-
е изд. СПб.: Питер. 2005. 859
с.

2.

К.

Дж.

Дейт Введение в системы баз данных. Изд.
:

Вильямс
.
2006. 1328 с.

3.

Ковязин А.Н., Востриков С.М. Мир IntarBase. Архитектура, администрирование и
разработка
приложений баз данных в InterBase/
Firebird
/
Yaffil
.
Издание 4
-
е. М.: Кудиц
-
образ. 2006. 496 с.

4.

Борри Х. Firebird
: руководство разработчика баз данных
: пер. с англ. СПб.: БХВ
-
Петербург. 2006. 1104 с.

5.

Гофман В.Э., Хомоненко А.Д. Работа с базами данных в
Delp
hi
.
2003. 624
с.

6.

Фаронов В.В., Шумаков П.В.
Delphi

5.
Руководство разработчика баз данных. 2001.
640 с.

7.

Фаронов В.В. Программирование баз данных в
Delphi

7
.

Учебный курс. 2005. 459 с.





Приложенные файлы

  • pdf 7767004
    Размер файла: 1 MB Загрузок: 1

Добавить комментарий