Курсовая работа: Создание базы данных для организации
Название: Создание базы данных для организации Раздел: Рефераты по информатике, программированию Тип: курсовая работа | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Содержание Введение 1. Анализ предметной области 1.1 Общее описание предметной области 1.2 Описание информационных процессов проходящих в предметной област 1.3 Обоснование необходимости автоматизации 2. Проектирование 2.1 Построение диаграммы потоков данных 2.2 Построение Инфологической Модели 2.3 Обоснование выбора СУБД и языка программирования 2.4 Построение даталогической модели 3. Разработка приложения 3.1 Выбор среды реализации 3.2 Особенности разработки приложения 3.3 Разработка пользовательского интерфейса Список литературы Графическое приложение Листинг программы Введение Специализированные СУБД создаются для управления базами данных конкретного назначения — бухгалтерскими, складскими, банковскими и т. д. Заказные СУБД требуют существенных затрат, а их подготовка к работе и отладка занимают значительный период времени (от нескольких месяцев до нескольких лет). Однако, в отличие от промышленных, заказные СУБД в максимальной степени учитывают специфику работы заказчика (того или иного предприятия), их интерфейс обычно интуитивно понятен пользователям и не требует от них специальных знаний. В настоящее время в разных сферах деятельности все более нуждаются в средствах, позволяющих быстро и безошибочно перерабатывать большое количество информации. Применение таких средств позволяет существенно снизить затраты и повысить эффективность работы.Например, в каждом видео прокате большой поток данных (клиенты, фильмы, режиссеры и т.п.) и чтобы снизить время обработки информации и облегчить работу сотрудникам заведений создается информационная система, которая может это позволить. Информационные технологии в настоящее время являются средством совершенствования и развития управленческой деятельности. Внедрение информационных систем способствуют более качественному управлению заведением, уменьшают расходы и повышают эффективность принимаемых управленческих решений.Цель курсовой работы заключается в разработке информационной системы для удобства работы сотрудников видео проката. Информационная система будет включать в себя базу данных и приложение для более функциональной работы. Для успешного создания работоспособной, отказоустойчивой и удобной информационной системы необходимо тщательное изучение предметной области, сбор исходных данных и их анализ. 1. Анализ предметной области1.1 Общее описание предметной областиСущностью проекта является создание программы, предоставляющей услуги проката аудио- и видеокассет, DVD и CD дисков. Коммерческая организация заказчик имеет организационно-правовую форму - общество с ограниченной ответственностью и относиться к субъектам малого предпринимательства. Полное наименование организации: общество с ограниченной ответственностью "Видеоклуб"(сокращенное:ООО "Видеоклуб").Целью организации данного предприятия является получение прибыли, а также формирование клуба, который будет в своей деятельности стремиться максимально полно удовлетворить потребности видеолюбителей. Деятельность по предоставлению услуг в области видеопроката относится к отрасли "культура и искусство" 93000 в соответствии с Общероссийским классификатором отраслей народного хозяйства (ОКОНХ), непроизводственной сфере деятельности. Видеопрокат относится к материальным услугам и характеризуется следующими качествами: - неосязаемостью (их невозможно транспортировать, хранить, упаковывать или изучать до покупки, нельзя увидеть, услышать, потрогать, можно лишь верить в результат, можно лишь почувствовать эффект, который появится в результате получения услуги); - невозможностью хранения услуг; - неотделимостью от источника (контакт с потребителем - неотъемлемая часть предоставления услуги видеопроката); - изменчивостью, что означает непостоянства качества услуги; в данном виде деятельности качество удовлетворения потребности видеолюбителя зависит от квалификации продавца-консультанта, от менеджеров, формирующих ассортимент видеопродукции. 1.2 Описание информационных процессов проходящих в предметной областиВ ходе данного проекта необходимо проанализировать систему «Организация работы пункта видео-проката». Итогом системного анализа будет текст технического задания на проект программного продукта, который улучшит характеристики данной системы. Под программным продуктом в данном случае будем понимать совокупность баз данных, СУБД, приложений и документации их характеризующей, находящихся в непосредственной или косвенной взаимосвязи и предназначенные для поставки, передачи или продажи пользователям систем типа «Организация работы пункта видео-проката». В процессе приема заказа производится его прием от клиента и регистрация. Регистрационные данные сохраняются в компьютере и используются для последующего поиска. Клиент может четко указать название фильма и тип носителя, которые его интересуют, либо же указать жанр фильмов, которые он бы хотел посмотреть, или страну, производство фильма которой он хотел бы посмотреть. Использую данные, полученные от пользователя, производится поиск в базе имеющихся фильмов. Результаты поиска выводятся на экран оператора, который сообщает о них пользователю. В случае неудовлетворительного результата предлагается сделать новый заказ. В случае удовлетворительного результата поиска, оператор получает информацию о местонахождении требуемого фильма, условий, на которых этот фильм предоставляется в прокат и другую информацию. Затем производится оценка состояния возвращенного материала. В случае выявления повреждений носителей производится взимание штрафа с клиента. Данные о результатах вносятся в компьютер. Оплата производится по наличному расчету через кассу предприятия. После оплаты клиенту предоставляется заказанная им видео-продукция. Вся необходимая информация отмечается на вкладыше к носителю оператором вручную, а именно: название фильма, срок возврата, состояние носителя на момент заказа в кодированной форме. 1.3 Обоснование необходимости автоматизацииЕстественно отметить в вышеперечисленных этапах процессы, которые легко подвергаются автоматизации и в которых целесообразно создание электронных баз данных (например, регистрация заказов, данные о клиенте, ведение статистики заказов и прочее). С экономической точки зрения необходимо отметить, что подобное нововведение позволит значительно облегчить процесс обслуживания клиентов и резко понизить время оказания услуг, что позволяет обслуживать большее количество клиентов за одно и тоже время, и как результат ведет к увеличению прибыли пункта видео-проката. Работа старшего менеджера с отчетами существенно облегчается с введением СУБД. Статистику заказов, можно просматривать за любой период, тем самым, выявляя товары, пользующиеся наибольшим спросом и соответственно пользующиеся наименьшим спросом, лучших клиентов месяца и т.д. Дополнительно появляется возможность контроля над пользователями (менеджерами) и просмотра статистики заказов осуществленным каждым менеджером. Итак, можно сказать, что итогом проектирования должна быть система управления баз данных. СУБД должна иметь дружественный интуитивно понятный интерфейс (быть наглядной, простой в освоении…), так как пользоваться ей предстоит, как правило, слабо подготовленных пользователей, не имеющих определенных знаний в области информационных систем. К СУБД может быть спроектирована система помощи, направленная на ее быстрое освоение и поиска ответов на возможные возникшие вопросы при пользовании программным средством. Естественно отметить в вышеперечисленных этапах процессы, которые легко подвергаются автоматизации и в которых целесообразно создание электронных баз данных (например, регистрация заказов, данные о клиенте, ведение статистики заказов и прочее). Данная система в соответствии с проведенным ранее анализом легко подвергается автоматизации. В качестве операционной среды была выбрана MS Windows XP/Vista – совместимая среда, в качестве языка программирования SQL. 2. Проектирование ЭИС 2.1 Построение диаграммы потоков данныхАнализ и моделирование любой системы является важным этапом в построении технического задания на то или иное изменение или дополнение к данной системе, не говоря уже об автоматизации. Вот почему важно рассмотреть изучаемую систему наиболее тщательно и наиболее полно построить ее модель. Наиболее подходящим в данном случае является очень распространенный в мире стандарт DFD, по сути являющийся методологией функционального моделирования. С помощью наглядного графического языка DFD изучаемая система предстает перед аналитиками и специалистами предметной области в виде набора взаимосвязанных функций, которые в терминах DFD называются функциональными блоками. Кроме того, необходимо отметить то, что стандарт DFD содержит набор процедур, позволяющий рассчитывать и согласовывать модель большой группой людей из разных областей деятельности. Согласованная модель легко потом может быть изучена с любой степенью детализации практически любым человеком, не принимающим участия в построении модели. В этом состоит одно из важнейших его преимуществ. Построим модель в стандарте DFD. Первым делом составим контекстную диаграмму (рисунок 1), характеризующую модель в терминах вход/выход и являющуюся самым общим представлением. Внешние сущности изображают входы в систему и/или выходы из системы. Внешние сущности изображаются в виде прямоугольника с тенью и обычно располагаются по краям диаграммы(рис.1 блок «Клиент»). Потоки работ изображаются стрелками и описывают движение объектов из одной части системы в другую. Поскольку в DFD каждая сторона работы не имеет четкого назначения, как в IDEF0, стрелки могут подходить и выходить из любой грани прямоугольника работы. В DFD также применяются двунаправленные стрелки для описания диалогов типа "команда-ответ" между работами, между работой и внешней сущностью и между внешними сущностями. (рис. 1 блоки «Информация о клиенте» и «Внесение информации о заказе»). В отличие от стрелок, описывающих объекты в движении, хранилища данных изображают объекты в покое. 2.2 Построение Инфологической Модели Так как в процессе моделирования системы было выяснено, что необходимо создание хранилищ данных (клиенты, заказы, база фильмов …), то в процессе моделирования системы необходимо рассмотреть закрепление этих хранилищ за основными процессами. Это можно сделать при помощи модели IDEF1X, которая является методологией построения реляционных структур баз данных в терминах сущность-связь. Построим модель данных в стандарте IDEF1Х. Данная модель изображена на рисунке и имеет 4 сущности (2 из которых зависимые), объединенных связями. Все связи один-ко-многим, следовательно модель не противоречит концепции IDEF1Х («связи многие-ко-многим нежелательны ибо не раскрывают реальную структуру данных…»). В модели IDEF1X легко заметить по внешнему представлению зависимые и независимые сущности (зависимые сущности обозначаются прямоугольниками с закругленными концами). В данной модели, как это было сказано ранее, это – «Deal». Естественно, без клиента не может быть заказа, произведенного им. Статистика заказов не может существовать без заказов. 2.3 Обоснование выбора СУБД и языка программирования Проанализировав диаграмму сущность-связь можно уже сделать выбор СУБД и клиентской части. 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-серверами, и в-третьих, потому, что он обладает прекрасными функциональными возможностями. Firebird выбран мной в качестве сервера из-за того, что он бесплатен и более функционален, чем Interbase, а также хорошо совместим с новыми операционными системами Windows Vista и Server 2008. Используемая мною версия это наиболее стабильная на данный момент – 2.0.3. 2.4 Построение даталогической модели Предметная область, выбранная мною для данной курсовой работы – информация о клиентах, дисках и выдаче дисков небольшого видеопроката.Целью данной работы является автоматизация обработки данных по клиентам с целью упрощения работы персонала с клиентами. При покупке или выдаче на прокат товара клиенту выдаётся чек. Количество товара на складе соответственно уменьшается. Также в видеопрокате существуют скидки постоянным клиентам в зависимости от количества покупок (сделок).В процессе реализации задачи при разработке структуры для хранения данных, первым объектом выступают информация о товаре (дисках или кассетах) и клиентах. В нашем случае БД будет состоять из 3 таблиц. В таблице MOVIE будут содержаться сведения о фильмах (штрих-код, количество дисков, название, режиссер и жанр). В таблице CLIENT будут храниться все нужные сведения о клиентах – с указанием полных паспортных данных. Третья таблица DEAL будет содержать сведения о сделках (дата сделки, сумма с учетом скидки (если она есть) и т.д.) Таким образом, таблица DEAL будет центральной. Она должна будет иметь уникальной поле, которое будет однозначно определять каждую сделка. В дальнейшем по этому полю мы создадим первичный ключ, чтобы СУБД могла быстро найти нужную запись. Каждой записи в таблице MOVIE будет соответствовать произвольное количество записей в таблице DEAL (такая связь в терминологии БД называется связью один ко многим), т. е. одно из её полей будет содержать уникальный идентификатор фильма. В таблице DEAL будет также ссылка на уникальный идентификатор клиента из таблицы CLIENT. При появлении очередной записи в таблице DEAL должно меняться значение поля KOL (количество) в таблице MOVIE. Таблица Фильмы (MOVIE):
Таблица Клиенты(CLIENT):
Таблица Заказы(DEAL):
Таблица Log
3. Разработка приложения3.1 Выбор среды реализацииСреда разработки Borland Delphi.Приложение-клиент разрабатывается при помощи программных средств Borland Delphi, используя набор компонентов Interbase Express (IBX). Эти компоненты используют функции Intebase API, т.е. обращаются к серверу непосредственно. VCL-библиотека классов среды проектирования Delphi предоставляет ряд классов, позволяющих быстро и эффективно разрабатывать различные приложения баз данных. Эти классы представлены следующими группами: · компоненты для доступа к данным, реализующие: o доступ через машину баз данных BDE (Borland Database Engine), предоставляющую доступ через ODBC-драйверы или через внутренние драйверы машины баз данных BDE (компоненты страницы BDE-палитры инструментов); o доступ через ADO-объекты (ActiveX Data Objects), в основе которого лежит применение технологии OLE DB (компоненты страницы ADO); o доступ к локальному или удаленному SQL-серверу InterBase (компоненты страницы InterBase); o доступ посредством легковесных драйверов dbExpress; o доступ к БД при многозвенной архитектуре (компоненты страницы DataSnap); · визуальные компоненты, реализующие интерфейс пользователя; · компоненты для связи источников данных с визуальными компонентами, предоставляющими интерфейс пользователя; · компоненты для визуального проектирования отчетов. Компоненты для доступа к серверу InterBase: · 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. 3.2 Особенности разработки приложения С учетом назначения функциональной спецификации, а также с учетом возможности тяжелых ошибок в этом документе, функциональная спецификация должна быть очень точной и не противоречивой и по возможности приближаться к математическим формулировкам, однако это не означает что она должна быть формализована настолько, что по ней можно было бы автоматически генерировать код программы. Это означает лишь то, что она должна базироваться на понятиях, построенных как математические объекты, и утверждениях, однозначно понимаемых и заказчиком и разработчиками. Достаточно часто функциональная спецификация формализуется на естественном языке, тем не менее использование математических и других формализованных методов при разработке функциональной спецификации весьма приветствуется. В целом функциональная спецификация состоит из трех основных частей: 1. Описание внешней информационной среды по отношению к программному средству; 2. Определение функций ПС. Чаще всего такие функции рассматриваются на множестве состояний внешней информационной среды; 3. Описание нежелательных ситуаций, которые могут возникнуть при работе ПС и описание реакции ПС на эти ситуации. Основной функцией ПС можно считать автоматизацию процесса управления процессом принятия заказов, поиска заказов, ведение статистики и пр. Как сказано выше, основными функциями разрабатываемого ПС являются: - Добавление нового поступления видео-продукции с проведением маркировки. Каждое новое поступление должно быть введено в базу фильмов с заполнением всех необходимых полей. Результатом выполнения данной функции является запись в таблице базы данных и присвоение каждому видео-фильму своего индивидуального номера, с его последующим нанесением на физический носитель. Повторение индивидуального номера не допускается, поэтому необходимо либо генерировать его внутри системы. Название видео-фильма должно быть символьным и не более 50 символов. Число копий должно быть целым числом. Поля «Носитель», «Категория», «Производство фильма (Страна)», заполняются из выпадающих списков. - Регистрация новых клиентов пункта проката. Регистрация клиентов производится только при наличии паспорта. При регистрации необходимо обязательно заполнить поля «№ паспорта», «Фамилия», «Имя», «Отчество», остальные поля не обязательными для заполнения. Также необходимо проводить проверку на совпадение вводимой информации при регистрации нового клиента по всем обязательным параметрам в совокупности и при совпадении необходимо выводить соответствующее сообщение. Поля «Фамилия», «Имя», «Отчество», «Адрес» являются символьными и ограничены 50 символами. - Быстрый поиск видео-продукции по индивидуальному номеру, категории, типу носителя, названию. Результатом работы функции является список видео-продукции, отобранный по определенному критерию, или группе критериев. Поле «Название» является символьным и должно содержать название искомой продукции, поле «Индивидуальный номер» является целым числовым, другие поля заполняются из выпадающего списка. Если не будет обнаружено ни одной записи, отвечающей критериям поиска, то должно быть выведено соответствующее сообщение. - Возможность показа статистики заказов отдельным клиентом. Результатом работы данной функции является вывод списка с информацией о клиенте и видео-продукцией, которую он заказывал ранее. В этом списке указывается количество заказов, сделанных клиентом, размер штрафа, который он уплатил, количество дней, прошедших с момента регистрации. Также указывается количество заказов, которые клиент сделал, выбирая видео-продукцию на различных видов носителей (VHS, CD, DVD). Входной информацией является ввод в поле «Номер паспорта», который является целым числом. Также имеется возможность показа статистики заказов отдельного фильма. Результатом работы является вывод списка с информацией о количестве заказов фильма, название которого введено в поле «Название фильма», а поле «Номер паспорта» остается пустым. - Возможность показа общей статистики. Результатом работы данной функции является вывод списка всех заказов, осуществленных предприятием. Период, за который статистика будет выведена определяется пользователем, который может в поле «Год» указать год, в поле «Месяц» указать месяц и в поле «День» указать день. В результате выведется статистка заказов на то число, которое было введено пользователем. Все перечисленные выше поля являются символьными и ограничены 8 символами и заполняются из выпадающего списка, в котором присутствует строка «все», при выборе которой должна учитываться статистика за все дни, месяцы, годы в зависимости от того в каком поле эта строка выбрана. Исключительные ситуации должны быть обрабатываться отдельным обработчиком и перекрывать системный обработчик. Должен выполняться принцип прозрачности и пользователю помимо ошибки должны сообщаться ее причины и при его желании соответствующие справки. Локальные ошибки должны устраняться без прерывания основного процесса не подверженного ошибочным действиям. Фатальные ошибки должны отрабатываться особо и не нарушать целостности системы. В случае краха системы, должно быть обязательно предусмотрено ее восстановление предыдущей рабочей версией, с целью чего необходимо создавать архивы системы при каждом ее отключении. Создание архива системы должно быть автоматическим и не сказываться на скорость основных вычислений. Опытным путем нетрудно выяснить, что Delphi при работе с InterBase интерпретирует столбцы типа CHAR и VARCHAR как T S t r i n g F i e l d. При этом, во-первых, столбцы типа CHAR всегда читаются без завершающих пробелов, во-вторых, при занесении завершающих пробелов в столбец (а часто это бывает необходимо) типа CHAR они всегда удаляются, в то время как в столбце типа VARCHAR, наоборот, они всегда хранятся. Столбцы типа DATE позволяют хранить значения даты в пределах от 01.01.0100 до 11.12.5941, а также значения времени (тип DATE InterBase полностью совместим с типом TDateTime Delphi). Если ввод данных в столбец типа DATE производится из утилиты IBConsole, значения даты должны указываться в формате InterBase. Согласно этому формату, значения даты состоят из номера дня (01-31), месяца (JAN-DEC) и года. Эти значения отделяются друг от друга разделителями. Стандартным разделителем является символ дефиса (-), но принимаются и пробел, правый слеш (/) и точка (.). Значения дат в InterBase должны лежать в диапазоне от 1-JAN-100 до 11-DEC-5941. Интерпретация формата представления значений типа DATE зависит от настройки — программы или операционной системы компьютера. Полезно всякий раз при старте приложения программно переустанавливать формат даты и времени к привычному нам российскому формату: procedure TForml.FormCreate(Sender: TObject); begin DateSeparator:= '. '; ShortDateFormat:= 'dd.mm.yyyy'; ShortTimeFormat:= 'hh:mm:ss'; end; Таким образом можно игнорировать неопределенность текущей настройки операционной системы на конкретном компьютере. В InterBase значения типа DATE совместимы со строковыми типами. Поэтому, если в SQL-операторах InterBase требуется интерпретировать значения типа DATE как строку, нет необходимости в приведении типов. Например, можно так записать в символьный столбец S значение типа DATE (символы I I означают операцию конкатенации, или сцепления, строк, функция NOW возвращает текущие дату и время): UPDATE DEAL SET S = "Дата отгрузки " I I NOW; Как уже говорилось, в InterBase нет автоинкрементного типа. Поля автоинкрементного типа автоматически заполняются уникальными числовыми значениями при вводе очередной записи. Такие поля обычно используются для создания первичных ключей. Вместо автоинкрементных полей InterBase предоставляет механизм генераторов — особых программ, которые хранят некоторое значение вплоть до момента, когда оно будет использовано, после чего изменяют хранимое значение на заданную величину. Генератор создается следующим оператором: CREATE GENERATOR Имя_генератора После создания генератора ему необходимо присвоить начальное значение таким оператором: SET GENERATOR Имя_генератора ТО Начальное_значение Для получения очередного значения генератора используется такая функция: GEN_ID(Имя_генератора, Шаг) Здесь Шаг — целое число, на которое изменяется текущее значение генератора. Проиллюстрируем использование генератора на примере поля ID_C таблицы CLIENT. Создаем генератор: CREATE GENERATOR GEN_CLIENT_ID_C; SET GENERATOR GEN_CLIENT_ID_C TO 1; Однажды созданный генератор хранится в БД наряду с другими ее сущностями — таблицами, индексами, хранимыми процедурами и т. п. Используем генератор при вводе очередной записи: CREATE TRIGGER TRIG_CLIENT FOR CLIENT ACTIVE BEFORE INSERT POSITION 0 AS BEGIN IF (NEW.id_c IS NULL) THEN NEW.id_c = GEN_ID(gen_client_id_c,1); END Доменами называются заранее созданные описания столбцов. Наряду с другими сущностями БД, домены должны иметь уникальные имена. Однажды созданный домен хранится в БД и может использоваться вместо типа столбца. С помощью доменов достигается унификация типов данных, хранящихся в различных столбцах, возможно, разных таблиц. CREATE DOMAIN D_GANR AS VARCHAR(10) CHARACTER SET NONE NOT NULL CHECK (VALUE IN ('comedy', 'action', 'melodrama', 'fantasy', 'horror')) COLLATE NONE В InterBase нет столбцов денежного типа (Currency). Вместо них обычно используются столбцы FLOAT или DOUBLE PRECISION. При выводе их значений в визуализирующих компонентах они представляют денежные суммы как значения с плавающей запятой, что в большинстве случаев мешает их восприятию. Вернуть этим столбцам нормальный денежный вид можно либо в обработчике события OnGetText объекта-поля, либо с помощью его (объекта-поля) свойства DisplayEdit. В обработчике можно использовать оператор такого вида: procedure TForml.QUSUMMAGetText(Sender: TField; var Text: String; DisplayText: Boolean); begin Text:= FloatToStrFfquSumma.AsFloat, ffCurrency, 10, 2) end; В свойстве DisplayEdit можно указать следующую маску: # # #, # # #. 0 0 ' р. ' Конечный результат будет одинаков, но указать маску, как мне кажется, проще. Визуальные средства разработки запросов обеспечивают реально удобное представление решаемой задачи, помогают определить связи и условия запроса. Но в Interbase нет как таковых визуальных средств разработки запросов. Однако можно обращаться с Interbase при помощи ibExpert. Это гибкий и мощный инструмент. В нем присутствует возможность разрабатывать структуру самой БД, сохранять и выполнять скрипты на SQL, использовать множество встоенных утилит, облегчающих работу, как разработчика, так и администратора. Загрузив ibExpert в меню Tools->Query Builder, нужно перетащить требуемые таблицы. Определить связи между ними и отметить поля, необходимые для вывода. Они появятся внизу на вкладке Selection. А на закладке Edit можно будет просмотреть текст запроса. На закладке Perfomance Analisys есть очень полезная информация о быстродействии и количестве чтений с каждой таблицы. 3.3 Разработка пользовательского интерфейсаЕсть два способа добиться хорошего оформления таблиц. Попробовать самостоятельно улучшать стандартный DBGrid или использовать компоненты сторонних производителей, предоставляющих альтернативу стандартному компоненту. При выполнении работы надо учитывать современные тенденции и стандарты, то есть делать так, чтобы программа выглядела современной, похожей на офисные приложения. Используя компоненты от EhLib можно улучшить стандартный DBGrid, добавив новые возможности: автоматический расчет итоговых значений (сумма, среднее значение, количество записей), экспорт данных и т.д. Устаревший дизайн стандартной таблицы теперь можно легко заменить стильной конструкцией DBGridEh, изменив свойство Flat. Также есть богатый выбор различных цветовых схем выделения данных. Практически всегда, разрабатывая приложения для работы с базами данных, приходится выделять каким-нибудь образом данные, подпадающие под некоторое условие. Это может быть и уровень продаж определенной менеджера, достигший критически низкого уровня, и «минусовые» остатки на складе. Чтобы не пропустить такие происшествия, программа должна правильно выделять это в таблице. Для этого достаточно прописать в событии OnGetCellParams нужное условие и параметры выделения (размеры, цвет шрифта, цвет фона). Важнейшим элементом работы с прикладными программами является возможность переноса данных в офисные приложения, например, в Microsoft Office. То есть часто бывает недостаточно просто создать отчет и вывести его в таблицу. Как правило, потом требуется, чтобы он был предоставлен в виде документа Excel для последующих манипуляций. Можно создавать различные OLE – объекты и, перебирая нужные записи в DataSet, копировать их в ячейки Excel. Этот способ довольно гибкий, так как позволяет формулировать качественные отчеты, предварительно оформив их. То есть добавлять заголовки, формулы, делать выделение критических данных и т.д. Но вот копирование по строкам сильно замедляет создание отчета, особенно если данных много. К тому же уйдет много времени на программирование переноса данных. Поэтому когда речь идет не о создании красивого оформления, а о скорости и простоте экспорта данных лучше использовать средства EhLib. Эта библиотека позволяет одним вызовом функции записывать содержимое таблицы в форматы.xls,.rtf,.html,.txt,.csv. Также полезна функция копирования в буфер выделенных данных. Например, при наличии нескольких офисов, которые в течении дня обмениваются данными о наличии у них количества товара. Менеджерам достаточно скопировать нужные данные и вставить их в любое приложение: почтовый клиент, ICQ. При работе с большими объемами данных бывает очень удобно не только отсортировывать данные по какому-либо полю, но и группировать («свернуть») по значениям одного из полей, чтобы потом можно было развернуть любую из подгрупп щелчком и просмотреть её содержимое. К примеру, организуя рассылку товаров по множеству городов по неким направлениям, не всегда удобно листать отсортированный по городам массив данных. Удобнее сгруппировать данные по городу и разворачивать города только нужного направления. Используя DropDownBox в DBGridEh, можно легко решать подобные задачи. Менеджеру будет удобнее просматривать отчёты о продажах используя привычный Excel.(Рис.1) Для начала нужно установить драйвер ODBC Firebird. Запустить Excel. Выбрать меню Данные, Импорт внешних данных, Создать запрос. После проверки запроса необходимо обязательно сохранить запрос (кнопка с изображением дискеты). Запрос будет сохранен вместе со всеми параметрами алиаса, поэтому для "распространения" запроса на несколько компьютеров вовсе необязательно создавать алиас ODBC на каждом (конечно, ODBC-драйвер и клиентскую часть IB/FB все равно придется устанавливать на этих компьютерах). CREATE PROCEDURE NEW_PROCEDURE returns ( kld numeric(15,0), movie varchar(50), famio varchar(50)) as declare variable idm integer; declare variable cl integer; declare variable dt date; begin for select deal.cl_id, deal.d_d, deal.id_m from deal into:cl,:dt,:idm do begin kld = current_date - dt; if (:kld > 12) then begin select client.fio from client where client.id_c =:cl into:famio; select movie.name_film from movie where movie.id =:idm into:movie; suspend; end end end^ Инструкция пользователя Пользовательский интерфейс построен в соответствии с классическими требованиями и правилами системы Windows, правилами системы Delphi. Основными задачами при построении интерфейса были: простота, удобство.Программный проект включает в себя 7 оконных форм (одна из них форма главного меню), 4 из них являются непосредственно рабочими (т.е. здесь происходит ввод, обработка и корректирование данных), 3 – формы отображения обработанных данных.При открытие программы появляется главная форма (fmMain) (Рис. 1), на которой расположены таблицы и соответствующие им элементы управления. Если есть задолжники, у которых на руках находятся диски, то вместе с главной формой появляется дочерняя форма «Задолжники»где можно увидеть наименование диска и данные задолжника и количество дней. Для удобства пользователя главная форма содержит несколько вкладок, где и находятся таблицы. Работать с базой можно как непосредственно из главной формы, так и вызвав отдельное окно из главного меню формы. Так пункт меню «Файл» содержит такие подпункты как «Новое» и «Выход». Сделать новую запись в таблице Клиенты(CLIENT) можно выбрав «Файл» -> «Новое..» -> «Клиент». После чего появится окно «Клиент» (Рис. 2), где пользователю представляется возможность заполнения каждого из предложенного полей. Кнопки «Удалить» и «Исправить» в режиме вставки не активны.Процесс редактирования данных происходит в том же самом окне, при выборе меню «Правка» -> «Изменить..» -> «Клиент». В этом же окне появляются уведомления пользователя о недопустимых ошибках. В таблице Клиенты(CLIENT) обязательно для заполнения поле ID_C, если пользователь забывает заполнить это поле, программа уведомит его об этом.Кнопка «Удалить» позволяет удалить запись из базы. Нельзя удалить данные о клиенте, если в таблице «Счета» есть связанные с ним записи, программа предупреждает об этом пользователя, показывая соответствующее сообщение (Рис. 4). В режиме изменение неактивна кнопка «Запись» и появляется дополнительная панель с кнопками навигации по таблице. И, наконец, для завершения работы с формой «Клиент» нужно нажать кнопку закрытия окна, и пользователь попадает на форму главного меню. При редактировании таблицы Фильмы пользователю нужно учитывать, что невозможно удалить данные о фильме, если его количество на складе больше 0. При выборе пункта меню «Счёт» или соответствующей вкладки главной формы пользователь может работать со счетами клиентов. При появлении окна «Новое..» -> «Счёт» пользователь должен ввести штрих код фильма и выбрать фамилию клиента, остальные поля заполняются автоматически (поля - стоимость и дата и возврат). Дата выставляется текущая, а поле стоимость изначально берется из таблицы MOVIE а потом высчитывается с учетом скидок клиенту, возврату автоматически присваивается “N”. Когда клиент возвращает фильм, то следует поставить в этом поле “Y” в ручную или через сканер. При этом количество фильмов в базе увеличивается на 1. На вкладке Счета также есть кнопки «Режим master detail» и «Cведенная таблица». При нажатии на кнопку «Сведенная таблица». Появляется окно с этой таблицей, которая является аналогом таблицы «Счета». Такая таблица может только отображать данные, редактировать их невозможно. Удобство её заключено в том, что листаться она будет заметно быстрее. Листание полного экрана таблицы состоящей из тысячи записей происходит в доли секунды, в то время как таблица «Счета» листается с заметными задержками. Кнопкой «Режим master detail» можно вызвать окно, где пользователь может одновременно просматривать и редактировать данные о клиенте и его счетах. Выбрав меню «Поиск» можно задействовать поиск по таблицам. Поиск по строковому полю позволяет искать по части слова и показывает все формы этого слова. Последняя вкладка «SQL» (Рис. 5) позволяет продвинутым пользователям выполнять различные действия с базой данных, такие как поиск, выборка данный и т.д. Менеджеру будет удобнее просматривать отчёты используя привычный Excel. Для удобства менеджера в Excel есть отчёты по заказам за период, отчёт по персоналу, поиск лучшего клиента месяца и т.д. При этом не требуется устанавливать на машину клиентское приложение. Список литературы 1. Фаронов В.В. Delphi 5. Руководство программиста. Нолидж. 2001. 2. Фаронов ВВ. Delphi 2005 Разработка приложений для баз данных и интернета. — СПб: Питер, 2006. 3. Хансен Г., Хансен Д. Базы данных. Разработка и управление. — М., Бином. 2000. ПриложениеЛистинг программыUnit2: interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, DB, IBCustomDataSet, Grids, DBGrids, StdCtrls, ExtCtrls, DBCtrls, ComCtrls, IBTable, XPMan, Menus, IBQuery; type TForm2 = class(TForm) DBGrid1: TDBGrid; DataSource1: TDataSource; Button1: TButton; PageControl1: TPageControl; TabSheet1: TTabSheet; TabSheet2: TTabSheet; TabSheet3: TTabSheet; DBNavigator1: TDBNavigator; DBGrid2: TDBGrid; DataSource2: TDataSource; Button2: TButton; DBNavigator2: TDBNavigator; DBGrid3: TDBGrid; Panel1: TPanel; DataSource3: TDataSource; Button3: TButton; TabSheet4: TTabSheet; XPManifest1: TXPManifest; Button4: TButton; MainMenu1: TMainMenu; N1: TMenuItem; N2: TMenuItem; N4: TMenuItem; N5: TMenuItem; N6: TMenuItem; N3: TMenuItem; N7: TMenuItem; N8: TMenuItem; N9: TMenuItem; About1: TMenuItem; N10: TMenuItem; N11: TMenuItem; N12: TMenuItem; N13: TMenuItem; N14: TMenuItem; DBGrid4: TDBGrid; Edit1: TEdit; IBQuery1: TIBQuery; DataSource4: TDataSource; procedure Button4Click(Sender: TObject); procedure N12Click(Sender: TObject); procedure N6Click(Sender: TObject); procedure N4Click(Sender: TObject); procedure N3Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form2: TForm2; implementation uses Unit3, Unit1, Unit4, Unit5, Unit6; {$R *.dfm} procedure TForm2.Button1Click(Sender: TObject); begin Form1.Show; end; procedure TForm2.Button2Click(Sender: TObject); begin try DataSource1.DataSet.Delete; except ShowMessage('Нельзя удалить данные о клиенте если в таблице База есть связанные записи!'); end; end; procedure TForm2.Button3Click(Sender: TObject); begin Form4.Show; end; procedure TForm2.N3Click(Sender: TObject); begin Form2.Close; end; procedure TForm2.N4Click(Sender: TObject); begin Form5.Show; Form5.Button1.Enabled:=true; Form5.Panel2.Visible:=false; Form5.Button3.Enabled:=false; Form5.Button4.Enabled:=false; end; procedure TForm2.N6Click(Sender: TObject); begin Form6.Show; end; procedure TForm2.N12Click(Sender: TObject); begin Form5.Show; Form5.Button1.Enabled:=false; DataSource1.DataSet.Cancel; DataSource1.DataSet.First; Form5.Panel2.Visible:=true; Form5.Button3.Enabled:=true; Form5.Button4.Enabled:=true; end; procedure TForm2.Button4Click(Sender: TObject); begin if Edit1.Text <>'' then begin IbQuery1.SQL.Text:=Edit1.Text; Form2.DataSource4.DataSet.Active:=true; end else ShowMessage('Пустой запрос!'); end; end. Unit4: unit Unit4; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, DB, Grids, DBGrids, IBCustomDataSet; type TForm4 = class(TForm) IBDataSet1: TIBDataSet; DBGrid1: TDBGrid; DBGrid2: TDBGrid; DataSource1: TDataSource; DataSource2: TDataSource; CheckBox1: TCheckBox; procedure CheckBox1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form4: TForm4; implementation uses Unit2, Unit3; {$R *.dfm} procedure TForm4.CheckBox1Click(Sender: TObject); begin if CheckBox1.State = cbchecked then begin DataModule3.IBDataSet1.Active:=False; Form4.IBDataSet1.SelectSQL.SetText('SELECT * FROM DEAL WHERE CL_ID =:ID_C'); Form4.IBDataSet1.Open; DataModule3.IBDataSet1.Open; end else begin Form4.IBDataSet1.Close; DataModule3.IBDataSet1.Close; Form4.IBDataSet1.SelectSQL.SetText('SELECT * FROM DEAL'); Form4.IBDataSet1.Active:=True; DataModule3.IBDataSet1.Active:=True; end; end; end. Unit5: unit Unit5; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, DBCtrls, Mask, DB, IBCustomDataSet; type TForm5 = class(TForm) DBEdit1: TDBEdit; Label1: TLabel; Label2: TLabel; Button1: TButton; Button2: TButton; Panel1: TPanel; DBMemo1: TDBMemo; DataSource1: TDataSource; Panel2: TPanel; Button3: TButton; Button4: TButton; Button5: TButton; Button6: TButton; procedure Button6Click(Sender: TObject); procedure Button5Click(Sender: TObject); procedure Button4Click(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormShow(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form5: TForm5; implementation uses Unit2, Unit4, Unit1, Unit3; {$R *.dfm} procedure TForm5.Button1Click(Sender: TObject); var name,p:string; begin name:=DbEdit1.Text; p:= DbMemo1.Text; try DataSource1.DataSet.FieldByName('FIO').AsString:=name; DataSource1.DataSet.FieldByName('PASPORT').AsString:=p; DataSource1.DataSet.Post; DataSource1.DataSet.Append; except ShowMessage('Поле ФИО обязательно для заполнения'); end; end; procedure TForm5.Button2Click(Sender: TObject); begin DbEdit1.Clear; DbMemo1.Clear; end; procedure TForm5.Button3Click(Sender: TObject); begin try Form2.DataSource1.DataSet.Delete; except ShowMessage('Нельзя удалить данные о клиенте если в таблице База есть связанные записи!'); end; end; procedure TForm5.FormShow(Sender: TObject); begin DataSource1.DataSet.Append; end; procedure TForm5.FormClose(Sender: TObject; var Action: TCloseAction); begin DataSource1.DataSet.Cancel; end; procedure TForm5.Button4Click(Sender: TObject); begin Form2.DataSource1.DataSet.Post; end; procedure TForm5.Button5Click(Sender: TObject); begin Form2.DataSource1.DataSet.Prior; end; procedure TForm5.Button6Click(Sender: TObject); begin Form2.DataSource1.DataSet.Next; end; end. Unit6: interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, DB, DBCtrls, StdCtrls, IBCustomDataSet, IBQuery, Mask; type TForm6 = class(TForm) DBLookupComboBox1: TDBLookupComboBox; DataSource1: TDataSource; Edit1: TEdit; Button1: TButton; Label1: TLabel; Label2: TLabel; IBQuery1: TIBQuery; DataSource2: TDataSource; DBEdit1: TDBEdit; procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure Button1Click(Sender: TObject); procedure FormShow(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form6: TForm6; s:string; implementation uses Unit3; {$R *.dfm} procedure TForm6.FormShow(Sender: TObject); begin DataSource1.DataSet.Append; end; procedure TForm6.Button1Click(Sender: TObject); var s: string; begin Form6.IBQuery1.Active:=false; s:='select MONEY from movie where movie.id = '+ Edit1.Text; Form6.IBQuery1.SQL.text:=s; Form6.IBQuery1.Active:=true; Form6.DBEdit1.DataField:='MONEY'; DataSource1.DataSet.FieldByName('DEN').AsString:=Form6.DBEdit1.Text; DataSource1.DataSet.FieldByName('ID_M').AsString:=Edit1.Text; DataSource1.DataSet.Post; DataSource1.DataSet.Append; end; procedure TForm6.FormClose(Sender: TObject; var Action: TCloseAction); begin DataSource1.DataSet.Cancel; end; end. Unit7: interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm7 = class(TForm) ComboBox1: TComboBox; Button1: TButton; Edit1: TEdit; ComboBox2: TComboBox; procedure ComboBox2Change(Sender: TObject); procedure Button1Click(Sender: TObject); procedure ComboBox1Change(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form7: TForm7; tb,k:string; implementation uses Unit2; {$R *.dfm} procedure TForm7.ComboBox1Change(Sender: TObject); begin if Combobox1.Items.Strings[Combobox1.ItemIndex]='Фильмы' then begin tb:='MOVIE'; Combobox2.Items.Clear; Combobox2.Items.Add('ID'); Combobox2.Items.Add('NAME_FILM'); Combobox2.Items.Add('DIRECTOR'); Combobox2.Items.Add('KOL'); Combobox2.Items.Add('MONEY'); Combobox2.Items.Add('GANR'); Combobox2.Items.Add('DESCRIPTION'); end else begin tb:='CLIENT'; Combobox2.Items.Clear; Combobox2.Items.Add('ID_C'); Combobox2.Items.Add('FIO'); Combobox2.Items.Add('PASPORT'); end; if Combobox1.Items.Strings[Combobox1.ItemIndex]='Счета' then begin tb:='DEAL'; Combobox2.Items.Clear; Combobox2.Items.Add('ID_D'); Combobox2.Items.Add('ID_M'); Combobox2.Items.Add('CL_ID'); Combobox2.Items.Add('DEN'); Combobox2.Items.Add('D_D'); end; end; procedure TForm7.Button1Click(Sender: TObject); var zapros: string; begin if (k = 'ID_C') or (k = 'ID') or (k = 'ID_D') or(k='KOL') or (k='MONEY') or(k='ID_M') or (k='CL_ID') then zapros:='SELECT * from '+tb+' where '+k+'='+Edit1.Text else zapros:='SELECT * from '+tb+' where '+k+' LIKE '+'''%'+Edit1.Text+'%'''; Form2.IBQuery1.SQL.Text:=zapros; Form2.DataSource4.DataSet.Active:=true; Form7.Close; Form2.PageControl1.ActivePage:= Form2.PageControl1.Pages[4]; Form2.FocusControl(Form2.PageControl1); end; procedure TForm7.ComboBox2Change(Sender: TObject); begin k:=Combobox2.Items.Strings[Combobox2.ItemIndex]; end; end. Скрипты: DOMAINS: CREATE DOMAIN D_GANR AS VARCHAR(10) CHARACTER SET NONE NOT NULL CHECK (VALUE IN ('comedy', 'action', 'melodramm', 'fantasy', 'horror')) COLLATE NONE Tables: CLIENT: /******************************************************************************/ /**** Tables ****/ /******************************************************************************/ CREATE GENERATOR GEN_CLIENT_ID_C; CREATE TABLE CLIENT ( ID_C INTEGER, FIO VARCHAR(50) NOT NULL, PASPORT VARCHAR(50) ); /******************************************************************************/ /**** Primary Keys ****/ /******************************************************************************/ ALTER TABLE CLIENT ADD PRIMARY KEY (ID_C); /******************************************************************************/ /**** Triggers ****/ /******************************************************************************/ SET TERM ^; /******************************************************************************/ /**** Triggers for tables ****/ /******************************************************************************/ /* Trigger: TRIG_CLIENT */ CREATE TRIGGER TRIG_CLIENT FOR CLIENT ACTIVE BEFORE INSERT POSITION 0 AS BEGIN IF (NEW.id_c IS NULL) THEN NEW.id_c = GEN_ID(gen_client_id_c,1); END ^ DEAL: /******************************************************************************/ /**** Tables ****/ /******************************************************************************/ CREATE GENERATOR GEN_DEAL_ID; CREATE TABLE DEAL ( ID_D INTEGER, ID_M INTEGER NOT NULL, CL_ID INTEGER NOT NULL, DEN NUMERIC(4,2), D_D DATE ); /******************************************************************************/ /**** Primary Keys ****/ /******************************************************************************/ ALTER TABLE DEAL ADD PRIMARY KEY (ID_D); /******************************************************************************/ /**** Foreign Keys ****/ /******************************************************************************/ ALTER TABLE DEAL ADD FOREIGN KEY (CL_ID) REFERENCES CLIENT (ID_C) ON UPDATE CASCADE; ALTER TABLE DEAL ADD FOREIGN KEY (ID_M) REFERENCES MOVIE (ID) ON DELETE CASCADE ON UPDATE CASCADE; /******************************************************************************/ /**** Triggers for tables ****/ /******************************************************************************/ /* Trigger: DEC_MONEY */ CREATE TRIGGER DEC_MONEY FOR DEAL ACTIVE AFTER INSERT POSITION 0 AS declare variable x integer; begin Select Count(New.cl_id) from DEAL into:x; if (:x > 3) then begin update Deal set Deal.den = (DEAL.den - DEAL.den/100*10) where DEAL.id_d = New.id_d; end end /* Trigger: SUB_MOVIE */ CREATE TRIGGER SUB_MOVIE FOR DEAL ACTIVE AFTER INSERT POSITION 0 AS begin update movie set movie.kol = movie.kol - 1 where movie.id = new.id_m; end /* Trigger: TRIG_DEAL_BI */ CREATE TRIGGER TRIG_DEAL_BI FOR DEAL ACTIVE BEFORE INSERT POSITION 0 AS BEGIN IF (NEW.Id_d IS NULL) THEN NEW.Id_d = GEN_ID(Gen_DEAL_ID,1); END MOVIE: /******************************************************************************/ /**** Tables ****/ /******************************************************************************/ CREATE GENERATOR GEN_DEAL_ID; CREATE TABLE DEAL ( ID_D INTEGER, ID_M INTEGER NOT NULL, CL_ID INTEGER NOT NULL, DEN NUMERIC(4,2), D_D DATE ); /******************************************************************************/ /**** Primary Keys ****/ /******************************************************************************/ ALTER TABLE DEAL ADD PRIMARY KEY (ID_D); /******************************************************************************/ /**** Foreign Keys ****/ /******************************************************************************/ ALTER TABLE DEAL ADD FOREIGN KEY (CL_ID) REFERENCES CLIENT (ID_C) ON UPDATE CASCADE; ALTER TABLE DEAL ADD FOREIGN KEY (ID_M) REFERENCES MOVIE (ID) ON DELETE CASCADE ON UPDATE CASCADE; /******************************************************************************/ /**** Triggers for tables ****/ /******************************************************************************/ /* Trigger: DEC_MONEY */ CREATE TRIGGER DEC_MONEY FOR DEAL ACTIVE AFTER INSERT POSITION 0 AS declare variable x integer; begin Select Count(cl_id) from DEAL where cl_id = New.cl_id group by cl_id into:x; if (:x > 3) then begin update Deal set Deal.den = (DEAL.den - DEAL.den/100*10) where DEAL.id_d = New.id_d; end end /* Trigger: SUB_MOVIE */ CREATE TRIGGER SUB_MOVIE FOR DEAL ACTIVE AFTER INSERT POSITION 0 AS begin update movie set movie.kol = movie.kol - 1 where movie.id = new.id_m; end /* Trigger: TRIG_DEAL_BI */ CREATE TRIGGER TRIG_DEAL_BI FOR DEAL ACTIVE BEFORE INSERT POSITION 0 AS BEGIN IF (NEW.Id_d IS NULL) THEN NEW.Id_d = GEN_ID(Gen_DEAL_ID,1); END EXCEPTION: CREATE EXCEPTION NO_DELETE 'Нельзя удалить фильм если он имеется на складе!'; VIEW: CREATE VIEW BESTCLIENT(FIO) AS select FIO from client where id_c =(select cl from(select deal.cl_id as cl, count (cl_id) as col from deal group by deal.cl_id HAVING count (cl_id) >=All (select count (cl_id) as col from deal group by deal.cl_id))); |