Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






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

Лабораторная работа №2

Цель работы: знакомство с SQL-сервером БД Interbase, получение базовых навыков работы по технологии клиент-сервер, отработка операторов манипулирования данными языка SQL, изучение основ администрирования сервера.

Теоретические сведения: / Указания по выполнению

SQL-сервер Interbase предназначен для хранения и обработки больших объемов информации в условиях одновременной работы множества клиентских приложений.

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

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

Ограничения на значения отдельных столбцов; условия ограничений могут быть разнообразны — от требования удовлетворения вводимых значений опре­деленному диапазону или соответствия некоторой маске до требуемого отно­шения с одной или несколькими записями из другой таблицы (или многих таб­лиц) БД.

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

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

Триггеры — подпрограммы, автоматически выполняемые сервером до или (и) после события изменения записи в таблице БД.

В составе записи БД могут определяться BLOB-поля (Binary Large Object — большой двоичный объект), предназначенные для хранения больших объемов данных в виде последовательности байтов. Таким образом могут храниться тек­стовые и графические документы, файлы мультимедиа, звуковые файлы и т. д. Интерпретация BLOB-поля выполняется в приложении, однако разработчик мо­жет определить так называемые BLOB-фильтры для автоматического преобразо­вания содержимого blob-поля к другому виду.

InterBase дает возможность использовать функции, определяемые пользовате­лем (User Defined Function, UDF), в которых могут реализовываться функцио­нальности, отсутствующие в стандартных встроенных функциях InterBase (вычисление максимума, минимума, среднего значения, преобразование типов и приведение букв к заглавным). Например, в UDF можно реализовать извлечение из значения даты номера дня, года; определение длины символьного значения; усечение пробелов; разные математические алгоритмы и т. п. Функция пишется на любом алгоритмическом языке, позволяющем разрабатывать DLL (библиотеки динамического вызова), например, на Object Pascal.

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

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

InterBase был разработан в начале 80-х годов группой разработчиков из американ­ской корпорации DEC. В дальнейшем разработка данного продукта велась независи­мыми компаниями InterBase Software и впоследствии слившейся с ней Ashton-Tate. Borland приобрела права на InterBase у Ashton-Tate после слияния с нею.

InterBase активно используется в государственном и военном секторах США, что, видимо, и стало преградой для его продвижения в Россию. Интерес к этому серверу возрос только в последнее время в связи с включением его локальной (а начиная с Delphi 3 и 4-пользовательской) версии в состав Delphi Client/Server Suite и Delphi Enterprise. Внимание разработчиков БД InterBase привлек, во-первых, потому, что это «родной» продукт Borland (а средства разработки приложений этой компании давно зарекомендо­вали себя с положительной стороны), во-вторых, потому, что InterBase весьма прост в установке, настройке и администрировании по сравнению с другими SQL-серверами, и в-третьих, потому, что он обладает прекрасными функциональными возможностями.

Ниже приводятся некоторые технические характеристики сервера.

Характеристика Значение
Максимальный размер одной БД Рекомендуется не выше 10 Гбайт. Однако известны случаи объема одной БД в 10-20 Гбайт
Максимальное количество таблиц в одной БД  
Максимальное количество полей (столбцов) в одной таблице  
Максимальное количество записей в одной таблице Не ограничено
Максимальная длина записи 64 К (не считая полей BLOB)
Максимальная длина поля 32 К (кроме полей BLOB)
Максимальная длина поля BLOB Не ограничена
Максимальное количество индексов в БД  
Максимальное количество полей в индексе  
Максимальное количество вложенностей SQL-запроса  
Максимальный размер хранимой процедуры или триг­гера 48 К
Максимальное количество UDF в базе данных Длина имени UDF — не более 31 символа, каждая UDF должна иметь уникальное имя.

Начиная с версии 6.0 Interbase является Open Source продуктом (с открытым кодом) и послужила основой для выпуска клонов — Firebird, Interbase 6.5, Yaffil (российский клон), которые совместимы между собой.

Вместе с Interbase поставляется один инструмент администрирования: IBConsol (isql.exe). Работа с которым заключается в написании SQL-скрипта (текстовый файл с расширением.sql, который содержит SQL-операторы) и обработке последнего. К сожалению, этот инструмент недостаточно удобен. Существует масса средств сторонних разработчиков, которые удовлетворяют самым изысканным требованиям разработчиков и администраторов БД: IBExpert, IBManagen, IBWorkbench, IBAdmin, BlazeTop и др.

Создание БД

При создании БД требуется указать ряд моментов:

1. Тип сервера (локальный /удаленный), имя сервера и сетевой протокол доступа к серверу.

2. Местонахождение и название файла будущей базы данных. Каталог для размещения БД у этому моменту должен быть создан.

3. Имя пользователя и пароль для доступа. После установки на сервере зарегистрирован единственный пользователь SYSDBA с паролем masterkey.

4. Размер страницы БД влияет на эффективность работы сервера (фактор влияния тем значительнее, чем больше размер БД). Файл базы данных разбивается на страницы фиксированного размера, и все обращения к диску выполняются постранично. Поэтому идеальным считается размер страницы совпадающий с размером записи и размером кластера диска. (Для NTFS — размер страницы = 4096 байт).

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

6. Диалект может быть либо 1, либо 3 (диалект 2 используется для миграции между ними). Принципиально они отличаются: 1) диалект 3 позволяет использовать расширенный набор типов данных для работы с большими числами, для работы с датой и временем; 2) диалект 3 различает регистр идентификаторов, если идентификатор заключен в двойные кавычки; 3) диалект 3 не поддерживает неявное приведение типов данных (н-р, выражение '25'+5 в первом диалекте даст результат 30, а в третьем — ошибку несоответствия типов).

Рис. 1. Окно создания БД утилиты IBExpert

После создания БД можно создавать таблицы и другие объекты используя возможности GUI утилиты, либо при помощи SQL-редактора.

Для подключения к уже созданной БД на удаленном сервере, нужно указывать имя компьютера, на котором установлен сервер и полный путь к файлу БД, н-р, OUR_SERVER: C: \KINO\KINO.GDB

Инфологическая модель

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

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

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

Операторы, создающие таблицы выбранной предметной области:

CREATE DOMAIN D_Money INTEGER DEFAULT 0 CHECK (VALUE > = 0)

CREATE TABLE Prod (
id_pr INTEGER NOT NULL PRIMARY KEY,
fio VARCHAR(30) NOT NULL,
bd DATE,
adres VARCHAR(50),
money D_Money);

CREATE TABLE Movie (
id_m INTEGER NOT NULL PRIMARY KEY,
title VARCHAR(40) NOT NULL UNIQUE,
year INTEGER NOT NULL CHECK (year> 1910),
len INTEGER NOT NULL CHECK (len> 20),
kind CHAR(10) CHECK (kind IN ('Комедия', 'Боевик', 'Мелодрама')),
id_pr INTEGER,
FOREIGN KEY (id_pr) REFERENCES PROD ON DELETE SET NULL);

CREATE TABLE Star (
id_pr INTEGER NOT NULL PRIMARY KEY,
fio VARCHAR(30) NOT NULL,
bd DATE,
adres VARCHAR(50),
money D_Money);

CREATE TABLE StarIN (
Id_m INTEGER NOT NULL REFERENCES Movie ON UPDATE CASCADE
ON DELETE CASCADE,
Id_s, INTEGER NOT NULL REFERENCES Movie ON UPDATE CASCADE
ON DELETE CASCADE,
UNIQUE (Id_m, Id_m));

CREATE INDEX I_Title ON Movie (Title);

CREATE INDEX I_FIO_Pr ON Prod (FIO);

CREATE INDEX I_FIO_St ON Movie (FIO);

Генераторы и автоинкремент

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

CREATE GENERATOR Gen_Movie_Id_m;

SET GENERATOR Gen_Movie_Id_m TO 1;

CREATE TRIGGER Trig_Movie_BI FOR MOVIE

ACTIVE BEFORE INSERT POSITION 0

AS BEGIN

IF (NEW.Id_m IS NULL) THEN NEW.Id_m = GEN_ID(Gen_Movie_Id_m, 1);

END

Аналогичные скрипты — для других таблиц.

Триггеры

Одно из основных назначений триггеров — реализация бизнес-правил. Для примера, введем в нашей предметной области такое бизнес-правило: доход продюсера увеличивается на x% с каждым новым фильмом, где х — 10% от длины фильма.

CREATE TRIGGER INC_MONEY FOR MOVIE
ACTIVE AFTER INSERT POSITION 0
AS
declare variable x numeric(10, 5);
begin
x = NEW.LEN * 0.001;
update prod
set money=money * (1 +: x)
where id_pr = NEW.id_pr;
end

Хранимые процедуры

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

CREATE PROCEDURE STAR_LIST
RETURNS (FIO VARCHAR(30))
AS
declare variable tmp INTEGER;
begin
FOR SELECT S.FIO, COUNT(*)
FROM STAR S INNER JOIN " StarIN" SI ON S.ID_ST=SI.ID_S
GROUP BY S.FIO
ORDER BY 2 desc
INTO: FIO,: tmp
DO suspend;
end

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

Создание приложения

Общее описание основных компонентов, включенных в состав IBX:

Приложение-клиент разрабатывается при помощи программных средств Borland Delphi | C++ Builder, используя набор компонентов Interbase Express (IBX). Эти компоненты используют функции Intebase API, т.е. обращаются к серверу непосредственно.

 

Иерархия компонентов

TIBDatabase — предназначен для подключения к базе данных. Основные методы: Open, Close.

TIBTransaction — предназначен для явного управления транзакцией. Основные методы: StartTransaction, Commit, Rollback, CommitRetaining, RollbackRetaining.

TIBTable — аналог стандартного TTable. Компонент предназначен для получения данных из одной таблицы или представления базы данных. Основное свойство — TableName. Основные методы: Open, Close. Набор данных, полученных при помощи TIBTable, является редактируемым, если речь идет о таблице базы данных или обновляемом представлении. Компонент совместим с визуальными компонентами.

TIBQuery — аналог стандартного TQuery. Компонент предназначен для получения данных на основе SQL-запроса. Этот набор данных не всегда будет редактируемым, зачастую необходимо использовать дополнительный компонент TIBUpdateSQL, чтобы иметь возможность редактировать полученные сведения. Основное свойство — SQL. Основные методы: Open, Close, ExecSQL. Компонент совместим с визуальными компонентами.

TIBDataSet — предназначен для получения и редактирования данных, является потомком стандартного класса TDataSet и полностью совместим со всеми визуальными компонентами. Основные методы: Prepare, Open, Close, Insert, Append, Edit, Delete, Refresh.

TIBStoredProc — предназначен для выполнения хранимых процедур и получения набора данных на основе результатов выполнения процедуры. Получаемый набор данных является нередактируемым. Компонент совместим с визуальными компонентами. Основное свойство — StoredProcName. Основной метод — ЕхесРгос.

TIBUpdateSQL — аналог TUpdateSQL. Используется в паре с TIBQuery и предназначен для создания модифицируемых наборов данных. Основные свойства: DeleteSQL, InsertSQL, ModifySQL и RefreshSQL.

TIBSQL — предназначен для выполнения SQL-запросов. В отличие от TIBQuery или TIBDataSet, TIBSQL не имеет локального буфера для набора данных и несовместим с визуальными компонентами.

TIBDatabaseInfo — позволяет получить системную информацию о некоторых свойствах базы данных, соединения и сервера. Например, UserNames — список пользователей, подключенных к базе данных, PageSize — размер страницы базы данных.

TIBSQLMonitor — предназначен для перехвата и отслеживания всех запросов, которые выполняют приложения, использующие IBX.

TIBEvents — предназначен для получения пользовательских событий InterBase. Основное свойство — Events. Основные методы: RegisterEvents, UnregisterEvents.

Подключение к базе данных:

На форме (а лучше в контейнере Data Module) размещается компонент TIBDatabase и при помощи специального редактора указываются свойства подключения (см. рисунок).

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

Необходимо помнить, что любое действие с базой данных происходит в рамках той или иной транзакции. Работа с InterBase основана на явном управлении транзакциями, а поскольку библиотека IBX — это обертка вокруг соответствующих функций InterBase API, то использование этих компонентов также предполагает, что программист явным образом будет управлять транзакциями из своего приложения. Для контроля транзакций в IBX существует специальный компонент TIBTransaction.

TIBTransaction ссылается на компонент базы данных при помощи свойства DefaultDatabase. Если также указать свойство DefaultTransaction у TIBDatabase, то в дальнейшем любые компоненты (TIBDataSet, TIBSQL и т. д.), которые ссылаются на TIBDatabase, будут автоматически " подхватывать" и указанную транзакцию.

Теперь рассмотрим свойства AllowAutoStart и AutoStopAction. Как вам уже известно, любой запрос к базе данных должен выполняться в контексте транзакции. То есть, прежде чем выполнить даже простейший запрос вида SELECT * FROM TABLE1, необходимо предварительно запустить транзакцию при помощи вызова IBTransaction.StartTransaction.

Такой " ручной" вызов не всегда удобен. Более того, каждый раз совершенно определенно известно: если мы хотим выполнить запрос, то мы должны запустить транзакцию. Чтобы избежать лишнего кода, связанного с запуском транзакций, можно установить значение свойства AllowAutoStart равным True. В этом случае если мы попробуем, например, открыть TIBDataSet, то он сам автоматически запустит соответствующую транзакцию.

Аналогичный смысл имеет свойство AutoStopAction. Когда мы закрываем все запросы, выполнявшиеся в контексте автоматически запущенной транзакции, то TIBTransaction выполняет действие, указанное в AutoStopAction. Например, автоматически подтверждает всю транзакцию при помощи метода Commit, если свойство AutoStopAction равно saCommit. Таким образом, разработчику предоставляется возможность указать, как компоненты должны автоматически взаимодействовать друг с другом!

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

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

Для выборки данных, их изменения, удаления и вставки в TIBCustomDataSet используется набор свойств, представляющих собой SQL-запросы для манипулирования данными, — это SelectSQL, DeleteSQL, InsertSQL и ModifySQL.

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

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

В свойствах DeleteSQL, InsertSQL и ModifySQL указываются соответствующие запросы, которые будут вызываться автоматически самим компонентом при вызове методов Delete, Insert и Edit для удаления, вставки и редактирования записей.

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

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

Например, для таблицы с именем Table1 запрос в SelectSQL будет иметь вид:

SELECT * FROM Table1...

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

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

Аналогично TIBTable, компонент TIBQuery скрывает запросы для получения и редактирования данных. Вместо скрытого в этом компоненте свойства SelectSQL разработчику предлагается использовать свойство SQL. На самом деле после присвоения свойства SQL компонент присваивает его значение свойству SelectSQL.

Но самое примечательное с точки зрения проектирования классов начинается тогда, когда мы хотим сделать наш запрос редактируемым (live-query).

Поскольку свойства DeleteSQL, InsertSQL и ModifySQL спрятаны, то TIBQuery сам по себе не может предоставить разработчику редактируемые запросы.

Однако, как уже было сказано, TIBQuery был сделан как аналог TQuery и для полной аналогии в IBX введен компонент TIBUpdateSQL. Он содержит собственные свойства DeleteSQL, InsertSQL и ModifySQL и может подключаться к TIBQuery. После чего TIBQuery начинает использовать свойства компонента TIBUpdateSQL для редактирования собственных данных! Получается, что готовую функциональность TIBCustomDataSet, уже заложенную в него с самого начала, приходится дублировать в отдельном компоненте.

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

Компонент TIBStoredProc предназначен для выполнения исполняемых (executed) хранимых процедур. Т.е. получить с его помощью набор данных невозможно. Он также является потомком TIBCustomDataSet и полностью совместим с визуальными компонентами.

Являясь прямым наследником TIBCustomDataSet, компонент TIBStoredProc прячет все основные свойства предка и добавляет такое свойство, как ProcedureName.

В результате указания названия процедуры (например, proс1) компонент сформирует SQL-запрос следующего вида: EXECUTE PROCEDURE Proс1.

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

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

Итак, размещаем на форме еще три компонента: IBDataSetMovie: TIBDataSet, DataSourceMovie: TDataSource и DBGridMovie: TDBGrid и связываем их между собой при помощи соответствующих свойств.

Свойство SelectSQL компонента получает значение 'select * from movie' (см. рис). После этого мы можем открыть таблицу в design-time, установив в True IBDatabase1.Connected и IBDataSetMovie.Active. В случае, если мы не укажем текста запроса в SelectSQL, открыть таблицу не удастся.

Аналогично, для того, чтобы можно было добавлять, изменять и удалять записи из таблицы необходимо написать запросы в свойства InsertSQL, ModifySQL и DeleteSQL, которые будут выполнятся серверов при вызове (явном и неявном) методов Insert, Edit и Delete компонента IBDataSetMovie.

 

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

UPDATE MOVIE
SET
ID_M =: ID_M,
TITLE =: TITLE,
YEAR=: YEAR,
LEN=: LEN,
KIND=: KIND,
ID_PR=: ID_PR
WHERE
ID_M =: OLD_ID_M

Здесь, в качестве значений полей указаны параметры (с двоеточием), названия которых совпадают с названиями реальных полей.

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

Особое внимание обратите на параметр: OLD_ID_M в предложении WHERE запроса. Префикс OLD_ в названии означает, что IBDataSetMovie должен подставить в параметр значение поля до изменения пользователем.

Аналогичная идея подразумевается и для свойств InsertSQL и DeleteSQL. Для автоматической генерации текстов запросов можно использовать редактор IBDataSet.

В редакторе нужно указать таблицу, ключевые поля и поля, которые будут изменяться (CALCULATED-поля изменять нельзя). Если есть поля, названия которых совпадают с ключевыми словами (например, YEAR), их, в соответствии с диалектом 3, нужно взять в кавычки (установка флага Quote Identifiers приведет к взятию в кавычки всех идентификаторов).

Нажатие на кнопку Generate SQL сформирует необходимые запросы для свойств InsertSQL, ModifySQL, DeleteSQL и RefreshSQL. Последний запрос должен возвращать только одну текущую запись и нужен для обновления значений полей текущей записи.

Смысл данного запроса становится очевидным, если допустить существование в базе данных триггеров для таблицы MOVIE, которые модифицируют значения полей. Поскольку изменения происходят в самой базе данных сразу после вставки или после изменения записей, то без повторного перечитывания записи (т. е. без Select только что вставленной или измененной записи), мы не узнаем о тех изменениях, которые были сделаны в триггерах. Можно, конечно, вообще переоткрыть весь запрос, заданный в SelectSQL.

Именно такой механизм и реализуется в BDE, когда мы вынуждены целиком переоткрывать все запросы. В IBX без этого легко можно обойтись, используя RefreshSQL, значительно сэкономив при этом сетевой трафик и снизив нагрузку на сервер, поскольку получение всего лишь одной измененной записи гораздо более эффективно, чем переоткрытие запроса целиком.

У TIBDataSet как наследника TDataSet существует три основных метода для изменения данных: Delete, Insert (Append) и Edit. Например,

procedure TForm1.Button1Click(Sender: TObject);
begin
with IBDataSetMovie do
begin
Insert;
FieldByName('ID_M').Aslnteger: = 47;
FieldByName('TITLE').AsString: = 'Десять негритят';
FieldByName('YEAR').Aslnteger: = 1984;
FieldByName('KIND').AsString: = 'детектив';
FieldByName('LEN').AsInteger: = 201;
FieldByName('ID_PR').AsInteger: = 5;
Post;
end;
end;

После того как мы вызываем метод Insert, IBDataSetMovie формирует пустой буфер для нашей (пока еще не введенной) записи. Далее мы задаем значения нужных полей при помощи вызовов метода FieldByName и заканчиваем (точнее, подтверждаем) редактирование вызовом метода Post. В этот момент IBDataSetMovie выполняет запрос, прописанный в свойстве InsertSQL, подставив вместо параметров те значения полей, которые мы задали.

Если запрос выполнился успешно, то IBDataSetMovie автоматически выполняет RefreshSQL для обновления только что вставленной записи — для проверки изменений, внесенных на стороне базы данных.

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

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

Поэтому у компонента IBDataSet существует свойство Generator Field со своим редактором:

Укажите название генератора, имя поля в таблице, значения для которого будут генерироваться, шаг увеличения счетчика (в большинстве случаев это 1), а также опцию, указывающую, когда будет генерироваться значение поля: сразу при вставке новой записи (On New Record), при завершении вставки (On Post) или при помощи триггера (On Server). В последнем случае вы не увидите значения сгенерированного поля, пока не переоткроете весь запрос, однако данная опция все равно может оказаться полезной.

Указав же явным образом, что значение поля будет получено именно в триггере, мы обойдем это ограничение. Тем не менее рекомендуется использовать опции On New Record или On Post, поскольку они лучше укладываются в общую идеологию применения IBX.

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

Механизм master-detail

Для нашего примера механизм master-detail используется следующим образом: в сетке DBGridMovie отображаются записи только того продюсера, запись которого является текущей в таблице Prod.

Свойство IBDataSetMovie.DataSource задается равным DataSourceProd, а свойство IBDataSetMovie.SelectSQL — 'SELECT * FROM MOVIE WHERE ID_PR =: ID_PR'. Значение параметра: ID_PR будет автоматически браться из одноименного поля ID_PR IBDatasetProd.

Кроме того, необходимо открывать IBDataSetMovie и IBDataSetProd в режиме rum-time, например:

procedure TForm1.FormCreate(Sender: TObject);
begin
IBDatasetProd.Open; // IBDatasetProd.Active: =True;
IBDatasetMovie.Open; // IBDatasetMovie.Active: =True;
end;

Эта процедура приведет к ошибке, если в design-time не установить предварительно свойства Active в False, либо открывать компоненты способом, приведенным в комментарии.

Чтобы включать/выключать режим master-detail в режиме run-time можно организовать CheckBox. По которому надо IBDataSetMovie.SelectSQL присвоить соответствующий текст и переоткрыть IBDataSetMovie.

Ведение журнала

С точки зрения безопасности небесполезной может оказаться информация о действиях пользователей над данными: кто и когда совершил то или иное действие над каким-либо объектом. Такого рода информацию приходится записывать в специальные таблицы при помощи трех триггеров AFTER INSERT, AFTER UPDATE и AFTER DELETE, используя системные переменные current_timestamp и current_user.

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

CREATE TABLE LOG (
" WHEN" TIMESTAMP,
" USER" VARCHAR(20),
" ACTION" CHAR(3));

Триггеры для таблицы MOVIE:

CREATE TRIGGER TR_FOR_MOVIE_AI
ACTIVE AFTER INSERT POSITION 0
AS
BEGIN
INSERT INTO " Log" VALUES (current_timestamp, current_user, 'INS');
END;

CREATE TRIGGER TR_FOR_MOVIE_AU
ACTIVE AFTER UPDATE POSITION 0
AS
BEGIN
INSERT INTO " Log" VALUES (current_timestamp, current_user, 'UPD');
END;

CREATE TRIGGER TR_FOR_MOVIE_AD
ACTIVE AFTER DELETE POSITION 0
AS
BEGIN
INSERT INTO " Log" VALUES (current_timestamp, current_user, 'DEL');
END;

 

 

Указания по выполнению:

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

2. Создать базу данных

3. Создать таблицы. Требования:

§ таблицы должны содержать ограничения /CONSTRAINT/ и значения по умолчанию);

§ продемонстрировать использование доменов, даже если это и нецелесообразно;

§ определить связи между таблицами путем определения первичных (PRIMARY) ключей у родительских и внешних (FOREIGN) ключей у дочерних таблиц;

§ создать необходимые индексы.

4. Создать генераторы и триггеры для реализации автоинкремента и триггеры для обеспечения бизнес-правил.

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

6. Написать исключения и их обработчики.

7. Создать User Defined Functions.

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

9. Создать приложение-клиент используя технологию Interbase Express. Требования:

§ приложение должно отражать работу со всеми созданными объектами БД;

§ продемонстрировать динамический режим включения механизма master-detail;

10. Подключиться к БД как к находящейся на сервере.

11. Оформить отчет по лабораторной работе.

§ скрипты по созданию всех используемых в БД объектов.

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

Контрольные вопросы:

1. Укажите все явные и неявные ограничения, имеющиеся в вашей БД.

2. Укажите все явные и неявные индексы, имеющиеся в вашей БД.

3. Сколько потенциально индексов можно создать к любой вашей таблице?

4. Какова технология изменения характеристик отдельного столбцы таблицы?

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

6. Расскажите механизм реализации автоинкрементных полей в Intebase.

7. Назовите отличия триггера и хранимой процедуры.

8. Алгоритмический язык хранимых процедур и триггеров пересматривает постановку двоеточия перед идентификатором параметра или локальной переменной. В каких случаях это делается и для чего?

9. Объясните механизм работы оператора SUSPEND.

10. Может ли хранимая процедура вернуть значения через выходные параметры если в ней не используется оператор SUSPEND?

11. Как осуществляется обработка исключений на сервере?

12. Для чего в третьем диалекте SQL идентификаторы нужно брать в кавычки?

13. В чем недостатки использования компонентов TIBTable и TIBQuery по сравнению с TIBDataSet, а в чем преимущество?

Источники информации:

1. Ковязин А., Востриков С. Мир InterBase. Архитектура, администрирование и разработка приложений баз данных в InterBase/Firebird/Yaffil. М., Кудиц-Образ, 2002.

2. Фаронов В.В. Delphi. Программирование на языке высокого уровня: Учебник для вузов. СПб., Питер, 2003.

3. Фаронов В.В. Программирование баз данных в Delphi 7. Учебный курс. СПб., Питер, 2004.

4. www.ibase.ru

5. www.ibphoenix.com

<== предыдущая лекция | следующая лекция ==>
Речевая избыточность | B. Interaction of different types of lexical meaning




© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.