Настройка параметров доступа к данным в C++ Builder

         

Библиотека Borland Database Engine (BDE)


Если созданное с помощью С++ Builder приложение в процессе работы обращается к базам данных, оно, как правило, использует для этой цели библиотеку BDE (Borland Database Engine), основанную на технологии IDAPI (Integrated Database Application Program Interface). Эта библиотека устанавливается автоматически при установке С++ Builder. По умолчанию она устанавливается в каталог C:\Program Files\Borland\Common Files\BDE.

Следует отметить, что файлы, входящие в состав библиотеки BDE, предназначены для использования не только приложениями, созданными с помощью С++ Builder, но и многими другими продуктами Borland (Visual dBase, Paradox, Delphi, Borland C++, IntraBuilder), созданными на их основе приложениями, а также офисными приложениями Corel (например, электронной таблицей Quattro Pro), генератором отчетов Crystal Reports (Seagate Software) . Поэтому при наличии нескольких использующих BDE приложений все 32-разрядные приложения (в том числе C++ Builder) используют установленную последней 32-разрядную версию BDE. В этом случае по умолчанию программа установки C++ Builder предложит поставить BDE в каталог, где установлена уже используемая версия BDE.

Рис.1. Связь приложений с источниками данных с помощью BDE

BDE обеспечивает для созданных приложений:

непосредственный доступ к локальным базам данных (dBase, Paradox, текстовые файлы) доступ к SQL-серверам (Oracle, Sybase, MS SQL Server, InterBase, Informix, DB2) с помощью драйверов Borland SQL Links доступ к любым источникам данных, имеющим драйвер ODBC (Open DataBase Connectivity), например, к файлам электронных таблиц (Excel, Lotus 1-2-3), серверам баз данных, не имеющим драйверов SQL Links (например, Gupta/Centura) создание приложений клиент-сервер, использующих разнородные данные высокую производительность при работе с плоскими таблицами использование SQL (Structured Query Language - язык запросов к серверным СУБД), в том числе при работе с локальными данными изоляцию приложения от средств языковой поддержки изоляцию приложения от конфигурации системы и сети



DBase


При работе с таблицами dBase настройка соответствующего драйвера сводится к настройке следующих параметров:

ПараметрОписаниеЗначение по умолчанию



VERSION Внутренний параметр BDE 1.0
TYPE Тип сервера (SQL-сервер или файловый сервер) FILE
LANGDRIVER Языковый драйвер, определяющий набор символов и порядок алфавитной сортировки dBASE ENU cp437
LEVEL Версия формата dBase при создании таблиц 5
MDX BLOCK SIZE Размер блока, отводимого под индексные файлы *.mdx. Может быть целым числом, кратным 512 K 1024
MEMO FILE BLOCK SIZE Размер блока, отводимого под файлы memo-полей *.dbt. Может быть целым числом, кратным 512 K 1024

При установке параметров псевдонима нужно указать значение параметра PATH - пути к каталогу, где расположены таблицы базы данных (это может быть и сетевой диск).

С языковой настройкой таблиц dBase обычно не возникает проблем. Для DOS-кодировки обычно используется языковый драйвер dBASE RUS cp866, а для Windows - 'ascii' ANSI.

Следует отметить, что к таблицам dBase можно обращаться, используя ODBC.

Особое внимание следует обратить на то, что расширение *.dbf имеют не только таблицы формата dBase, но и таблицы Clipper, FoxBase, FoxPro. Однако эти СУБД могут иметь другой формат индексных файлов и мемо-полей, которые в явном виде могут не поддерживаться библиотекой BDE (например, индексы *.cdx). В этом случае рекомендуется либо доступ через ODBC (что не всегда эффективно с точки зрения производительности), либо использование библиотек третьих фирм, обеспечивающих интерфейс с такими СУБД (например, Apollo компании SuccessWare).



InterBase


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

ПараметрОписаниеЗначение по умолчанию

BLOBS TO CACHE Определяет, сколько BLOB-полей кэшируется на рабочей станции. Возможные значения: 64 - 65536 64
BLOB SIZE Определяет размер буфера для BLOB-полей, передаваемых в результате запроса. Возможные значения - 32-100 К. Параметр применим только в случае нередактируемых данных 32 К

Отметим, что при соединении с локальным сервером InterBase следует указывать путь к файлу базы данных.

При возникновении проблем связи C++ Builder с InterBase следует проверить наличие связи с помощью утилиты Interactive SQL. При наличии связи в Interactive SQL следует проверить параметры конфигурации драйвера и псевдонима BDE, а при отсутствии - попробовать найти ошибки в сетевом протоколе, проверив соединение с помощью утилит PING и TELNET.

Более подробно о работе с C++ Builder можно узнать из книги Н.З.Елмановой и С.П.Кошеля "Borland C++ Builder", выходящей в августе в издательстве "Диалог-МИФИ".



Настройка драйверов баз данных


Для настройки драйверов баз данных используется страница Drivers утилиты настройки BDE. В левой части этой страницы имеется список доступных для BDE драйверов, куда входят драйверы для dBase и Paradox, установленные на данном компьютере драйверы SQL Links для доступа к серверным СУБД, а также имена ODBC-источников данных, созданные с помощью 32-разрядного администратора ODBC панели управления Windows (рис. 5.2).

Рис. 2. Настройка драйверов баз данных

При нажатии на кнопку New ODBC Driver можно добавить в список новый ODBC-источник данных (перед этим, естественно, следует установить соответствующий ODBC-драйвер и описать источник данных с помощью ODBC-администратора в панели управления Windows). Можно также удалить ODBC-драйвер из файла конфигурации BDE (Delete ODBC Driver).

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



Настройка параметров отображения даты, времени и чисел


Страница Date позволяет указать параметры отображения дат (см. табл.2).

Таблица 2. Параметры настройки отображения дат

ПараметрОписаниеЗначение по умолчанию

SEPARATOR Символ-разделитель числа, месяца и года Значение, содержащееся в настройках панели управления Windows 95/NT
MODE Параметр, определяющий порядок следования числа. месяца и года. Может принимать значения: 0(MDY), 1( DMY), 2(YMD). Значение, содержащееся в настройках панели управления Windows 95/NT
FOURDIGITYEAR Параметр, определяющий отображаемое число цифр года. Может принимать значения: TRUE (4 цифры), FALSE (2 цифры) TRUE
YEARBIASED Параметр, определяющий, прибавлять или нет 1900 к значению года, если предыдущий параметр равен FALSE TRUE
LEADINGZEROM Параметр, определяющий, указывать ли лидирующие нули перед значением месяца, если оно является однозначным числом. FALSE
LEADINGZEROD Параметр, определяющий, указывать ли лидирующие нули перед значением числа, если оно является однозначным числом. FALSE

Страница Time позволяет указать параметры отображения времени (см. табл. 3).

Таблица 3. Параметры настройки отображения времени

ПараметрОписаниеЗначение по умолчанию

TWELVEHOUR Параметр, определяющий интервал отображения часов: 0-12 (TRUE) или 0-24 (FALSE) TRUE
AMSTRING Символьная строка для указания первой половины дня, если TWELVEHOUR=TRUE AM
PMSTRING Символьная строка для указания второй половины дня, если TWELVEHOUR=TRUE PM
SECONDS Параметр, определяющий, указывать ли секунды в значении времени TRUE
MILSECONDS Параметр, определяющий, указывать ли миллисекунды в значении времени . FALSE

Страница Number позволяет указать параметры отображения числовых данных (табл. 4).

Таблица 4. Параметры настройки отображения чисел

ПараметрОписаниеЗначение по умолчанию

DECIMALSEPARATOR Символ, отделяющий дробную часть числа Значение, содержащееся в настройках панели управления Windows 95/NT
THOUSANDSEPARATOR Символ, отделяющий друг от друга "тройки" разрядов в многозначных числах Значение, содержащееся в настройках панели управления Windows 95/NT
DECIMALDIGITS Максимальное число десятичных разрядов числа, полученного при преобразовании символьной строки 2
LEADINGZERON Параметр, определяющий, указывать ли нуль перед дробной частью числа, чье абсолютное значение меньше единицы TRUE



Некоторые выводы


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

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

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

|


Таким образом, архитектура клиент/сервер обладает рядом существенных преимуществ по сравнению с традиционной архитектурой информационных систем, основанных на сетевых версиях настольных СУБД: более высокой производительностью, более низким сетевым трафиком, улучшенными средствами обеспечения безопасности и целостности данных, возможностью задания бизнес-правил. Отметим также, что при использовании современных средств проектирования баз данных, и, в частности, CASE-технологии, разработчик имеет возможность возложить на сервер значительную часть проблем, которые ранее были проблемами самих клиентских приложений, что может существенно облегчить их создание.

|



Немного истории


Давайте отвлечемся от современных технических средств и программных продуктов, используемых при построении информационных систем, и вспомним, что происходило два десятилетия назад. В те времена при построении информационных систем самой популярной была модель "хост-компьютер + терминалы", реализованная на базе мэйнфреймов (например, IBM-360/370, или их отечественных аналогов - компьютеров серии ЕС ЭВМ), либо на базе так называемых мини-ЭВМ (например, PDP-11, также имевших отечественный аналог - СМ-4). Характерной особенностью такой системы была полная "неинтеллектуальность" терминалов, используемых в качестве рабочих мест - их работой управлял все тот же хост-компьютер (рис.1)

Рис.1. Этап 1: модель "хост-компьютер + терминалы"

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

В чем были недостатки подобной архитектуры вычислений? Главным образом в полной зависимости пользователя от администратора хост-компьютера. Фактически пользователь (а нередко и программист) не имел возможности настроить рабочую среду под свои потребности - используемое программное обеспечение, в том числе и текстовые редакторы, компиляторы, СУБД, целиком и полностью было коллективным.

Не будет, наверное, большим преувеличением сказать, что в значительной степени именно этот недостаток подобных систем привел к бурному (и не прекратившемуся до сих пор) развитию индустрии персональных компьютеров. Наряду с дешевизной и простотой эксплуатации достаточно привлекательной особенностью настольных информационных систем стала так называемая персонализация рабочей среды, когда пользователь мог выбрать для себя инструменты для работы (текстовый редактор, СУБД, электронную таблицу и др.), наиболее соответствующие его потребностям. Естественно, и инструментов этих на рынке программных продуктов появилось довольно много. Именно в этот период появились электронные таблицы и настольные СУБД (dBase, FoxBase, Сlipper, Paradox и др.), нередко совмещающие в себе собственно СУБД и средства разработки приложений, использующих базы данных.


Рис.2. Этап 2: автономная персональная обработка данных

Следующим этапом развития архитектуры информационных систем было появление сетевых версий вышеупомянутых СУБД, позволяющих осуществлять многопользовательскую работу с общими данными в локальной сети. Этот подход сочетал в себе как удобства персонализации пользовательской среды и простоты эксплуатации, так и преимущества, связанные со вновь открывшимися возможностями совместного использования периферии (главным образом сетевых принтеров и сетевых дисков, в том числе хранящих коллективные данные). Отметим, что большинство информационных систем, реально эксплуатируемых сегодня в нашей стране, имеют именно такую архитектуру (в том числе некоторые информационные системы, реализованные на Delphi и C++Builder), и в случае не очень большого количества пользователей системы, не слишком большого объема данных и количества таблиц, невысоких требований к защите данных этот подход себя, безусловно, оправдывает.



Рис.3. Этап 3: коллективная обработка данных с использованием сетевых версий настольных СУБД и файлового сервера

Недостатки использования сетевых версий настольных СУБД обычно начинают проявляться в процессе длительной эксплуатации информационной системы, когда со временем увеличивается объем введенных пользователями данных, а иногда и число пользователей. Обычно в первую очередь замечается снижение производительности работы приложений, хотя нередко возникают и иные сбои в работе (например, разрушение индексов, нарушение ссылочной целостности данных). Причины этих явлений кроются в самой концепции хранения коллективных данных в файлах на сетевом диске и сосредоточении всей обработки данных внутри пользовательского приложения.

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

Возросший сетевой трафик - не единственная неприятность, подстерегающая администратора и разработчика подобной информационной системы. Весьма частым явлением в этом случае является нарушение ссылочной целостности данных. Возьмем уже ставший классическим пример, приводимый во всех учебниках по базам данных. Имеются две таблицы формата dBase: список заказчиков какой-либо компании, и список их заказов, связанные по какому-либо полю, например, CUST_ID (рис.4). Вполне разумными требованиями, предъявляемыми к такой БД (иногда называемыми бизнес-правилами), являются уникальность значений этого поля в списке заказчиков (иначе как узнать, чьи заказы с этим CUST_ID находятся в таблице заказов?), и отсутствие в списке заказов записей со значениями CUST_ID, отсутствующими в таблице заказчиков (то есть "ничьих" заказов). В случае dBase выполнение таких требований реализуется на уровне логики приложения. При этом практически всегда имеется возможность произвольного редактирования таблиц иными средствами (от dBase III до обычных текстовых редакторов), что может привести к нарушению этих требований. Обычно для предотвращения подобных прецедентов используются различные организационно-технические меры, например, запрещение средствами сетевой ОС доступа к файлам с таблицами иначе как из конкретного приложения. При этом полной гарантии сохранения ссылочной целостности все равно нет, так как остается вероятность так называемых незавершенных транзакций (то есть попытки согласованного изменения данных в нескольких таблицах - например, удаления заказчика вместе со всеми его заказами, во время которого произошел сбой питания, в результате чего удалилась только часть данных). Отметим также, что если информационная система содержит несколько приложений, использующих общие данные, каждое из них должно содержать код, предотвращающий некорректное с точки зрения ссылочной целостности изменение данных.



Рис.4.Пример связи "один-ко-многим"

Каким образом можно избежать подобных неприятностей? Ответ напрашивается сам собой: еще раз подумать об архитектуре информационной системы и сменить ее, если в обозримом будущем ожидаются подобные прецеденты. Использование серверных СУБД является в этом случае наиболее подходящим решением.

| |


Немного о средствах языковой настройки BDE


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

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

Отметим, что в общем случае языковая настройка баз данных и использующих их приложений включает в себя не только настройку параметра LANGDRIVER на страницах Drivers, Aliases и System. Некоторые СУБД имеют свои средства языковой настройки, причем эти средства могут быть многоуровневыми. Например, в случае использования какой-либо серверной СУБД может потребоваться, помимо настройки BDE, настройка языковых параметров сервера, настройка аналогичных параметров клиентской части или даже выбор соответствующей языковой версии сервера. Подробнее эти проблемы будут рассмотрены чуть позже.

Помимо этого, существует проблема, связанная с различиями DOS- и Windows-кодировок для русского языка. Языковые драйверы BDE существуют для обеих кодировок. Какой из них выбрать, зависит от многих факторов: наличия и объема унаследованных данных, наличия других приложений, использующих эти же данные и др. Например, разумно, используя таблицы формата dBase III совместно с приложениями для DOS, созданными на Clipper, применить DOS-кодировку для этих таблиц.



Нормализация данных


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

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

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

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

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

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

| |



О генерации уникальных первичных ключей


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

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

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

В качестве примера рассмотрим, как можно использовать возможности генерации первичных ключей, предоставляемые Oracle, для автоматического заполнения поля TAG таблицы VISIT. С этой целью воспользуемся генератором последовательностей Oracle, создающим последовательности уникальных целых чисел, используемых клиентскими приложениями в качестве значений первичных ключей. Создадим такую последовательность с помощью следующего набора операторов (исполнить их можно с помощью SQL Plus или с помощью утилиты Database Explorer):


create sequence seqtag start with 200 increment by 1 nominvalue nomaxvalue nocycle nocache

На главной форме приложения заменим компонент TDBEdit, в который ранее вводилось значение поля TAG, компонентом TDBText, чтобы исключить возможность ввода этого значения пользователем. В модуль данных нашего клиентского приложения поместим компонент TUpdateSQL, выберем его имя в качестве значения свойства UpdateObject компонента TTable, с помощью которого вводятся данные в таблицу VISIT, сгенерируем операторы SQL для вставки, удаления и модификации записи и изменим оператор SQL для вставки следующим образом:

Insert into VISIT (TAG, STAT_ID, DIAG_ID, PURP_ID, PAT_ID, DOCT_ID, DATE_VIZ) values (seqtag.NEXTVAL, :STAT_ID, :DIAG_ID, :PURP_ID, :PAT_ID, :DOCT_ID, :DATE_VIZ)

Далее изменим свойство CachedUpdates этого компонента TTable на true и обеспечим возможность сохранять в базе данных изменения, накопленные в кэше, переопределив реакцию на нажатие кнопок компонента TDBNavigator либо введя для этой цели либо дополнительные интерфейсные элементы (например, кнопку):

void __fastcall TMAINFORM::Button1Click(TObject *Sender) { DataModule2->Table1->ApplyUpdates(); DataModule2->Table1->CommitUpdates(); }

Метод ApplyUpdates() нужен для сохранения изменений в базе данных, а метод CommitUpdates() - для очистки кэша.

Скомпилировав и выполнив приложение, можно убедиться в том, что первичные ключи в базе данных генерируются автоматически (например, с помощью Database Explorer). Окончательный вид приложения представлен на рис.11.



Рис. 11. Окончательный вид главной формы АРМ медстатистика.

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

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

CREATE TRIGGER MEDIC1.VI_INS BEFORE INSERT ON MEDIC1.VISIT FOR EACH ROW BEGIN UPDATE VISIT SET TAG=seqtag.nextval where TAG=10; END;

Триггер можно создать, например, с помощью утилиты SQL Plus, и с помощью SQL Explorer можно просматривать его текст (рис.12):



Рис.12. Просмотр текста созданного триггера с помощью SQL Explorer.

В этом случае компонент TUpdateSQL уже не требуется, но при этом нужно добавить в приложение код, присваивающий значение полю TAG, так как в противном случае клиентское приложение не допустит отправки запроса на сервер:

void __fastcall TDataModule2::Table1BeforeInsert(TDataSet *DataSet) { Table1TAG->Value=10; }

| |


О проектировании данных для клиент-серверных приложений С++Builder


Наталия Елманова
"Компьютер-Пресс", 1998, N 2

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

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

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

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

Не вдаваясь в подробности теории реляционных СУБД (этой теме посвящено немало книг и статей), перечислим некоторые термины, применяющиеся при проектировании, и основные принципы проектирования данных.



 ODBC-источники


При работе с ODBC-источниками требуется настройка следующих параметров:

ПараметрОписаниеЗначение по умолчанию

VERSION Внутренний параметр BDE 1.0
TYPE Идентификатор ODBC-источника FILE
DLL Имя 16-разрядной динамической библиотеки, содержащей драйвер IDODBC16.DLL
DLL32 Имя 32-разрядной динамической библиотеки, содержащей драйвер IDODBC32.DLL
ODBC DRIVER ODBC-драйвер для соединения с сервером  
DRIVER FLAGS Внутренний параметр BDE  
USER NAME Имя пользователя в диалоге ввода пароля  
ODBS DSN Имя источника данных, описанного в администраторе ODBC  
OPEN MODE Параметр, определяющий, в каком режиме открываются таблицы - READ/WRITE eee READ ONLY READ/WRITE
LANGDRIVER Языковый драйвер, определяющий набор символов и порядок алфавитной сортировки 'ascii'ANSI
SCHEMA CASHE SIZE Число таблиц, чья структура кэшируется. Возможные значения - от 0 до 32 8
SQLQRYMODE Метод выполнения запросов. Возможные значения: LOCAL - запрос обрабатывается только клиентским приложением, SERVER - запрос выполняется только сервером, NULL (пустая строка) - запрос передается клиенту, если сервер не может его обработать. NULL
SQLPASSTHRU MODE Определяет режим совместного использования одного и того же псевдонима направляемыми на сервер и локальными запросами: NOT SHARED - совместное использование запрещено, SHARED AUTOCOMMIT - совместное использованием разрешено с автоматическим завершением транзакций, SHARED NOAUTOCOMMIT - совместное использованием разрешено с завершением транзакций по правилам сервера. SHARED AUTOCOMMIT
TRACE MODE Численное значение, определяющее уровень вывода отладочной информации.  
SCHEMA CACHE TIME Время нахождения информации о структуре таблиц в кэше в секундах от 1 до 2147483647. Другие значения: -1 - до закрытия БД, 0 - информация не кэшируется -1
BATCH COUNT Число записей, помещаемых в пакет до завершения транзакции Число записей, умещающихся в 32 К.
MAX ROWS Максимальное число записей, которые драйвер может доставить на рабочую станцию при выполнении одиночного SQL-запроса -1 (нет ограничений)
ROWSET SIZE Число записей, доставляемых в одном блоке данных (поддерживается не всеми ODBC- драйверами). 20
<
При создании псевдонимов баз данных на страницу Aliases по умолчанию заносятся параметры со страницы Drivers для соответствующего ODBC-драйвера. При необходимости многие из них можно переопределить.

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

Следует обратить внимание на то, что перед описанием ODBC-источника в файле конфигурации BDE обязательно нужно установить соответствующий ODBC-драйвер и описать соответствующий источник данных в панели управления Windows 95/NT, используя соответствующий ODBC-администратор. При этом следует обратить внимание на некоторую терминологическую неувязку. Дело в том, что ODBC-драйвер с точки зрения BDE, создаваемый при нажатии кнопки New ODBC Driver на странице Drivers утилиты конфигурации BDE, на самом деле представляет собой указание не на реальный ODBC-драйвер, установленный в панели управления Windows, а на конкретный источник данных, доступ к которому осуществляется с помощью реального ODBC-драйвера (с точки зрения панели управления). При этом следует еще создать и соответствующий псевдоним базы данных, что окончательно сбивает с толку некоторых начинающих пользователей. Таким образом, последовательность действий при осуществлении доступа к ODBC-источникам следующая: 

Установить нужный ODBC-драйвер (и, возможно, соответствующий ODBC-администратор для панели управления Windows). Описать с помощью ODBC-администратора необходимый источник данных в панели управления. Запустить утилиту конфигурации BDE и нажать кнопку New ODBC Driver на странице Drivers. Придумать и ввести имя так называемого ODBC-драйвера с точки зрения BDE Выбрать "настоящий" ODBC-драйвер из установленных в операционной системе Выбрать имя источника данных Нажать OK. В списке драйверов появится новый так называемый ODBC-драйвер (с точки зрения BDE). Перейти на страницу Aliases и создать псевдоним, связанный со вновь созданным драйвером с точки зрения BDE.



Рис. 6. Описание нового ODBC-драйвера "с точки зрения BDE".

Отметим, что в версии BDE, поставляемой с Delphi 3.0, вся эта терминологическая путаница ликвидирована, а все описанные в реестре Windows источники данных добавляются в список псевдонимов, и тем самым ликвидируется необходимость выполнения описанной выше инструкции. Остается надеяться, что в следующей версии C++ Builder доступ к ODBC-источникам упростится таким же образом

Для корректного отображения русских букв и установки правильного порядка алфавитной сортировки можно попытаться использовать какой-либо из русскоязычных драйверов dBase или Paradox. Однако следует помнить, что некоторые ODBC-драйверы имеют свои процедуры настройки, которые могут, в частности, включать опцию перекодировки OEM->ANSI (т.е. DOS->Windows). Кроме того, если доступ через ODBC осуществляется к какой-либо серверной СУБД, следует обратить внимание на возможности языковой настройки сервера и клиентской части. 


Oracle


Для настройки доступа к серверам Oracle следует настроить примерно тот же набор параметров, что и в случае ODBC-источников. Помимо этого, для драйвера ORACLE существует дополнительный набор параметров:

ПараметрОписаниеЗначение по умолчанию

VENDOR INIT Имя библиотеки для соединения клиента с сервером (ORANT.DLL, ORA72.DLL и др.) ORANT.DLL
SERVER NAME Имя псевдонима (alias) БД, указанного в файле TNSNAMES.ORA. Если сервер локальный, то SERVER NAME=@2:  
NET PROTOCOL TNS - если используется SQL*Net версии 2.0 или выше, или имя сетевого протокола для доступа к серверу, если используется более ранняя версия SQL*Net.  
ENABLE SCHEMA CASHE Разрешается ли кэширование на рабочей станции структуры таблиц, содержащихся на сервере. FALSE
SCHEMA CASHE DIR Каталог для кэширования структуры таблиц. 1.0
ENABLE BCD Разрешен ли перевод числовых и денежных величин в формат BCD (binary coded decimals) во избежание ошибок округления. FALSE
ENABLE INTEGERS Разрешено ли преобразование числовых величин с фиксированной запятой в целый формат. FALSE
LIST SYNONYMS Разрешены ли синонимы (альтернативные имена таблиц и представлений) в структурах таблиц: NONE - нет, PRIVATE - разрешены личные синонимы, ALL - разрешены личные и общие синонимы. NONE

Проблемы установки соединения с Oracle из приложений Borland связаны главным образом с правильной настройкой сетевого программного обеспечения Oracle SQL*Net. Последние версии серверов Oracle (7.2, 7.3) содержат в своем составе SQL*Net версии 2.0 или выше. Для конфигурации SQL*Net 2.0 и выше следует настроить псевдонимы баз данных Oracle с помощью утилиты SQL*Net Easy Configuration, описав сетевое имя или адрес сервера, имя базы данных и тип сетевого протокола. После этого рекомендуется проверить наличие соединения с сервером с помощью утилиты Oracle SQL Plus. Только после проверки соединения можно конфигурировать псевдоним BDE.

При конфигурации псевдонима BDE в качестве сетевого протокола можно указать TNS (Transparent Network Substrate - высокоуровневая надстройка Oracle над сетевыми протоколами). В качестве имени сервера следует указать имя псевдонима базы данных Oracle, указав перед этим именем символ '@' (об этом в документации не сказано). Для локального сервера (или в случае, когда клиентское приложение функционирует на одном компьютере с сервером баз данных, например, Oracle Workgroup Server for Windows NT) в качестве имени сервера можно использовать строку '@2:' .

Для корректного отображения русских букв и установки правильного порядка алфавитной сортировки можно использовать драйверы dBase RUS CP866 или Paradox ANSI Cyrillic в зависимости от того, какая кодировка - DOS или Windows - будет использоваться. Однако корректная работа с русским языком будет обеспечена только в том случае, если удачно подобрано сочетание трех параметров языковой настройки: языковой настройки сервера (она указывается при его установке), языковой настройки клиентской части (значение HKEY_LOCAL_MACHINE//SOFTWARE)//ORACLE//NLS_LANG реестра Windows 95) и собственно языкового драйвера BDE. Подробности языковой настройки клиентской части и сервера можно найти в документации к серверу Oracle. 



Особенности архитектуры клиент/сервер


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

Рис.5. Этап 4: обработка данных в архитектуре клиент/сервер

В чем преимущества клиент-серверных информационных систем по сравнению с их аналогами, созданными на основе сетевых версий настольных СУБД?

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

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

Кроме того, для описания серверных бизнес-правил в наиболее типичных ситуациях (как в примере с заказчиками и заказами) существуют весьма удобные инструменты - так называемые CASE-средства (CASE означает Computer-Aided System Engineering), позволяющие описать подобные правила, и создавать реализующие их объекты базы данных (индексы, триггеры), буквально рисуя мышью связи между таблицами без какого бы то ни было программирования. В этом случае клиентское приложение будет избавлено от значительной части кода, связанного с реализацией бизнес-правил непосредственно в приложении. Отметим также, что часть кода, связанного с обработкой данных, также может быть реализована в виде хранимых процедур сервера, что позволяет еще более "облегчить" клиентское приложение, а это означает, что требования к рабочим станциям могут быть не столь высоки. Это в конечном итоге удешевляет стоимость информационной системы даже при использовании дорогостоящей серверной СУБД и мощного сервера баз данных.

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

Итак, клиент-серверная информационная система состоит в простейшем случае из трех основных компонентов:

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

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

| |



Paradox


При работе с таблицами Paradox настройка соответствующего драйвера сводится к настройке следующих параметров:

ПараметрОписаниеЗначение по умолчанию

VERSION Внутренний параметр BDE 1.0
TYPE Тип сервера (SQL-сервер или файловый сервер) FILE
NET DIR Местоположение файла PDOXUSRS.NET, управляющего совместным использованием таблиц Paradox в сети. FILE
LANGDRIVER Языковый драйвер, определяющий набор символов и порядок алфавитной сортировки 'ascii'ANSI
LEVEL Версия формата Paradox при создании таблиц (3,4,5 или 7) 5
BLOCK SIZE Размер блока, отводимого для хранения записей таблиц Paradox. Может быть целым числом, кратным 1024 K. Возможные значения зависят от значения параметра LEVEL. 2048
FILL FACTOR Максимальный процент заполнения блока для индексных файлов. 95
STRICTINTEGRTY Параметр, определяющий, могут ли таблицы Paradox модифицироваться приложениями, не поддерживающими ссылочную целостность. TRUE

Как и в случае dBase, русские языковые драйверы для Paradox существуют для обеих кодировок - и DOS, и Windows. Однако указание на используемый язык содержится еще и внутри самих таблиц. Поэтому при создании таблицы Paradox (например, с помощью Database Desktop) следует обязательно указать используемый языковый драйвер при описании свойств таблицы. Как показывает опыт, при неверном определении языка таблицы могут возникнуть проблемы при последующем вводе в нее данных, содержащих русские буквы - некоторые из них после выхода из редактируемого поля могут превратиться в латинские.



Перенос унаследованных данных с использованием CASE-средств


Рассмотрим альтернативный способ переноса данных на сервер, более дорогой и сложный, но приводящий в целом к более качественному результату. Этот способ базируется на использовании CASE-средств (CASE расшифровывается как Computer-Aided System Engineering) для восстановления схемы базы данных по имеющимся таблицам (так называемого обратного проектирования), замены платформы и описания связей между таблицами с точки зрения реакции сервера на попытки того или иного изменения данных со стороны клиентского приложения. В качестве такого средства рассмотрим, например, ERwin 3.0 - CASE-средство компании Logic Works, предназначенное для проектирования баз данных и на сегодняшний день являющееся одним из наиболее простых и доступных по цене средств такого класса.

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

Рис.18. Описание ODBC-источника с помощью панели управления Windows

Попробуем осуществить обратное проектирование с помощью ERwin , используя созданный ODBC-источник. Для этого из меню главного окна ERwin выберем опцию Tasks/Reverse Engineering .

Первая проблема, с которой при этом можно столкнуться, заключается в том, что Erwin не поддерживает формат данных dBase 5.0 (с прежними версиями dBase такой проблемы нет), и при обратном проектировании структура таблиц, содержащих графические поля, не всегда восстанавливается. Обычно эта проблема решается путем выбора сходной по структуре платформы (dBase III, Clipper, FoxPro) и последующей коррекции результатов обратного проектирования. Особое внимание при этом следует обращать на специфические типы данных (например, BLOB-поля), так как различия между платформами заключаются, в частности, в способах хранения подобных типов данных (но, разумеется, не только в этом).

Выберем в качестве исходной платформы Clipper, ответим на вопросы, предлагаемые в последующем диалоге (можно оставить то, что предложено по умолчанию) и в результате получим модель данных, похожую на изображенную на рис.19 (она содержит описание всех dBase-таблиц из каталога, содержащего данные для примеров, поставляемых с C++Builder):


Рис.19. Результат обратного проектирования каталога CBUILDER\EXAMPLES\DATA

Отредактируем полученную модель данных, убрав все таблицы, кроме CLIENTS и HOLDINGS, определив ACC_NBR первичный ключ таблицы CLIENTS и изменив тип данных поля IMAGE на МЕМО (опция Column Editor контекстного меню таблицы). Создадим также неидентифицирующую связь "один-ко-многим" между таблицами CLIENTS и HOLDINGS, выбрав для этой цели соответствующую пиктограмму на "плавающей" инструментальной панели.

Далее следует выбрать другую целевую платформу (в нашем случае Oracle). В результате получим примерно следующий вид модели данных:



Рис.20. Примерный вид модели данных для генерации БД в Oracle

Теперь можно описать свойства имеющейся связи между таблицами. Так как это связь "один-ко-многим", это следует явно указать в диалоге, вызываемом с помощью опции Relationship Editor контекстного меню связи. В том же диалоге на другой странице трехстраничного блокнота следует выбрать из предлагаемых выпадающих списков возможную реакцию сервера на попытки нарушения ссылочной целостности со стороны клиента. Например, при попытке удалить запись из таблицы CLIENTS можно либо совершить каскадное удаление (то есть удалить все соответствующие записи из таблицы HOLDINGS), либо запретить удаление, если имеются соответствующие записи в дочерней таблице, с выдачей диагностического сообщения.



Рис.21. Определение реакции сервера на попытки нарушения ссылочной целостности

После этого можно выбрать из меню опцию Tasks/Forward Engineer/Schema Generation и после установки соединения с Oracle сгенерировать базу данных, выбрав в появившейся диалоговой панели опции для генерации структуры. Можно также просмотреть и сохранить скрипт на языке PL/SQL (это процедурное расширение SQL, используемое для написания триггеров и хранимых процедур Oracle), называемый также DDL-сценарием (DDL расшифровывается как Data Definition Language).



Рис.22. DDL-сценарий генерации схемы базы данных

Далее можно попытаться снова воспользоваться Data Migration Wizard для переноса данных, отказываясь при этом от удаления уже сгенерированных таблиц. Однако в ряде случаев удобнее создать приложение для переноса данных из старой БД в новую. Как было отмечено выше, унаследованные данные могут не удовлетворять правилам ссылочной целостности, установленным на сервере. В этом случае от приложения, используемого для переноса данных, требуется некоторая гибкость (например, предоставление возможности редактирования исходных данных или создание дополнительных таблиц, содержащих записи, не удовлетворяющие бизнес-правилам новой базы данных, для последующего анализа).

Создадим простейшее приложение для переноса данных. Для этого создадим форму следующего вида (рис.23):





Рис.23. Форма приложения для переноса данных на сервер

Для переноса данных с одной платформы на другую обычно используется компонент TBatchMove. Этот компонент обеспечивает копирование данных из одной таблицы в другую. Основные свойства этого компонента следующие: Source - таблица (или запрос), откуда копируются данные, Destination - таблица, куда копируются данные, Mapping - определяет соответствие между колонками исходной и результирующей таблиц (для идентичных таблиц это свойство определять не обязательно), Mode - тип перемещения (batAppend - добавляет новые строки в результирующую таблицу, batUpdate - заменяет строки в результирующей таблице на соответствующие строки оригинала, batCopy - копирует строки в результирующую таблицу, переписывая ее, batDelete - удаляет записи в результирующей таблице, соответствующие записям оригинала), KeyViolTableName и ProblemTableName - имена дополнительных таблиц для помещения записей, чье копирование запрещено правилами ссылочной целостности или по каким-либо причинам невозможно (например, из-за несоответствия типов данных), ChangedTableName - имя таблицы для помещения измененных записей. Копирование данных происходит при выполнении метода Execute(). Отметим, что этот метод может быть вызван непосредственно из среды разработки с помощью контекстного меню компонента TBatchMove.

Установим следующие значения свойств используемых компонентов:

КомпонентСвойствоЗначение
Table1DatabaseNameOracle7
Exclusivetrue
TableNameCLIENTS
Activetrue
Table2DatabaseNameBCDEMOS
TableNameClLIENTS.DBF
Activetrue
DataSource1DataSetTable1
DataSource2DataSetTable2
DBGrid1DataSourceDataSource1
DBGrid2DataSourceDataSource2
DBNavigator1DataSourceDataSource1
DBNavigator2DataSourceDataSource2
BatchMove1SourceTable2
DestinationTable1
ModebatAppend
Button1CaptionCLIENTS
Button2CaptionHOLDINGS
Button3CaptionДобавить
Button4CaptionОчистить
Button5CaptionВыход
Создадим также обработчики событий для кнопок:



//-------------------------------------------------------- #include <vcl\vcl.h> #pragma hdrstop #include "upsize1.h" //-------------------------------------------------------- #pragma link "Grids" #pragma resource "*.dfm" TForm1 *Form1; //-------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner) { } //-------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { Table1->Close(); Table2->Close(); Table1->TableName="CLIENTS"; Table2->TableName="CLIENTS.DBF"; Table1->Open(); Table2->Open(); } //-------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { Table1->Close(); Table2->Close(); Table1->TableName="HOLDINGS"; Table2->TableName="HOLDINGS.DBF"; Table1->Open(); Table2->Open(); } //-------------------------------------------------------- void __fastcall TForm1::Button5Click(TObject *Sender) { Table1->EmptyTable(); } //-------------------------------------------------------- void __fastcall TForm1::Button3Click(TObject *Sender) { BatchMove1->Execute(); } //-------------------------------------------------------- void __fastcall TForm1::Button4Click(TObject *Sender) { Close(); } //--------------------------------------------------------

Скомпилируем и запустим приложение. Кнопки CLIENTS и HOLDINGS осуществляют выбор между той или иной парой таблиц. При нажатии кнопки Добавить происходит перенос данных из активной в данный момент таблицы dBase (CLIENTS или HOLDINGS) в соответствующую таблицу Oracle. Отметим, что наличие поддержки ссылочной целостности можно проверить, попытавшись перенести данные из таблицы HOLDINGS до того, как перенесены данные из таблицы CLIENTS. При этом перенос осуществлен не будет, и в процессе выполнения приложения появится диагностическое сообщение примерно следующего вида (рис.24):





Рис.24. Диагностическое сообщение при попытке добавления записей в detail-таблицу при пустой master-таблице.

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

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

Теперь, если мы попытаемся удалить запись из таблицы CLIENTS при наличии связанных с ней записей в таблице HOLDINGS, нам это не удастся. При этом клиентским приложением будет выдано диагностическое сообщение о наличии записей в дочерней таблице (рис. 25):



Рис.25. Диагностическое сообщение при попытке удаления записей из master-таблицы при наличии связанных с ней записей в detail-таблице.

Точно так же окажется невозможным добавить запись с произвольным значением поля ACC_NBR в таблицу HOLDINGS. Причина такого поведения созданной информационной системы очевидна: при проектировании базы данных с помощью ERwin помимо самих таблиц и индексов были созданы также специальные объекты базы данных, называемые триггерами. Триггер - это специальная процедура, выполняющаяся при наступлении определенного события, например, при попытке удаления записи в таблице CLIENTS. При описании свойств связи между таблицами мы выбирали, как сервер будет реагировать на подобные события, и в соответствии с нашим выбором были сгенерированы триггеры для выполнения соответствующих действий (в данном случае - для передачи клиентскому приложению диагностического сообщения).

Разумеется, пользователь приложения должен видеть нечто более вразумительное, нежели англоязычное сообщение с именем триггера и словами про "integrity constraint" и "key violation". Можно сделать это путем перехвата исключения в клиентском приложении, но более предпочтительно делать это на сервере, так как тогда будет исключена необходимость в повторении кода в случае, когда с одной и той же базой данных работают несколько приложений. Современные CASE-средства позволяют это сделать, и интересующиеся этой проблемой могут найти ее решение в документации по используемому CASE-средству и в документации, прилагаемой к соответствующему серверу баз данных.

| |


Перенос унаследованных данных с помощью Data Migration Wizard


Способов переноса данных может быть несколько. Первый, самый примитивный, и, к сожалению, весьма распространенный, представляет собой перенос структур данных и самих данных "как есть" с одной платформы на другую с заменой типов данных настольной СУБД на эквивалентные им типы данных сервера. Этой цели служит утилита Data Migration Wizard, входящая в комплект поставки C++Builder. Рассмотрим ее работу на простом примере из двух связанных таблиц. Для этой цели вполне подойдут таблицы CLIENTS.DBF (список клиентов) и HOLDINGS.DBF (список зданий), связанные отношением "один ко многим". Такой пример выбран потому, что таблица CLIENTS содержит графические и мемо-поля, при переносе которых с платформы на платформу нередко возникают проблемы (в отличие от символьных и числовых полей, для которых обычно можно подобрать эквивалентный тип данных). В качестве серверной СУБД используем 90-дневную trial-версию Personal Oracle 7.2 для Windows 95 или Oracle Workgroup Server 7.2.для Windows NT (в принципе подобный пример можно выполнить и с помощью входящего в комплект поставки С++Builder локального сервера InterBase). Перед тем как выполнить данный пример, запустим сервер и с помощью входящей в комплект поставки утилиты администрирования сервера (в нашем случае Personal Oracle Navigator) опишем пользователя USER1, от имени которого будут создаваться таблицы, проверив заодно наличие соединения с базой данных.

Рис 6. Создание пользователя с помощью Personal Oracle Navigator

Далее опишем параметры псевдонима используемой базы данных:

Рис.7. Создание псевдонима для доступа к данным Oracle

Отметим, что 2: - имя локального сервера Oracle (при работе с Oracle Workgroup Server for Windows NT, расположенном на том же компьютере, что и С++Builder, можно использовать такое же имя сервера). В случае удаленного сервера следует описать местоположение и доступ к базе данных (имя БД, сетевой протокол, IP-адрес или сетевое имя компьютера) с помощью утилиты SQL*Net Easy Configuration, входящей в комплект поставки серверов Oracle последних версий.

После описания доступа к БД рекомендуется проверить правильность настроек BDE. Это можно сделать, запустив SQL Explorer и попытавшись открыть какую-либо из таблиц Oracle (любая современная серверная СУБД, как правило, содержит какие-либо таблицы в качестве примера). Если список таблиц получить не удается, следует проверить, есть ли в переменной окружения PATH каталог типа С:\ORAWIN95\BIN, и есть ли в каталоге WINDOWS\SYSTEM файлы типа ORA72.DLL или ORANT71.DLL.

После проверки настроек BDE можно приступить непосредственно к переносу таблиц. Запустим Data Migration Wizard:


Рис.8. Выбор исходной БД в Data Migration Wizard

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



Рис.9. Выбор таблиц для переноса данных с помощью Data Migration Wizard

После этого получим экран, содержащий список таблиц и индексов, подлежащих переносу.



Рис.10. Список таблиц и индексов, подлежащих переносу.

Если нажать кнопку Modify Mapping Information For Selected Item, получим сведения о том, в какие типы данных будут преобразованы поля исходных таблиц. При необходимости в эти сведения можно внести правки.



Рис.11. Внесение правок в правила преобразования полей

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

Достоинством этого метода переноса данных является его простота. Но при его применении далеко не все преимущества архитектуры клиент/сервер оказываются использованными. Скорость выполнения запросов к данным, хранящимся теперь в серверной базе данных, действительно может возрасти - их будет выполнять сервер. Однако, перенося данные таким способом, мы создали на сервере только то, что было в исходной базе данных - таблицы и индексы. Новые объекты серверной базы данных, реализующие бизнес-правила, такие, как триггеры и хранимые процедуры, при этом созданы не будут - их придется создавать вручную, занимаясь кодированием на процедурном расширении SQL, характерном для данного сервера, либо, как и в случае настольных СУБД, описывать их внутри клиентского приложения, рискуя нарушить ссылочную целостность данных. Если мы попытаемся создать приложение, работающее с только что созданными нами таблицами, то сумеем в этом убедиться.

Для создания такого приложения воспользуемся инструментом под названием Database Form Wizard. Запустим C++Builder, создадим новый проект, удалим из него пустую форму и выберем со страницы Forms репозитария объект Database Form:





Рис.12. Выбор Database Form из репозитария С++Builder

Далее выберем создание формы master/detail c использованием объектов TTable:



Рис.13. Выбор типа будущей главной формы приложения

После выбора псевдонима базы данных Oracle из списка псевдонимов определим master-таблицу. В нашем случае это только что созданная таблица CLIENTS:



Рис.14. Выбор master-таблицы

Затем определим, какие поля этой таблицы нам нужны (можно выбрать все), и как они будут расположены на форме (выберем горизонтальное расположение полей). Затем определим detail-таблицу (в данном случае HOLDINGS), выберем все поля и в качестве способа их отображения выберем размещение их в TDBGrid. Наконец, укажем, что таблицы связаны по полю ACCT_NBR:



Рис.15. Установка связи между таблицами

Далее выбираем опцию Generate a Main Form и в результате получим форму, похожую на представленную на рис. 16:



Рис.16. Вот что обычно получается при использовании Database Form Wizard

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



Рис.17. Главная форма приложения после "приведения в порядок"

Скомпилируем и запустим созданное приложение и рассмотрим, каким образом созданная информационная система реагирует на изменение данных.

Если мы попытаемся удалить первую запись в таблице CLIENTS, нам это удастся, несмотря на то, что в таблице HOLDINGS есть связанные с ней записи. Точно так же можно добавить запись с произвольным значением поля ACC_NBR в таблицу HOLDINGS, и это нам также удастся. Таким образом, в созданной нами базе данных из двух таблиц связь "один-ко-многим" фактически отсутствует.

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

| |


Пример проектирования простейшей информационной системы


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

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

Рис.1. Примерное содержание статистического талона

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

Рис.2. Первый вариант модели данных - выделяем сущности "Врач" и "Пациент"

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

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


Рис.3. Модель данных после нормализации.
Возникает вопрос: а как быть с остальными атрибутами этой сущности? Ведь очевидно, что атрибуты "Ставка" и "Категория" тоже повторяются. Однако атрибут "Категория" - это обычно целое число, и поэтому нет смысла выносить его в отдельный справочник. Что касается атрибута "Ставка", характеризующего продолжительность рабочего времени, то это обычно дробное число (например, 1.25). В принципе можно было бы вынести его в отдельный справочник, но из соображений разумной достаточности в данном примере мы этого делать не будем (нормализуя модель, можно дойти до такого состояния, когда выполнение запросов к таблицам окажется весьма длительным из-за их большого числа).
Теперь рассмотрим сущность "Пациент". Исходя из требования атомарности атрибутов, следует обдумать, является ли таковым адрес пациента. Отметим, что ответ на этот вопрос неоднозначен. Если, например, речь идет о районной поликлинике с делением на участки, очевидно, что следует как минимум выделить в отдельные атрибут номер квартиры и остальную часть адреса (улица, дом, номер корпуса), так как эта остальная часть адреса указывает на принадлежность к определенному участку, а также, возможно, создать сущности "Участок" и "Часть участка" (со сведениями об улице, доме и номере корпуса), связав их между собой и с сущностью "Пациент". С другой стороны, если речь идет о хозрасчетной или ведомственной поликлинике, где адрес может потребоваться главным образом для отправки по почте счетов за услуги, то вполне возможно, что в этом случае адрес может считаться атомарным атрибутом (если, конечно, в дальнейшем не потребуется какая-либо специфическая статистическая обработка данных, связанная с анализом распределения посещений по районам проживания пациентов). Кроме того, если речь идет о районной поликлинике, возможна повторяемость не только частей адресов, но и самих адресов (в случае, если поликлиника обслуживает нескольких жителей одной квартиры). В любом случае, проектируя данные, следует ставить подобные вопросы перед заказчиками и будущими пользователями информационной системы еще на этапе проектирования данных, так как исправления в модели данных гораздо более удобно делать до разработки автоматизированных рабочих мест, нежели исправлять вместе с моделью готовую базу данных и приложения.
Итак, мы создали логическую модель данных. До этого момента можно было думать о предметной области, не вдаваясь в подробности физической реализации разрабатываемой модели. Теперь же следует подумать о физическом проектировании данных, а именно о выборе СУБД, создании таблиц, соответствующих созданным сущностям, типах полей для хранения атрибутов, а также о создании других объектов базы данных, предназначенных для облегчения поиска в таблицах, контроля ссылочной целостности данных, обработки данных, таких, как индексы, триггеры, хранимые процедуры.
Как уже отмечалось в данном цикле статей, использование серверной СУБД значительно облегчает разработку информационных систем по сравнению с использованием плоских таблиц типа dBase или Paradox, так как в последнем случае реализация правил ссылочной целостности, а также механизмов авторизации пользователя и методов ограничения доступа к данным может быть реализована только в приложении (фактически разработчик вынужден "изобретать велосипед при наличии самолетов", создавая в своих приложениях код, уже реализованный в серверах баз данных). Поэтому для реализации данной информационной системы воспользуемся какой-либо серверной СУБД (например, Oracle Workgroup Server 7.2 for Windows NT).Для создания физической модели выберем соответствующую платформу в используемом CASE-средстве и опишем характеристики таблиц, соответствующих описанным в логической модели сущностям, и содержащихся в них полей, соответствующих их атрибутам (рис.4)



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

Рис.5. Описание реакции сервера на попытки нарушения ссылочной целостности данных
После этого можно создать на сервере схему базы данных, либо сгенерировать DDL-сценарий создания базы данных, представляющий собой набор предложений на процедурном расширении языка SQL данной серверной СУБД) с целью его последующего выполнения. В результате выполнения DDL-сценария на сервере должны быть созданы пустые таблицы, а также иные объекты базы данных, которые можно просмотреть с помощью утилиты Database Explorer (рис.6)

Рис.6. Созданные на сервере объекты базы данных
| |

Серверные СУБД и унаследованные данные


Одной из наиболее распространенных проблем, связанных с модернизацией эксплуатируемых информационных систем, является использование в них данных, унаследованных от прежних версий и содержащихся, как правило, в форматах настольных СУБД. В частности, вопросы модернизации устаревших систем на основе xBase и переноса их на платформу Oracle, а также этапы модернизации с организационной точки зрения были подробно проанализированы Алексеем Ярцевым в статье "Миграция из xBase в Oracle'' ("Компьютер -Пресс", 1997, N 8, стр.137-140).

В данной работе хотелось бы рассмотреть некоторые технические аспекты проблемы использования унаследованных данных применительно к С++Builder.

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

| |



Системные настройки BDE


Страница системных настроек позволяет указать параметры системы и сети, используемые BDE и хранящиеся в реестре Windows (рис. 5, табл. 1).

Рис. 5. Страница System утилиты конфигурации BDE.

Таблица 1. Параметры системы и сети, используемые BDE.

ПараметрОписаниеЗначение по умолчанию

VERSION версия BDE  
LOCAL SHARE Если этот параметр равен true, можно использовать одни и те же данные приложениями, использующими BDE, и приложениями, не использующими BDE FALSE
MINBUFSIZE Минимальный размер буфера оперативной памяти для кэширования данных из БД. Возможные значения - от 32 до 65535 Кб, но не более, чем объем доступной Windows оперативной памяти  
MAXBUFSIZE Максимальный размер буфера оперативной памяти для кэширования данных из БД. Должен быть выше, чем MINBUFSIZE, но не более, чем объем доступной Windows оперативной памяти. Должен быть кратен 128. 2048
LANGDRIVER Языковый драйвер, соответствующий национальной версии операционной системы  
MAXFILEHANDLES Максимальное число файлов, открываемых BDE. Может принимать целые значения от 5 до 256 48
SYSFLAGS Внутренний параметр BDE  
LOW MEMORY USAGE LIMIT Максимально допустимый объем основной памяти, используемый BDE 32
AUTO ODBC если этот параметр принимает значение true, используются все ODBC-источники из файла ODBC.INI FALSE
DEFAULT DRIVER драйвер, используемый первым, если тип БД - FILE, и имя таблицы не имеет расширения.  
SQLQRYMODE Метод исполнения запросов к серверам. Может принимать значения NULL, SERVER, LOCAL NULL
SHAREDMEMSIZE Максимальный размер для разделяемой оперативной памяти 2048
SHAREDMEMLOCATION Предпочтительный адрес для размещения разделяемой области памяти. E000 (Windows 95) 7000(Windows NT)



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


Итак, база данных создана. Теперь, наконец, можно заняться созданием автоматизированных рабочих мест.

Сколько и каких автоматизированных рабочих мест должно быть создано, обычно решается на этапе проектирования данных. В данном простейшем случае очевидно, что работа по вводу данных в информационную систему подразделяется на три основных дочерних работы: ввод сведений о врачах поликлиники (это обычно делается в отделе кадров, и соответственно следует создать АРМ инспектора отдела кадров), ввод сведений о пациентах (рабочее место медрегистратора), ввод сведений о статистических талонах (рабочее место медстатистика). Помимо этого, кто-то должен осуществлять заполнение справочников "Цель посещения" и "Статус" (можно добавить эти функции в АРМ медстатистика, так как объем этих таблиц невелик). Что касается списка диагнозов, он может быть либо введен в базу данных кем-либо из персонала поликлиники, либо импортирован администратором базы данных из какого-либо другого формата, так как этот список основан на реально существующем и неоднократно опубликованном документе.

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

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

Первые два АРМ-а создать относительно несложно (одно из них предназначено для ввода данных в одну таблицу, другое - в две таблицы, связанные соотношением "один ко многим"). Для этой цели можно воспользоваться утилитой Database Form Wizard и затем внести небольшие изменения в сгенерированные формы и код, в частности, для обеспечения возможности не использовать мышь при массовом вводе данных, а также для установки фокуса ввода в первое поле формы при создании новой записи (в обработчике события OnNewRecord соответствующего компонента TTable). Кроме того, следует исключить возможность ввода пользователем значения поля PROF_ID в список врачей - в этом случае значение этого поля генерируется автоматически в соответствии со значением в выбранной строке списка специальностей, что исключает попытки создания некорректной записи уже на уровне клиентского приложения (рис. 7,8)


Рис. 7. Автоматизированное рабочее место медрегистратора



Рис. 8. Автоматизированное рабочее место инспектора отдела кадров.

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





Рис.9. Автоматизированное рабочее место медстатистика - ввод справочных таблиц

Используя серверную СУБД и сгенерировав базу данных с учетом правил ссылочной целостности в соответствии со схемой данных, представленной на рис.4, мы, конечно, можем быть уверены, что ввести в базу данных некорректные значения полей DOCT_ID, DIAG_ID, STAT_ID, PURP_ID, PAT_ID сервер пользователю не даст. Однако это вовсе не означает, что можно поместить на форму набор компонентов TDBEdit для ввода данных в эти поля. Такая реализация интерфейса приведет к совершенно неприемлемым условиям труда пользователя, вводящего данные - он должен помнить наизусть все табельные номера, номера карт и коды во вспомогательных таблицах и в случае ошибок сталкиваться с сообщениями, сгенерированными триггерами сервера. Более разумно использовать выбор нужного значения из списка, поэтому для ввода данных в эти поля поместим на форму компоненты TDBLookupCombBox и выберем в качестве значения ListSource источники данных, связанные с соответствующими словарными таблицами, в качестве значения КеуField - имена их первичных ключей, а в качестве ListField - имена полей, в которых хранятся соответствующие названия статусов, диагнозов, имена врачей и др. Теперь пользователь может выбирать значения полей DOCT_ID, DIAG_ID, STAT_ID, PURP_ID, PAT_ID из выпадающих списков, в которых содержатся не коды, а символьные строки (рис 10). Таким образом, мы избавились от необходимости непосредственного ввода пользователем значений внешних ключей, заменив его выбором из соответствующих списков.





Рис.10. Автоматизированное рабочее место медстатистика - ввод статистических талонов.

Такая реализация автоматизированного рабочего места, разумеется, не является идеальной. Если список статусов и целей посещения обычно действительно невелик, и выпадающий список здесь вполне уместен, то список пациентов, скорее всего, будет составлять не меньше сотни строк. Поэтому вполне уместно либо иметь этот список в отсортированном по алфавиту виде (например, создав соответствующий индекс в базе данных, либо используя в качестве источника данных компонент TQuery с соответствующим предложением Order by). В этом случае при наборе начала фамилии пациента указатель в списке автоматически установится на ближайшую подходящую позицию. Примерно так же можно поступить и со списком диагнозов. Возможен также ввод каких-либо признаков (например, специальности врача или типа заболевания) и дальнейший выбор диагноза или фамилии врача из отфильтрованного списка, причем такая фильтрация записей может быть реализована как с помощью параметризованного запроса, выполняемого на сервере, так и с помощью локального фильтра в клиентском приложении. Какую из реализаций выбрать, зависит от размера справочной таблицы - локальные фильтры могут быть более производительны, чем параметризованный запрос, если таблица целиком кэшируется на рабочей станции, то есть ее объем сравним с емкостью буферов для кэширования данных.

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

| |


Создание и настройка псевдонимов баз данных


Для доступа приложений к данным средства разработки Borland используют механизм псевдонимов, описывающих доступ к конкретным источникам данных. Создать описание нового источника данных можно, нажав кнопку New Alias в левой части окна (рис. 6.3, 6.4).

Рис. 3. Выбор псевдонима БД и установка параметров

После этого в появившейся диалоговой панели следует ввести имя-псевдоним для этого источника и выбрать нужный драйвер из предложенного списка (того, что определен на странице Drivers). Имя STANDARD в этом случае соответствует таблицам dBase, Paradox и текстовым файлам (в формате CSV - Comma Separated Value).

Рис. 4.Создание нового псевдонима БД

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



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


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

и атрибут.

Сущность

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

Атрибут

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

Связь

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

Связи обладают свойством, называемым кардинальностью. Например: "Заказчик может иметь 0,1 или много заказов" (связь типа "0,1 или много"), "заказ содержит 1 или много товаров" (связь типа "1 или много"), "у автомобиля ровно 4 колеса" (связь типа "ровно n"), "билет резервируется для 0 или 1 пассажира (связь типа "0 или 1"). Наиболее типичным является первый случай, называемый иногда связью "один ко многим".

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

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

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

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

|



Утилита настройки BDE


При возникновении необходимости доступа к данным в большинстве случаев для их источника (как правило, это какая-либо конкретная база данных) создается псевдоним (alias), имя которого используется приложением. Параметры этого и других псевдонимов, а также параметры настройки драйверов баз данных содержатся в файле idapi32.cfg, расположенном в том же каталоге, что и файлы BDE. Для изменения содержания этого файла, а также значений соответствующих этой библиотеке ключей реестра Windows 95 и Windows NT используется утилита конфигурации BDE - BDECFG32.EXE.

Утилита конфигурации состоит из одной формы, содержащей блокнот из шести страниц.

Страница Drivers содержит параметры доступа к различным типам данных.

Страница Aliases содержит сведения о псевдонимах источников данных, к которым посредством BDE обращаются приложения, установленные на данном компьютере.

Страница System содержит параметры настройки работы самой библиотеки BDE, связанные с использованием памяти, сетевого окружения и других ресурсов, доступных использующим BDE приложениям. Эти параметры содержатся в реестре Windows 95 (или Windows NT).

Страницы Date, Time, Number содержат правила отображения в приложениях календарных дат, времени и числовых данных в соответствии с правилами, принятыми в той или иной стране.



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


Современные средства разработки информационных систем, к числу которых относится C++Builder, ориентированы на широкую поддержку различных СУБД, как настольных, так и серверных. Построение эффективных и надежных с точки зрения сохранности и защиты данных многопользовательских информационных систем, как правило, производится с использованием последних. Создание приложений в архитектуре клиент/сервер с помощью C++ Builder обладает рядом особенностей, отличающих их от приложений, использующих настольные СУБД. Эти особенности и будут рассмотрены в ближайших нескольких статьях данного цикла.
|