Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Самитов Р.К.
БАЗЫ ДАННЫХ. (5-й семестр ВМК)
Информационная система (ИС):
Конкретная ИС всегда связана с конкретной областью применения - предметной областью:
Информационные системы подразделяются на персональные (однопользовательские), групповые и корпоративные. Персональные ИС ориентированы на раздельное использование индивидуальными конечными пользователями. Групповые - на коллективное использование членами рабочей группы, одновременно решающими взаимосвязанные задачи на общей базе данных. Корпоративные ИС ориентированы на масштаб предприятия, могут поддерживать согласованную работу территориально распределенных подразделений предприятия. Групповые и корпоративные ИС предполагают связывание рабочих станций (персональных компьютеров, терминалов...) в вычислительную сеть.
База данных (БД): набор взаимосвязанных файлов данных, предназначенных для решения набора взаимосвязанных задач предметной области.
Обычно ИС имеет дело с большим количеством данных, которые в предметной области с точки зрения ее специалистов сильно взаимосвязаны. По языку Паскаль мы знаем, что данные полезно группировать (в записи, массивы, файлы...), таким способом часть содержательной информации о взаимосвязи данных запоминается в (формальном!!!) описании структуры данных. Однако остаются взаимосвязи и между данными разных файлов, поэтому нужны более мощные средства их описания и использования - языки описания баз данных (DDL) и манипулирования данными (DML).
При одновременном решении взаимосвязанных задач на общей базе данных вполне могут возникать конфликтные ситуации, поэтому нужны средства управления доступом к данным (DCL).
Система управления базами данных (СУБД) - программный комплекс, предназначенный для обработки баз данных; независимый от предметной области, т.е. это программное обеспечение (ПО) общего назначения.
СУБД (в широком смысле) содержит:
Назначение и состав СУБД - системного ядра:
СУБД позволяет обеспечить независимость программ от данных - изменение структуры данных и способа их физического представления (в определенных пределах) не влечет необходимости внесения изменений в прикладные (связанные с предметной областью) программы.
Такая возможность имеет принципиальное практическое значение. Информационные системы развиваются в своем длительном жизненном цикле - усложняются функции ИС и появляются новые функции. Все это неминуемо влечет изменения в структуре БД - появляются новые файлы и новые поля в старых файлах, может измениться тип некоторых полей. Отметим, что программа, написанная на (чистом) языке Паскаль, будет некорректно работать с файлом, даже если изменения произошли только в тех полях, с которыми она непосредственно не работает, - как минимум потребуется изменить описание файла и перетранслировать программу.
Возможность обеспечить независимость по данным открывается благодаря тому, что:
Технология обеспечения независимости по данным основана на концепции 3-х уровневого представления базы данных (ANSI/SPARC-1975):
В рамках этой концепции различаются:
Пользователи информационных систем и, в общем случае, прикладных систем (Application):
Системное программное обеспечение (СПО) доступа к БД:
Две причины усложнения СПО доступа к БД:
Отсюда возникают задачи синхронизации и прав доступа, повышения скорости доступа и повышения гарантий сохранности БД. Централизация механизмов решения этих задач позволяет локализовать ответственность за решение этих задач, а в итоге повысить надежность приемлемого их решения.
Отсюда возникает задача преобразования между способами представления. Даже если конкретная система предназначена для работы с БД фиксированного формата, у разработчиков могут быть основания застраховаться при необходимости сменить базовый формат представления... желательно без излишних трудоемких хлопот...
В простых ситуациях «Программа в целом» может иметь вид цельного загрузочного модуля (.EXE), СПО доступа к БД включено в состав этого загрузочного модуля.
В более сложных случаях «Программа в целом» кроме основного загрузочного модуля может иметь дополнительные компоненты, прежде всего стандартные модули (типа DLL-библиотек) реализующие именно средства доступа к БД. В определенном смысле, эта ситуация мало отличается от предыдущей, поскольку DLL-библиотека определенном смысле действительно является специально препарированной библиотекой описаний процедур, которые могут быть вызваны загрузочным модулем.
Однако по выше рассмотренным причинам могут быть основания не просто сгруппировать СПО доступа к БД в физически отдельные компоненты (типа DLL-библиотек), а пойти дальше - функционально централизовать доступ к БД (и даже к нескольким БД) от различных пользователей (и даже от различных программных систем).
Для такой организации программных систем сегодня существуют стандартизованные технологии и стандартизованные программные компоненты.
Прикладные программные системы (Application), так же функционирующие как отдельные независимые задачи, не имеют возможности прямого доступа к данным БД. Они должны связываться с сервером БД, для того чтобы передать запрос на операцию с БД и получить ответ или другие результаты.
Таким образом, централизуется не только доступ к БД от многих пользователей-задач, но и централизуются сами процессы непосредственной обработки данных БД в одной задаче, обслуживающей запросы многих задач. При такой организации доступа к БД на сети обычно выделяется специальный компьютер для работы на нем сервера БД и хранения самой БД.
ODBC (Open Database Connectivity) стандарт «открытого доступа к БД». ODBC-компоненты обеспечивают средства для связи прикладных программных систем с SQL-серверами БД. Использование ODBC не просто облегчает решение проблем связи, но и позволяет обеспечить высокий уровень независимости прикладной системы от конкретных SQL-серверов и их форматов представления БД.
BDE (Borland Database Engine) - это, по сути, низкоуровневое Run-time ядро СУБД. Оформлено оно в виде комплекса DLL-библиотек, на основе которых построены настольные СУБД Borland - Paradox, dBase и др., и на основе которых программные продукты Borland связываются с базами данных других СУБД.
База данных содержит файлы - ПОСТАВЩИКИ, ДЕТАЛИ, ДОГОВОРА, ПОСТАВКИ.
Файл ПОСТАВЩИКИ (PSTS) имеет поля - код поставщика (KPST - уникальный ключ), наименование поставщика (IMPST), адрес поставщика (ADRPST).
Файл ДЕТАЛИ (DET) имеет поля - код детали (KDET - уникальный ключ), наименование детали (IMDET), цвет детали (CVET).
Файл ДОГОВОРА (DOG) содержит сведения о том «кто» - «что» - «в каком количестве» обязался поставить, и имеет поля - код поставщика (KPST), код детали (KDET), количество (KOL), дата начала договора (DTN), дата завершения договора (DTK). (KPST, KDET) уникальный (составной) ключ этого файла.
В период действия договора поставщик поставляет детали не обязательно «все за раз», а обычно партиями. Файл ПОСТАВКИ (PST) содержит сведения о партиях поставленных деталей: «кто» - «что» - «в каком количестве» - «когда» поставил, и имеет поля - код поставщика (KPST), код детали (KDET), количество (KOL), дата поставки (DTP). (DBLEC\DBLEC.ER1)
Задача. Сформировать список крупных (в количестве > 1000) поставок детали с кодом 1010: наименование поставщика, размер поставки.
Дополнительный учебный материал по этой теме можно взять: Сетевое окружение > NTSERVER\PROGRAM\SRKDOC\ в каталогах INF(3S)\ и DB(5S)\
Ниже рассматриваются только избранные средства языка SQL в синтаксисе InterBase SQL (имеются небольшие отклонения от стандарта).
Базовые типы данных.
Ключи таблиц.
Межтабличные связи и ключи. Межтабличную связь можно объявить только для пары таблиц (бинарную) и только типа (1:N) (Родительская таблица : Дочерняя таблица).
Связь определяется с помощью пары ключей: родительский ключ (REFERENCES) один из уникальных ключей родительской таблицы (чаще всего, это ее первичный ключ), внешний ключ (FOREIGN KEY) ключ дочерней таблицы (как правило, это неуникальный ключ).
В этой связи строке родительской таблицы соответствуют все строки дочерней таблицы, у которых значение внешнего ключа равно значению родительского ключа строки родительской таблицы.
Одна и та же таблица может быть и родительской и дочерней для нескольких таблиц, но в разных связях.
Еще раз отметим, что родительский ключ уникальный, поэтому получаем связь типа 1:N, т.к. в родительской таблице не более одной строки с заданным значением такого ключа.
Связь объявляется при дочерней таблице
Ограничения целостности базы данных. Ограничения целостности (Integrity Constraint) это условия правильности данных. СУБД не допускает внесения изменений в данные таблиц, при которых нарушаются объявленные требования к правильности данных.
Ограничения целостности можно классифицировать.
Стратегии поддержания ссылочной целостности. Существуют две основные стратегии поддержания ссылочной целостности.
Эти стратегии являются стандартными и присутствуют во всех СУБД, в которых имеется поддержка ссылочной целостности. В некоторых СУБД имеются дополнительные варианты стратегии поддержания ссылочной целостности. В дополнение к системным стратегиям программист может придумать свои уникальные стратегии поддержания ссылочной целостности и реализовать их, используя триггера и транзакции.
Средства описания баз данных (DDL) в SQL.
CREATE TABLE ИмяТаблицы
(Колонка, ... [, ОграничениеТаблицы, ...])
Колонка = ИмяКолонки ТипКолонки
[DEFAULT Константа] [ОграничениеКолонки ...]
ОграничениеКолонки =
NOT NULL | UNIQUE | PRIMARY KEY | CHECK(Условие)
| REFERENCES ИмяРодительскойТаблицы
[(ИмяЕеКолонки)] [СтратегияПоддержки]
ОграничениеТаблицы =
CHECK(Условие)
| UNIQUE (ИмяКолонки, ...)
| PRIMARY KEY (ИмяКолонки, ...)
| FOREIGN KEY (ИмяКолонки, ...)
REFERENCES ИмяРодительскойТаблицы
[(ИмяЕеКолонки, ...)] [СтратегияПоддержки]
СтратегияПоддержки =
ON DELETE CASCADE
| ON UPDATE CASCADE
Оператор CREATE TABLE описывает (и создает пустую) таблицу, ее ограничения целостности и ее связи с родительскими таблицами.
ПРИМЕР.
/* Table: PSTS, ПОСТАВЩИКИ */
CREATE TABLE PSTS
(
KPST INTEGER DEFAULT 0 NOT NULL PRIMARY KEY,
IMPST VARCHAR(20) DEFAULT '',
ADRPST VARCHAR(30) DEFAULT ''
);
/* Table: DET, ДЕТАЛИ */
CREATE TABLE DET
(
KDET INTEGER DEFAULT 0 NOT NULL PRIMARY KEY,
IMDET VARCHAR(20) DEFAULT '',
CVET VARCHAR(10) DEFAULT ''
);
/* Table: DOG, ДОГОВОРА */
CREATE TABLE DOG
(
KPST INTEGER DEFAULT 0 NOT NULL REFERENCES PSTS,
KDET INTEGER DEFAULT 0 NOT NULL REFERENCES DET,
KOL INTEGER,
DTN DATE,
DTK DATE,
PRIMARY KEY (KPST, KDET), CHECK (DTN<DTK)
);
/* Table: PST, ПОСТАВКИ */
CREATE TABLE PST
(
KPST INTEGER DEFAULT 0 NOT NULL,
KDET INTEGER DEFAULT 0 NOT NULL,
KOL INTEGER,
DTP DATE CHECK (DTP>'01.01.2000'),
FOREIGN KEY (KPST, KDET) REFERENCES DOG
);
Средства манипулирования данными (DML) в SQL.
Имеется всего четыре, но очень мощных, оператора: SELECT (отбор), INSERT (вставка), DELETE (удаление), UPDATE (обновление).
SELECT [DISTINCT | ALL] СписокКолонок
FROM ИмяТаблицы [ПсевдонимТаблицы], ...
[WHERE УсловиеОтбора]
[GROUP BY КлючГруппировки]
[HAVING УсловиеОтбораПослеГруппировки]
[ORDER BY КлючУпорядочения]
[UNION [ALL] Select-оператор]
ПсевдонимТаблицы произвольное имя. Если псевдоним не указан, то по умолчанию он совпадает с ИменемТаблицы.
Семантика оператора SELECT. По исходным FROM-таблицам, назовем их Т1,... строится безымянная выходная таблица.
Строится W3 = в W3 формируется точно по одной строке для каждой группы из W2. Способ формирования такой строки по группе определяется СпискомКолонок, детали рассмотрим позже.
Строки полученного результата добавляются к W4, поэтому результат UNION-фразы должен быть таблицей, совместимой с W4. Если UNION-фраза не имеет уточнения ALL, то добавляются только строки, хотя бы чем-то отличающиеся по значению от строк, уже имеющихся в W4.
Выражения в SQL.
Групповые выражения строятся с помощью групповых функций.
Если указано уточнение DISTINCT, то каждое из полученных для строк группы значений ПростогоВыражения участвует в сумме точно один раз без повторений.
Аргумент = * | DISTINCT ПростоеВыражение
имеет значением для Аргумент = * - количество строк в группе, а для другого вида Аргумента количество различных значений ПростогоВыражения по всем строкам группы.
ПРИМЕР. Пусть таблица поставок PST сгруппирована по ключу группировки PST.KDET.
COUNT(DISTINCT PST.KPST) количество разных поставщиков уже поставивших деталь KDET.
COUNT(*) количество партий этой детали уже полученных от всех поставщиков.
SUM(PST.KOL) общее количество в штуках детали KDET уже полученное, суммарно по всем поставщикам.
Из вышеприведенных групповых выражений можно строить более сложные групповые выражения, используя дополнительно константы, имена полей и операции базовых типов данных.
Ниже Выражение простое или групповое выражение.
Набор операций Сравнения для базовых типов данных: = < > и т.п.
SelectOne-оператор должен строить одно колоночную таблицу с одной строкой.
E1 BETWEEN E2 AND E3 в терминах языка Паскаль имеет смысл E1 IN [E2..E3], а NOT отрицание.
E1 IN (E2,...) в терминах языка Паскаль: E1 IN [E2,...].
SelectList-оператор строит одно колоночную таблицу.
E > ALL (SelectList-оператор) имеет смысл: E строго больше всех значений из строк одно колоночной таблицы. SOME ... хотя бы одного значения...
Имеет смысл: результат Select-оператора непустая таблица.
Из вышеприведенных условий можно строить более сложные с помощью операций логики высказываний: AND OR NOT.
Теперь вернемся к синтаксису оператора SELECT.
Если надо включить все колонки FROM-таблиц, то качестве элемента СпискаКолонок можно использовать [ПсевдонимТаблицы.]*
Имена колонок результирующей таблицы:
ПРИМЕРЫ.
SELECT Psts.ImPst, Pst.Kol FROM Pst, Psts
WHERE (Psts.KPst=Pst.KPst) AND
(Pst.KDet=1010) AND (Pst.Kol>1000)
SELECT KDet,COUNT(DISTINCT KPst) AS KolPst
FROM Pst GROUP BY KDet
SELECT MAX(Det.ImDet), Det.KDet, COUNT(*) AS KolP
FROM Det,Pst WHERE Det.KDet=Pst.KDet
GROUP BY Det.KDet ORDER BY 1
Замечание: MAX пришлось использовать по техническим причинам InterBase «не любит неключевые поля там».
SELECT DISTINCT Dog.* FROM Dog,Pst
WHERE (Dog.KPst=Pst.KPst)AND(Dog.KDet=Pst.KDet)
Замечание: Задачу решает декартово произведение с выборкой (естественное соединение), DISTINCT исключает повторы, появляющиеся от декартова произведения.
SELECT Dog.* FROM Dog
WHERE NOT EXISTS (
SELECT Pst.* FROM Pst
WHERE (Dog.KPst=Pst.KPst)AND(Dog.KDet=Pst.KDet))
SELECT Dog.KPst,Dog.KDet, SUM(Pst.Kol)-MAX(Dog.Kol)
FROM Dog,Pst
WHERE (Dog.KPst=Pst.KPst)AND(Dog.KDet=Pst.KDet)
GROUP BY Dog.KPst,Dog.KDet
HAVING SUM(Pst.Kol)>Dog.Kol
Замечание: опять пришлось использовать MAX по техническим причинам.
Delphi - инструментальная среда разработки Object Pascal - программ. Delphi предоставляет программистам-разработчикам:
VCL (Visual Component Library) основной комплекс объектно-ориентированных библиотек Delphi. Предназначенные для работы с базами данных Delphi-средства во многом основаны на представлении данных, принятом в процессоре баз данных BDE(*).
Класс TDatabase. Объект этого типа обеспечивает соединение с (одной) базой данных.
Задает внешний псевдоним, под которым база данных зарегистрирована в администраторе BDE. Использование псевдонимов позволяет обеспечить независимость Delphi-приложения от физического места хранения БД.
Задает внутренний псевдоним, под которым БД будет известна только Delphi-приложению в периоде его выполнения. См. свойство Params.
Развитые СУДБ имеют средства контроля прав доступа к БД (DCL), SQL-сервер InterBase при соединении с БД запрашивает «Имя пользователя» и «Пароль». Свойство Params позволяет «привязать» эту информацию к внутреннему псевдониму БД. Если Delphi-приложение ссылается на БД по внутреннему псевдониму, то запрос прав доступа можно «скрыть».
Если LoginPrompt= TRUE, то SQL-сервер запрашивает (повторное) подтверждение прав доступа.
Это свойство позволяет включить-отключить-проверить соединение с БД.
Класс TTable. Объект этого типа обеспечивает связь и выполнение операций с таблицей. Важнейшие свойства, методы и события этого класса унаследованы им от своего предка - класса TDataSet («абстрактная таблица»).
Указывает (внутренний) псевдоним базы данных.
Указывает имя таблицы в этой базе данных.
Как отмечалось выше - BDE является ядром СУБД, поэтому предоставляет типовой набор средств обработки таблиц в клиентском приложении (т.е. не SQL-сервером, а «на стороне клиента», на рабочей станции).
Эти средства обеспечивают построчный доступ к данным таблицы, и в этом они аналогичны стандартным средствам языка Паскаль.
procedure Open; procedure Close;
Свойство Active позволяет открыть и закрыть таблицу или проверить, открыта ли она. Открыть и закрыть можно также с помощью методов Open и Close.
procedure Next; procedure Prior;
Эти методы позволяют перемещать маркер текущей строки на первую, последнюю, следующую и предшествующую строки.
Eof известная по языку Паскаль функция, Bof аналогичная: принимает значение TRUE, когда маркер текущей строки перемещен в другой конец за пределы таблицы.
property RecordCount: Longint; {количество строк}
procedure Delete; {удалить текущую строку}
function FieldByName(const FieldName:string):TField;
Этот метод по имени поля «FieldName» возвращает значение класса TField, который мы рассмотрим далее.
Отметим важное обстоятельство: в приложении может быть несколько одновременно активных объектов типа TTable, связанных с одной и той же таблицей БД. Возникает впечатление, что «объект работает с собственной копией таблицы», однако это не совсем так. Каждый объект имеет действительно «собственный» маркер текущей строки, который только он может перемещать по строкам таблицы, реальная таблица у таких объектов общая, поэтому операции вставки-удаления-изменения, выполненные одним объектом, «видны» всем другим.
procedure Cancel;
Изменения, проведенные в текущей строке таблицы, фактически хранятся в буфере. Только после подтверждения (Post) строка в таблице реально обновляется (для чего, в случае SQL-серверной базы данных, Post пошлет соответствующий запрос). Cancel позволяет «откатить» изменения в текущей строке (еще до запроса к SQL-серверу). Post (а в некоторых ситуациях, наоборот - Cancel) неявно отрабатывает в каждом действии, «покидающем» измененную текущую строку (потому что «заложен» в реализующей процедуре) (*).
Конкретный объект TTable может «не заметить» изменений в таблице, проведенных «помимо него окольным путем». Метод Refresh позволяет «освежить» его сведения о реальном хранилище данных.
Класс TField. Объекты этого типа обеспечивают работу с полями «абстрактной таблицы» TDataSet. Поля не создаются отдельно, они входят в состав TDataSet (TTable или TQuery)(**). В программе доступ к полям «абстрактной таблицы» можно получить, используя метод FieldByName класса TDataSet.
Свойства класса TField для присваивания-извлечения значения поля и приведения его к подходящему типу:
property Value:Variant; property AsString:string; {и другие As...}
Индексные файлы и их использование.
Программистам хорошо известно, что упорядоченность является мощным инструментом эффективной обработки данных. В условиях многоцелевого использования данных возникает естественная потребность иметь для одной таблицы несколько видов ее упорядоченного представления. Хранить несколько копий таблицы, по-разному упорядоченных, и поддерживать их адекватность не самый лучший вариант решения этой проблемы. Типовой метод использование индексных файлов.
Индексный файл создается для фиксированной пары: таблица данных, ключ упорядочения. Ключ упорядочения обычно задается списком полей таблицы и определяет порядок по неубыванию ключа.
ИндексныйФайл: FILE OF
RECORD НомерСтрокиТаблицыДанных:T1;
ЗначениеКлючаУпорядоченияДляЭтойстроки:T2
END
Индексный файл обеспечивает эффективный доступ к строке таблицы данных по заданному ее ключу (упорядочения):
Реальное представление индексного файла может быть и другим. Сегодня чаще всего используются В-деревья сортировки. Кроме того, ускорение поиска достигается за счет предпочтительной буферизации индексного файла в основной памяти. Индексный файл не обязательно представляется в виде отдельного физического файла.
В современных СУБД индексные файлы широко используются, как для внутренних целей, так и в качестве инструмента, предоставляемого программистам напрямую.
SQL-ориентированные СУБД, в частности InterBase:
CREATE [UNIQUE] [ASC | DESC] INDEX ИмяИндексФайла
ON ИмяТаблицыДанных (ИмяКолонки,...)
Использование индексных файлов в Delphi. Свойства и методы объекта типа TTable позволяют:
Устанавливает логический порядок, соответствующий указанному имени индексного файла.
Устанавливает логический порядок по умолчанию, действующий только при пустом IndexName. Если DefaultIndex=TRUE и таблица имеет первичный ключ, то он и определяет логический порядок, иначе используется физический порядок.
Отметим, что ранее рассмотренные First, Next, Eof... выполняются в соответствии с текущим установленным логическим порядком.
function FindKey
(const KeyValues: array of const): Boolean;
FindKey выполняет поиск строки по ее ключу, заданное значение ключа (значение KeyValues) должно соответствовать текущему логическому порядку. Если строка была найдена, то она становится текущей и FindKey возвращает TRUE.
В операционной связи участвуют две таблицы Ведущая (Master) и Ведомая (Detal), любое перемещение маркера текущей строки в ведущей таблице вызывает перемещение в ведомой на соответствующую строку. Операционная связь определяется (и реализуется) с помощью двух ключей:
Для установления связей с объектами источниками данных в Delphi используются объекты специального класса TDataSource. Мы рассмотрим только одно свойство объектов этого класса property DataSet: TDataSet. Оно позволяет указать на объект типа TTable источник данных.
Операционная связь устанавливается в объекте типа TTable, управляющем Detal-таблицей:
Этому свойству надо присвоить значение - список полей Detal-ключа, неявно при этом устанавливается соответствующий логический порядок (индексный файл с соответствующим ключом должен существовать, обычно это индекс первичного ключа).
Эта ссылка на объект типа TDataSource, у которого свойство DataSet ссылается на объект типа TDataSet, приводит к Master-таблице.
Этому свойству надо присвоить значение - список полей Master-ключа.
ПРИМЕР. Решение задачи «о крупных поставках».
DBLEC\PRG01\Project1.dpr DBLEC\Prg01C++\Project1.bpr
СХЕМА СВЯЗЕЙ ОБЪЕКТОВ
type
TForm1 = class(TForm)
Database1: TDatabase;
PstsTable: TTable; {Объект доступа к таблице Psts}
DetTable: TTable; {... Det}
DogTable: TTable; {... Dog}
PstTable: TTable; {... Pst}
NewTable: TTable; {... New рабочая таблица для хранения
результата решения задачи}
DataSource1: TDataSource; {Объект, обеспечивающий связь
PstTable(Master) <- PstsTable(Detal)}
procedure N2Click(Sender: TObject);
procedure N3Click(Sender: TObject);
procedure N4Click(Sender: TObject);
end;
var Form1: TForm1;
procedure TForm1.N2Click(Sender: TObject);
{Решение 1. Используются средства работы с таблицами
на уровне записей ~ традиционные средства
программирования.}
begin
NewTable.Close;
NewTable.EmptyTable;
NewTable.Open;
PstsTable.Open;
PstTable.Open;
PstTable.First;
WHILE NOT PstTable.EOF DO
begin
IF (PstTable.FieldByName('KDet').Value=1010) AND
(PstTable.FieldByName('Kol').Value>1000) THEN
begin
PstsTable.First;
WHILE NOT PstsTable.EOF AND
(PstsTable.FieldByName('KPst').Value<>
PstTable.FieldByName('KPst').Value)
DO PstsTable.Next;
NewTable.Append;
NewTable.FieldByName('ImPst').Value:=
PstsTable.FieldByName('ImPst').Value;
NewTable.FieldByName('Kol').Value:=
PstTable.FieldByName('Kol').Value;
NewTable.Post;
end;
PstTable.Next;
end;
NewTable.Close;
NewTable.Open;
{Unit2.Form2.QuickRep1.DataSet:=Form1.NewTable;}
Unit2.Form2.QuickRep1.Preview
end;
procedure TForm1.N3Click(Sender: TObject);
{Решение 2. Используется FindKey - поиск по индексу}
begin
NewTable.Close;
NewTable.EmptyTable;
NewTable.Open;
PstsTable.Open;
PstTable.Open;
PstTable.First;
WHILE NOT PstTable.EOF DO
begin
IF (PstTable.FieldByName('KDet').Value=1010) AND
(PstTable.FieldByName('Kol').Value>1000) THEN
begin
{bb:=}PstsTable.FindKey
([PstTable.FieldByName('KPst').Value]);
{Да!!!??? В ObjectPascal2 это действительно
так... функцию можно вызвать как процедуру,
по крайней мере иногда.}
NewTable.Append;
NewTable.FieldByName('ImPst').Value:=
PstsTable.FieldByName('ImPst').Value;
NewTable.FieldByName('Kol').Value:=
PstTable.FieldByName('Kol').Value;
NewTable.Post;
end;
PstTable.Next;
end;
NewTable.Close;
NewTable.Open;
Unit2.Form2.QuickRep1.Preview
end;
procedure TForm1.N4Click(Sender: TObject);
{Решение 3. Используется реляционная связь Master-Detal}
begin
NewTable.Close;
NewTable.EmptyTable;
NewTable.Open;
PstsTable.Close;
DataSource1.DataSet:=PstTable;
PstsTable.MasterSource:=DataSource1;
PstsTable.MasterFields:='KPst';
PstsTable.Open;
PstTable.Open;
PstTable.First;
WHILE NOT PstTable.EOF DO
begin
IF (PstTable.FieldByName('KDet').Value=1010) AND
(PstTable.FieldByName('Kol').Value>1000) THEN
begin
NewTable.Append;
NewTable.FieldByName('ImPst').Value:=
PstsTable.FieldByName('ImPst').Value;
NewTable.FieldByName('Kol').Value:=
PstTable.FieldByName('Kol').Value;
NewTable.Post;
end;
PstTable.Next;
end;
NewTable.Close;
PstsTable.Close;
PstsTable.MasterSource:=NIL;
PstsTable.MasterFields:='';
DataSource1.DataSet:=NIL;
PstsTable.Open;
NewTable.Open;
Unit2.Form2.QuickRep1.Preview
end;
Средства обработки БД в СУБД FoxPro. DBL(FOX).doc
= {0,1,2...} натуральный ряд. - множество всех векторов длины k с элементами из N. Отношение R, R: FILE OF RECORD x1,x2,... xk: Natural END
В теории рассматриваются в том числе и бесконечные отношения-файлы. Дело в том что задачи «Вычислить y=f(x)» и «Перечислить отношение {(x,y)/y=f(x)}» сводимы друг к другу (по крайней мере для xN).
Алгоритмический подход.
Перечислимое отношение - имеется программа, формирующая соответствующий файл:
R перечислимо относительно R1,...Rк имеется аналогичная программа, но с входными файлами R1,...Rк и на языке, расширенном логическими выражениями вида rR1,... rRk. Отметим, что в случае бесконечных R1,...Rк наличие возможности «запросто» получить ответ на вопрос вида «IF rR1 THEN ... ELSE ...» не просто облегчает задачу перечисления, а открывает возможность перечислять неперечислимое без такого использования R1,...Rк.
Алгебраический подход.
Общая схема:
Один из вариантов такой алгебраической системы:
Пусть R, I1,...Ik {1,2,...n}{#d/ dN}.
{n:I1,...Ik}(R) = {(A1,...An) / (B1,...Bk)R, где Bj = IF Ij{1,2,...n} THEN
ELSE d (где Ij=#d)}
Примеры важных (для последующего материала) операций. Пусть k=8.
{7:#d,1,...7}(R)=
{(A1,...A7)/(d,A1,...A7)R}
{7:1,1,...7}(R)=
{(A1,...A7)/(A1,A1,A2,...A7)R}
{8:2,1,3,...8}(R)=
{(A1,A2,A3,...A8)/(A2,A1,A3,...A8)R}
{9:1,...8}(R)=
{(A1,...A8,A9)/(A1,...A8)R, A9N}
{xi y}(R)= {(d1,...,di,...dk) /
для каждого dN такого, что (d di), имеет место (d1,...,d,...dk)R}
{xi y}(R)= {(d1,...,di,...dk) /
имеется dN такое, что (d di) и (d1,...,d,...dk)R}
Конструктивно определимое отношение - имеется (константное) выражение, построенное из базовых отношений (Sum, Mult) с помощью набора вышеприведенных операций такое, что это отношение является значением этого выражения.
{xi}(R)= {(d1,...,,...dk) /
имеется dN такое, что
(d1,...,,...dk)R}
Перечислимое отношение можно получить проекциями из подходящего конструктивно определимого отношения.
Логический подход.
...
Ниже используются обозначения:
Базовый набор файлов: файлы, содержащие одну запись; базовые файлы определяются с помощью операции - (имя_поля: значение_поля, ...)
Базовый набор операций над файлами.
ПРИМЕР.(A:1,B:2)*(B:2,C:3)=(A:1,B:2,C:3);
(A:1,B:2)*(C:3,D:4)=(A:1,B:2,C:3,D:4) - в случае файлов без одноименных полей, операция применима к каждой паре записей;
(A:1,B:2)*(B:3,D:4) - к такой паре записей операция не применима.
ПРИМЕР. Пусть R - файл с полями (A,B), S - файл с полем (A), T=(RS) - будет файлом с полем (B):
ПРИМЕР. Решение вышерассмотренной задачи «о крупных поставках» описывается реляционным выражением:
[ImPst,Kol](Psts*([(KDet=1010)&(Kol>1000)]Pst))
Базовые (элементарные) формулы:
константа сравнения константа
имеет смысл «поле A записи r (или константа) имеет значение больше (меньше, равно...), чем поле B записи s (или константа)».
Формулы общего вида - строятся из базовых с помощью операций:
Смысл формул без кванторов известен по языку Паскаль - это логические выражения с операциями AND(),OR() и NOT().
Смысл кванторных формул - для фиксированных значений других (кроме r) переменных:
ПРИМЕЧАНИЕ. С некоторыми оговорками (уточнениями, в которых используется операция естественного соединения - декартова произведения) имеют место следующие соответствия:
Запрос НАЙТИ{(r.A,...s.B,...)/rR,sS...}F имеет смысл:
ПРИМЕР. Вышеприведенный рисунок, иллюстрирующий операцию деления T=(RS), соответствует запросу T=НАЙТИ{t.B/tR} sS rR ((r.B=t.B)(r.A=s.A))
ПРИМЕР. Решение вышерассмотренной задачи «о крупных поставках» описывается запросом реляционного исчисления кортежей:
НАЙТИ{(r.ImPst,s.Kol)/rPsts,sPst}
(r.KPst=s.KPst)(s.KDet=1010)(s.Kol>1000)
ПРИМЕР. Найти имена поставщиков, которые поставляют все красные детали.
Переформулируем постановку задачи, явно оговорив неявное и явно выделив кванторы: найти имена таких поставщиков, что для каждой детали, если она красная, то существует договор о поставке этой детали этим поставщиком. Устранив импликацию (AB)(AB), получим: найти имена таких поставщиков, что для каждой детали - либо она не красная, либо существует договор о поставке этой детали этим поставщиком.
Запрос реляционного исчисления кортежей.
НАЙТИ{(r.ImPst)/rPsts} detDet ((det.Cvet#'КРАСНЫЙ')
dogDog ((dog.KDet=det.KDet)(dog.KPst=r.KPst)))
Реализация этого запроса на SQL потребует устранения -квантора с помощью эквивалентностей x A(x) x A(x) и (AB) AB. В итоге получим формулировку, не удовлетворяющую требованиям языка реляционного исчисления кортежей, но семантически эквивалентную и подходящую для реализации на SQL:
НАЙТИ{(r.ImPst)/rPsts} detDet ((det.Cvet='КРАСНЫЙ')
dogDog ((dog.KDet=det.KDet)(dog.KPst=r.KPst)))
SELECT Psts.ImPst FROM Psts
WHERE NOT EXISTS (SELECT * FROM Det
WHERE (Det.Cvet='Красный') AND
NOT EXISTS (SELECT * FROM Dog
WHERE (Dog.KDet=Det.KDet) AND
(Dog.KPst=Psts.KPst)))
Схема (лобовой) реализации этого запроса традиционными средствами уровня языка Паскаль.
Структуру запроса можно представить диаграммой:
Учитывая, что семантически
b:=false; RESET(File);
WHILE NOT b AND NOT EOF(File) DO
BEGIN READ(File,x); b:=B(x) END
b:=true; RESET(File);
WHILE b AND NOT EOF(File) DO
BEGIN READ(File,x); b:=B(x) END
В итоге получаем программу: DBLEC\PRG01\Project1.dpr
NewTable.Close; NewTable.EmptyTable; NewTable.Open;
DetTable.Open; DogTable.Open; PstsTable.Open;
PstsTable.First;
WHILE NOT PstsTable.EOF DO BEGIN
{aDet:= detDet Условие(r,det)}
aDet:=true; DetTable.First;
WHILE aDet AND NOT DetTable.EOF DO BEGIN
aDet:=(DetTable.FieldByName('Cvet').
AsString<>Красная);
IF NOT aDet THEN BEGIN
{aDet:=eDog:= dogDog Условие(r,det,dog)}
eDog:=false; DogTable.First;
WHILE NOT eDog AND NOT DogTable.EOF DO BEGIN
eDog:=(DogTable.FieldByName('KDet').Value=
DetTable.FieldByName('KDet').Value)AND
(DogTable.FieldByName('KPst').Value=
PstsTable.FieldByName('KPst').Value);
DogTable.Next
END;
aDet:=eDog
END;
DetTable.Next
END;
IF aDet THEN BEGIN
NewTable.Append;
NewTable.FieldByName('ImPst').Value:=
PstsTable.FieldByName('ImPst').Value; NewTable.Post;
END;
PstsTable.Next;
END; NewTable.Close;
Поскольку (KPst,KDet) является первичным ключом для таблицы Dog (а значит имеется соответствующий индекс), то выделенный жирным курсивом фрагмент можно заменить на:
aDet:=(DetTable.FieldByName('Cvet').
AsString<>Красная) OR
DogTable.FindKey([PstsTable.FieldByName('KPst').Value,
DetTable.FieldByName('KDet').Value]);
Выражение реляционной алгебры.
[ImPst](Psts*(([KPst,KDet]Dog)
([KDet]([Cvet='КРАСНЫЙ']Det))))
Схема (в лоб) соответствующей программы:
Воспользуемся представлениями (View), чтобы связать имя W1 с рабочим файлом промежуточных вычислений. (*)
CREATE VIEW W1 AS
SELECT KDet FROM Det WHERE Cvet='КРАСНЫЙ'
CREATE VIEW W2 AS SELECT KPst,KDet FROM Dog
Деление реализуется довольно громоздко, т.к. оно имеет -определение:
W3=(W2W1) = НАЙТИ{(r.KPst)/rW2}
sW1 tW2 ((t.KDet=s.KDet)(t.KPst=r.KPst))
Согласно этому определению его можно реализовать, как было описано выше.
Внимание. В этом запросе W2 используется два раза НАЙТИW2 и W2.
В SQL эта проблема решается с помощью псевдонима:
CREATE VIEW W3 AS
SELECT W2.KPst FROM W2
WHERE NOT EXISTS (SELECT * FROM W1
WHERE NOT EXISTS (SELECT * FROM W2 psevdonimW2
WHERE (psevdonimW2.KDet=W1.KDet) AND
(psevdonimW2.KPst=W2.KPst)))
В ObjectPascal эта проблема решается с помощью двух объектов типа TTable, управляющих доступом к таблице W2. Например, W2aTable для работы во внешнем цикле, и W2bTable для работы во внутреннем цикле.
SELECT Psts.ImPst FROM Psts,W3 WHERE Psts.KPst=W3.KPst
Однако ж окончательный ответ можно было получить уже на предыдущем шаге, т.к.
[ImPst](Psts*W3) = НАЙТИ{(r.ImPst)/rPsts}
sW1 tW2 ((t.KDet=s.KDet)(t.KPst=r.KPst))
Решение задачи «о поставщиках красных деталей» в СУБД FoxPro см. DBL(FOX).doc
Жизненный цикл программного обеспечения (ЖЦ ПО) (*) - это непрерывный процесс, который начинается с момента принятия решения о необходимости его создания и заканчивается в момент его полного изъятия из эксплуатации. Принято выделять три основных процесса в ЖЦ ПО - разработка, эксплуатация, сопровождение.
Разработка включает в себя работы по созданию ПО в соответствии с заданными требованиями. Обычно выделяют следующие фазы процесса разработки определение и анализ требований, проектирование и реализация (программирование).
Эксплуатация включает в себя работы, обеспечивающие функционирование ПО в интересах пользователей, - в том числе конфигурирование операционной среды, базы данных и рабочих мест пользователей, локализацию проблем и устранение причин их возникновения.
Сопровождение включает в себя модификацию ПО, поддержку его текущего состояния и функциональной пригодности в соответствии с изменяющимися условиями эксплуатации.
ЖЦ ПО носит итерационный характер: результаты очередного этапа часто вызывают изменения в проектных решениях, выработанных на более ранних этапах. К настоящему времени широкое признание получили варианты спиральной модели ЖЦ.
Спиральная модель ЖЦ.
Спиральная модель ЖЦ делает упор на начальные этапы: анализ и проектирование. На этих этапах реализуемость технических решений проверяется путем создания прототипов. Каждый виток спирали соответствует созданию фрагмента или версии ПО, на нем уточняются цели и характеристики проекта, определяется его качество и планируются работы следующего витка спирали. Таким образом углубляются и последовательно конкретизируются детали проекта и в результате выбирается обоснованный вариант, который доводится до реализации.
Разработка итерациями отражает объективно существующий спиральный цикл создания системы. Неполное завершение работ на каждом этапе позволяет переходить на следующий этап, не дожидаясь полного завершения работы на текущем. При итеративном способе разработки недостающую работу можно будет выполнить на следующей итерации. Главная же задача - как можно быстрее показать пользователям системы работоспособный продукт, тем самым активизируя процесс уточнения и дополнения требований.
Фаза определения и анализа требований (Analysis/Software Requirements). Определение требований выполняется при совместном участии пользователей и специалистов-разработчиков. Результаты этой фазы: список и приоритетность функций будущей ИС, предварительные функциональная и информационная модели ИС (модели процессов и данных предметной области).
Фаза проектирования (Design). Результаты этой фазы:
общая информационная модель системы (даталогическая модель, модель данных предметной области);
функциональные модели системы в целом и подсистем (модели процессов предметной области);
точно определенные интерфейсы между автономно разрабатываемыми подсистемами;
построенные прототипы экранов, отчетов, диалогов (представленные в виде форм документов, слайдов и программ-прототипов).
Фактически проектирование начинается уже в фазе анализа требований и продолжается в фазе реализации. Принято различать уровни (этапы, стадии) проектирования и соответствующих моделей.
Фаза реализации (Development), по другой терминологии фаза конструирования, программирования или собственно разработки. Результатом этой фазы является законченная версия программного продукта, готовая к внешнему тестированию. Иногда в эту фазу включают этап внешнего тестирования и внедрения программного продукта, иногда эти работы выделяют в отдельную фазу ЖЦ ПО.
Одним из возможных подходов к разработке ПО в рамках спиральной модели ЖЦ является получившая в последнее время широкое распространение методология быстрой разработки приложений RAD (Rapid Application Development). Под этим термином обычно понимается процесс разработки ПО, содержащий 3 элемента:
небольшую команду программистов (от 2 до 10 человек);
короткий, но тщательно проработанный производственный график разработки версии программного продукта (от 2 до 6 мес.);
повторяющийся цикл, при котором разработчики, по мере того, как приложение начинает обретать форму, и его версии передаются на эксплуатацию, запрашивают и реализуют в продукте требования, полученные через взаимодействие с заказчиком.
Следует отметить, что методология RAD, как и любая другая, не может претендовать на универсальность, она хороша в первую очередь для относительно небольших проектов, разрабатываемых для конкретного заказчика. В частности, не подходят для разработки по методологии RAD приложения, от которых зависит безопасность людей (например, управление самолетом или атомной электростанцией), так как итеративный подход предполагает, что первые версии наверняка не будут полностью работоспособны, что в данном случае исключается.
В таком процессе разработки особую роль играют CASE-средства проектирования и реализации программных систем (Computer Aided Software Engineering). Эти средства не просто облегчают разработку моделей, документирование процесса в целом и подготовку документации по программному обеспечению. CASE-средства используются для быстрого получения работающих прототипов приложений. Пользователи, непосредственно взаимодействуя с ними, уточняют и дополняют требования к системе, которые не были выявлены ранее. Каждый прототип развивается в часть будущей системы. Таким образом, на следующую фазу передается более полная и полезная информация. Применение единой среды хранения информации о проекте позволяет сохранять информацию о проекте при переходах с этапа на этап и от версии к версии.
Языки потоковых диаграмм, которые мы рассмотрим в этом разделе курса, акцентируют внимание на действиях-процессах, но с точки зрения приема-передачи-хранения-преобразования информации, т.е. откуда (или от кого) действия принимают информацию, куда (или кому) ее передают и как (посредством чего и кого) они преобразуют информацию. Иначе говоря, эти языки информационного моделирования процессов акцентируют внимание на информационных связях между дейстиями-процессами, а не на связях по управлению (порядком выполнения).
В таких языках используются различные виды графовых (сетевых) представлений.
Конкретные языки информационного моделирования, естественно, содержат и другие средства - в частности, внешние объекты - конечные пользователи и другие объекты, обменивающиеся данными с информационной системой; средства декомпозиции сложных данных и процессов...
ПОТОКОВЫЕ ОПЕРАЦИОННЫЕ ДИАГРАММЫ С ХРАНИЛИЩАМИ (DFD - Data Flow Diagramming).
Базовые элементы языка.
Действие (процесс)
Внешний объект
Группируя более простые действия и данные в более сложные, мы получаем возможность отвлечься (абстрагироваться) от внутренних деталей и сконцентрировать внимание на взаимосвязях между этими сложными действиями и данными. А при необходимости, мы можем сконцентрировать внимание на одном сложном действии или данном, рассмотрев его детализацию (конкретизацию), и отвлечься от внешней для него среды.
Группировка (композиция) и разгруппировка (декомпозиция) действий (процессов) представляется многоуровневыми потоковыми диаграммами, сложное действие представляется (прямоугольником) как единое целое в одной диаграмме и как набор взаимосвязанных действий в детализирующей диаграмме.
Группировка (композиция) и разгруппировка (декомпозиция) потоков представляется как их слияние и разветвление соответственно.
ЗАДАЧА о хозяине, его собаке и его друге.
PROGRAM Pp; VAR S0,Sk,Vh,Vd,Vs:REAL;
S,t:REAL; k:INTEGER; C:CHAR;
BEGIN READ(S0,Sk,Vh,Vd,Vs); S:=S0; C:='Х'; k:=0;
WHILE S>=Sk DO
BEGIN IF C='Х' THEN BEGIN C:='Д'; t:=S/(Vs+Vd) END
ELSE BEGIN C:='Х'; t:=S/(Vs+Vh) END;
S:=S-t*(Vh+Vd); k:=k+1 END;
WRITE(k) END.
ПРИМЕР Потоковой операционной диаграммы с хранилищами для задачи о бегающей собаке.
Типы потоков и действий. Реальные действия (процессы) и связывающие их потоки могут иметь специфические особенности, которые желательно отобразить в информационной модели. Для этих целей в языках потоковых диаграмм обычно имеются дополнительные средства.
Потоки можно классифицировать на:
В языке могут быть специальные элементы, которые используются в точках разветвления и слияния потоков, и позволяют фиксировать различия в семантике различных видов разветвления и слияния.
Аналогично можно классифицировать (и соответственно по-разному обозначать) действия (процессы):
Пример [9] модели деятельности условного предприятия «ТОРГОВАЯ СИСТЕМА». TGS.doc (DBLEC\TGS.BP1)
Заказчиком на разработку программной системы является некая организация, занимающаяся оптовой торговлей сельхозпродуктами. В представленной концептуальной модели еще не проведена «граница автоматизации» из общего набора бизнес-процессов не выделены процессы, выполняемые непосредственно программной системой или с помощью нее.
ВЕРБАЛЬНОЕ ОПИСАНИЕ. «ТОРГОВАЯ СИСТЕМА» предназначена для обслуживания клиентов оптового рынка.
См. также о языке SADT/IDEF0-диаграмм DB2LSADT.doc
Рассмотрим одно из хранилищ данных ранее рассмотренного примера «ТОРГОВАЯ СИСТЕМА».
ХРАНИЛИЩЕ ДАННЫХ «Накладные о приеме товаров».
Содержательной единицей хранения является некий документ о партии товара, поставленного неким поставщиком, и сбыте этого товара нашей торговой организацией. В процессе сбыта этот документ пополняется, а по окончании информация этого документа предоставляется поставщику в виде отчета «Об итогах завершающего анализа» по этой партии товаров.
ПОСТАВЩИК: Джон Харрис ЛТД АДРЕС: НКГР Лондон СВ8 |
ПОЛУЧАТЕЛЬ: |
||||
ДАТА ПРИЕМА: 14 июля 1980 |
N НАКЛАДНОЙ: 978 |
ДАТА ПРОДАЖИ: 25 июля 1980 |
НОМЕР СЧЕТА: 195 015 |
||
N КОНТЕЙНЕРА: аааааааааа |
N АВТОМАШИНЫ: ббббббббббб |
СПОСОБ ХРАНЕНИЯ: вввввввв |
|||
ПОЛУЧЕНО |
ПРОДАНО |
||||
МАРКИРОВКА |
К-ВО |
ВЕС |
К-ВО |
ЦЕНА |
СТОИМОСТЬ |
НАИМЕНОВАНИЕ ТОВАРА: Персики «Красный Дикси» А |
|||||
XXX |
50 |
40 |
1.00 |
40.00 |
|
10 |
1.05 |
10.50 |
|||
НАИМЕНОВАНИЕ ТОВАРА: Персики «Красный Дикси» Б |
|||||
YYY |
481 |
100 |
0.75 |
75.00 |
|
150 |
0.77 |
115.50 |
|||
200 |
0.80 |
160.00 |
|||
31 |
0.85 |
25.35 |
|||
ИТОГО: |
427.35 |
||||
СБОРЫ |
ВСЕГО СБОРЫ: |
200.19 |
|||
ЗА ХРАНЕНИЕ |
КОМИССИОННЫЕ |
ПРОЧИЕ |
|||
8.55 |
42.74 |
148.90 |
|||
ЧИСТЫМИ: |
227.16 |
СТРУКТУРА ХРАНИЛИЩА ДАННЫХ «Накладные о приеме товаров».
За основу возьмем структуру вышеприведенного документа.
В итоге мы имеем глубоко структурированное представление хранилища данных.
ПЕРВАЯ НОРМАЛЬНАЯ ФОРМА. В реляционной модели баз данных рассматриваются только файлы в (первой) нормальной форме - «плоские файлы», точнее таблицы-отношения. Поля таких файлов должны иметь базовый неструктурный тип.
Устранение повторяющихся (внутренних) группировок (приведение к нормальной форме) проводится (многократной) декомпозицией исходного файла на два, связанных по уникальному ключу исходного файла.
При устранении повторяющихся группировок потребуются дополнительные поля («N строки накладной») для ключей межтабличных связей. Для надежной идентификации поставщиков, товаров и удержаний введем соответствующие коды. Вычислимые поля («итого», «всего сборы», «чистыми», «стоимость») исключим. Первичные ключи таблиц подчеркнуты.
В итоге мы получили нормализованную базу данных многотабличную с межтабличными связями.
Такую БД всегда можно свести к нормализованной однотабличной (универсальная таблица-отношение) - соединением по ключу межтабличной связи, даже если эта связь типа «многие ко многим»:
SELECT КлючА, АтрибутыА, АтрибутыВ
FROM ТаблицаА, ТаблицаВ WHERE КлючА = КлючВ
Взаимосвязи между данными отражают семантику базы данных, унаследованную от предметной области. Поэтому в проектировании БД особое внимание уделяется выбору способа представления зависимостей между данными. Известно, что неудачный выбор может создавать впоследствии трудности при обновлении данных - аномалии.
Аномалии обновления данных. Рассмотрим эти трудности на примере таблицы «Партии товара».
Поставщики в БД идентифицируются кодом, но при добавлении накладной надо ввести и его реквизиты наименование, адрес. Кроме того, придется провести проверку. Если в других накладных этого поставщика указаны другие значения этих реквизитов, то впоследствии могут быть недоразумения. Например, в списке различных наименований окажется больше организаций, чем в списке различных (по коду) поставщиков(*).
В нашей БД можно хранить информацию о таком поставщике, только добавив частично заполненную накладную о фиктивной (пустой) сделке с этим поставщиком. Такие фиктивные сделки тоже впоследствии либо будут вызывать недоразумения в учете сделок, либо будут создавать дополнительные трудности в обработке (их придется «обходить»).
Причины аномалий исследуются в теории и методологии проектирования БД. Получены результаты об устранении некоторых видов аномалий приведением базы данных к более сильным нормальным формам, чем первая.
ВТОРАЯ НОРМАЛЬНАЯ ФОРМА. Значения неключевых полей должны зависеть от всего ключа в целом, а не от его части.
Уникальным ключом новой таблицы УДЕРЖАНИЯ является пара (N накладной, Код удержания), но поле «Наименование удержания» зависит от части ключа - поля «Код удержания». Можно привести примеры аномалий, используя «код и наименование удержания», аналогично «коду и наименованию поставщика» в вышеприведенных примерах.
Разложим эту таблицу на две.
ТРЕТЬЯ НОРМАЛЬНАЯ ФОРМА. В таблице «ПАРТИИ ТОВАРА» поля «Наименование и адрес поставщика» зависят от поля «Код поставщика», а «Код поставщика» в свою очередь зависит от ключа «N накладной». С другой стороны, поля «Наименование и адрес поставщика» однозначно определяются напрямую по ключу «N накладной». Такая ситуация называется транзитивной зависимостью. В третьей нормальной форме не должно быть транзитивных зависимостей. Отметим, что аналогичная ситуация в таблице «СТРОКИ НАКЛАДНЫХ» для полей «Код товара» и «Наименование товара».
Разложим каждую из этих таблиц на две.
Отметим, что ранее рассмотренные для таблицы «ПАРТИИ ТОВАРОВ» примеры аномалий уже не проявляются в новой БД.
(Упрощенная) ER-диаграмма новой базы данных «Накладные о приеме товаров».
ER/IDEF1X-диаграмма БД «Накладные о приеме товаров».
(DBLEC\TGS.ER1)
Введение в основы теории функциональных зависимостей.
Пусть R реляционное (конечное) отношение с атрибутами A = (X1,...Y1,...Z1,...). X,Y A.
R удовлетворяет функциональной зависимости XY :
проекция [X,Y](R) является функциональным отношением типа XY, т.е. не содержит пары строк с одинаковыми значениями атрибутов X («аргумент функции»), но разными значениями атрибутов Y («значение функции»). Будем использовать также терминологию: f-зависимость, Y функционально (однозначно) зависит от X, X функционально (однозначно) определяет Y, X посылка (детерминант) f-зависимости, Y заключение.
Пусть F множество f-зависимостей.
F = XY (F влечет f-зависимость XY): для любого R, если R удовлетворяет каждой f-зависимости из F, то R удовлетворяет f-зависимости XY. F - (соответствующее) замыкание F, т.е. множество всех f-зависимостей XY, таких что F влечет f-зависимость XY.
Аксиомы Армстронга (точнее, исчисление выводимости для f-зависимостей).
F1. Рефлексивность (аксиома): XX
F2. Пополнение (правило вывода): XY
XZY
F6. Псевдотранзитивность (правило вывода): XY YZW
XZW
Производные правила вывода (их обоснование можно получить из предыдущих):
F3. Аддитивность: XY XZ
XYZ
F4. Проективность: XYZ
XY
F5. Транзитивность (~ F6 при пустом Z): XY YW
XW
F - XY (из F выводима f-зависимость XY): имеется вывод XY из набора зависимостей F (как аксиом) и аксиом рефлексивности по правилам вывода Армстронга.
Теорема о полноте. F = XY F - XY
Таким образом, F - транзитивное замыкание F, построенные по отношению «влечет» и по отношению «выводимости», совпадают.
NB. Доказуемость в исчислении выводимости для f-зависимостей равносильна доказуемости в - фрагменте интуиционистской (конструктивной) логики высказываний.
Задача проверки (XYF) имеет вычислительную сложность по времени O(n), где n длина кода, представляющего (XY;F).
Как уже отмечалось выше, взаимосвязи между данными отражают семантику базы данных, унаследованную от предметной области. Фактически для проектировщика и администратора БД основной интерес представляют не конкретные взаимосвязи между конкретными данными конкретного текущего состояния БД, а именно зависимости между атрибутами, причем те, которые должны сохраняться, по крайней мере в периоде между реструктуризациями БД (изменениями в метаданных).
Поэтому точнее, семантику БД фиксирует именно F, множество зависимостей, которое определяется не по конкретному текущему наполнению конкретной БД, а (априорно) определяется проектировщиком БД, исходя из смысла предметной области («что, будем считать, должно сохранятся в процессе преобразований БД»).
Однако базовые зависимости F влекут свои последствия, из чего проистекает практический интерес к F и далее к понятиям «выводимость и сложность вывода».
Может возникнуть недоумение база данных состоит из нескольких взаимосвязанных таблиц, а все вышеприведенные определения даны применительно к одному отношению R. Поэтому напомним, что выше было оговорено, что многотабличная реляционная БД теоретически сводима к однотабличной, а практически... приведенные определения чисто технически обобщаются и на многотабличные БД.
X возможный ключ отношения R: X является уникальным ключом (но возможно не выделенным в качестве первичного ключа). Неключевой атрибут атрибут, не входящий в состав ни одного из возможных ключей.
R находится во второй нормальной форме: R находится в первой нормальной форме, и нет неключевых атрибутов, зависящих от части какого-либо (составного) возможного ключа.
Пусть (X,Y) возможный ключ отношения R, но поля B1,... зависят от X (части возможного ключа), т.е. XB1,... Тогда R = [X,B1,...](R) * [X,Y,C1,...](R), где C1,... остальные атрибуты отношения R. Это разложение отношения R на два отношения [X,B1,...](R) и [X,Y,C1,...](R) устраняет (внутритабличную) зависимость XB1,... от части ключа. Причем естественное соединение этих двух отношений точно совпадает с исходным отношением. Такое разложение называется декомпозицией без потерь.
ПРИМЕР.
B |
X |
Y |
C |
N группы |
N зачетки |
Наименование экзамена |
Оценка |
... |
... |
... |
... |
Для этой таблицы нетрудно привести (аналогичные ранее приведенным) примеры аномалий. Рекомендованная декомпозиция (без потерь) дает две таблицы:
B |
X |
X |
Y |
C |
|
N группы |
N зачетки |
N зачетки |
Наименование экзамена |
Оценка |
|
... |
... |
... |
... |
... |
Z транзитивно зависит от X (в отношении R): имеется такой Y, что XY и YZ, где XYZ и не верно: YX.
R находится в третьей нормальной форме: R находится во второй нормальной форме, и нет неключевых атрибутов, транзитивно зависящих от какого-либо возможного ключа.
Пусть X возможный ключ отношения R, XY и YZ (т.е. Z транзитивно зависит от X), W остальные атрибуты отношения R. Тогда R = [Y,Z](R) * [X,Y,W](R). Это разложение отношения R на два отношения [Y,Z](R) и [X,Y,W](R) устраняет (внутритабличную) транзитивную зависимость XZ. Причем декомпозицией без потерь.
ПРИМЕР.
W |
X |
Y |
Z |
Сумма оценок по всем экзаменам |
N зачетки |
Группа |
Количество экзаменов в текущей сессии |
... |
... |
... |
... |
Для этой таблицы нетрудно привести (аналогичные ранее приведенным) примеры аномалий. Рекомендованная декомпозиция (без потерь) дает две таблицы:
W |
X |
Y |
Y |
Z |
|
Сумма оценок по всем экзаменам |
N зачетки |
Группа |
Группа |
Количество экзаменов в текущей сессии |
|
... |
... |
... |
... |
... |
Функциональные зависимости и проектирование базы данных.
Определение f-зависимостей дано для одной таблицы, но зависимости имеются и межтабличные.
В явном виде F может и не содержать «плохих» зависимостей. Но аномалии могут быть, если «плохие» зависимости выводимы из F.
Вернемся к примеру устранения транзитивной зависимости. Пусть T исходная таблица, а T1,T2 полученные в результате декомпозиции.
Однако для решения этих проблем имеются типовые схемы и средства: операция «естественное соединение», средства определения межтабличных связей и соответствующего контроля ссылочной целостности.
В целом, принято считать хорошим правилом проектирования базы данных:
На сегодняшний день имеются CASE-средства, которые по заданному описанию БД и базовому набору зависимостей автоматически строят описание соответствующей БД, приведенной к затребованной нормальной форме.
Поэтому вполне возможно, что будет принято решение о частичной денормализации ранее полученного представления базы данных.
Как было отмечено выше, зависимости между атрибутами фиксируют семантику предметной области.
Когда разработчик знакомится с новой предметной областью, не столь очевиден и однозначен ответ на вопрос что следует считать объектами этой предметной области. В первую очередь выявляются скорее списки атрибутов и зависимости между ними. Разговоры с пользователями специалистами предметной области обычно происходят в терминах какие документы имеются, каковы реквизиты этих документов, как они связаны между собой и как по одним реквизитам одних документов рассчитать значения других(*). Некие объекты в названиях реквизитов документов конечно присутствуют, но...
ПРИМЕР(**). Ставится задача спроектировать БД для секретаря некой игровой лиги небольшого городка.
Речь идет об индивидуальном виде игр (в книге игра в кегли), в которой каждый игрок набирает личные очки. Команде засчитывается победа в игре с командой соперников, если ее игроки суммарно набрали больше очков, чем игроки команды соперников. Далее очки команды вычисляются по результатам серии из трех игр с командой соперников.
Эта информация необходима для расчета очков команд и определения соответствующего из положения в турнирной таблице. Кроме того, эта информация используется при распределении индивидуальных призов игрокам по результатам сезона.
В результате обсуждений с секретарем был подготовлен список атрибутов универсальной таблицы и набор функциональных зависимостей. При этом многие атрибуты первоначального списка были вычеркнуты, т.к. было установлено, что они вычислимы. Например, вычислимой оказалась вся информация о командных результатах.
NКоманды: номер, однозначно идентифицирующий
команду.
НКоманды: наименование, однозначно идентифицирующее
команду.
ФИОИгрока: ФИО, однозначно идентифицирующее игрока.
NПлощадки: номер, однозначно идентифицирующий
игровую площадку.
ФИОКапитана: ФИО, однозначно идентифицирующее не только
игрока капитана команды, но и команду.
Телефон: номер телефона игрока, несколько
игроков могут иметь один и тот же телефон.
Улица: улица, на которой проживает игрок.
NНедели: порядковый номер недели в сезоне.
Рез0: результативность игрока на начало сезона.
ОИгры1: число набранных игроком очков
в 1-й игре недели.
ОИгры2: аналогично... во 2-й игре недели.
ОИгры3: ... в 3-й игре недели.
(ФИОИгрока,NНедели) единственный возможный ключ.
НКомандыNКоманды
НКомандыФИОКапитана
ФИОКапитанаNКоманды
ФИОИгрокаNКоманды,Улица,Телефон,Рез0
ФИОИгрока,NНеделиОИгры1,ОИгры2,ОИгры3,NПлощадки
NПлощадки,NНеделиNКоманды
NКоманды,NНеделиNПлощадки
В диаграмме f-зависимостей: штрих-стрелками отмечены зависимости от части возможного ключа, белой стрелкой транзитивная зависимость от возможного ключа.
ФИОИгрока,NНеделиNПлощадки является транзитивной зависимостью:
ФИОИгрока,NНеделиNКоманды,NНедели
и NКоманды,NНеделиNПлощадки.
Замыкание базового набора f-зависимостей содержит и другие транзитивные зависимости, например:
ФИОИгрока,NНеделиNКоманды,
т.к. ФИОИгрока,NНеделиNПлощадки,NНедели
и NПлощадки,NНеделиNКоманды.
R1(ФИОИгрока,NНедели,NКоманды,НКоманды,ФИОКапитана,
Телефон,Улица,Рез0,ОИгры1,ОИгры2,ОИгры3)
R2(NКоманды,NНедели,NПлощадки)
R11(ФИОИгрока,NКоманды,НКоманды,ФИОКапитана,
Телефон,Улица,Рез0)
R12(ФИОИгрока,NНедели,ОИгры1,ОИгры2,ОИгры3)
R111(ФИОИгрока,NКоманды,Телефон,Улица,Рез0)
R112(NКоманды,НКоманды,ФИОКапитана)
В итоге получили базу данных с 4-мя таблицами. Соответствующая ER/IDEF1X-диаграмма (DBLEC\LIGA.ER1):
ПРИМЕРЫ ВОПРОСОВ НА (ПИСЬМЕННОМ) ЭКЗАМЕНЕ ПО БД.
==========================================================
PROGRAM PP; VAR a,b,x,y,t,s:REAL;
BEGIN READ(a,b); IF sin(a)>b THEN BEGIN x:=tg(a);y:=tg(b) END ELSE
BEGIN x:=t; WHILE x>cos(x) DO BEGIN s:=sin(cos(x));x:=tg(s) END;
IF sin(x)>cos(x) THEN BEGIN t:=x;y:=tg(t) END ELSE y:=tg(x) END; WRITE(x,y) END. ...но более «громоздкая»...
Файл содержит папку сведений о товарах на складах предприятия. Каждый компонент файла содержит сведения об одном виде товаров за один месяц:
наименование склада и ФИО ответственного лица;
движение этого товара на этом складе - для каждого из 31-го дней месяца для каждой из 10-ти возможных операций: вид операции (поступление или выбытие); количество и стоимость соответственно поступившего или выбывшего товара; наименование организации соответственно поставившей или получившей этот товар.
VAR TV:FILE OF RECORD naimt,edt:STRING; sved: RECORD god,mes:INTEGER;
svednal: ARRAY[1..15] OF RECORD kol,stoim:REAL END;
sveddv: ARRAY[1..15] OF RECORD naims,FIOs: STRING; dv: ARRAY[1..31]
OF ARRAY[1..10] OF RECORD vidop:STRING; kold,stoimd:REAL;
naimorg: STRING END END END END
(*) Сегодня интенсивно развиваются компонентные технологии в целом, и в частности технологии доступа к данным, обеспечивающие независимость прикладных приложений от источников данных (не только SQL-ориентированных, но и WEB-ориентированных и других…). ODBC и BDE естественно не единственно возможные средства обеспечения доступа к данными... есть стандарт CORBA (Common Object Request Broker Architecture), ADO (Microsoft ActiveX Data Objects)...
(*) Кстати, NULL-значение (пустое, неопределенное) не обязательно совпадает с 0 (или пробел). Обычно NULL-значение можно ввести, выделив и удалив (Del) текущее значение поля, но реально этот вопрос зависит от некоторых настроек.
(*) Эта зависимость неизбежна - чтобы описать классы, предназначенные для работы с базой данных, нужно конкретно и достаточно много знать о том, как она устроена. Поэтому в основе всегда лежит подходящий формат представления базы данных, а конвертация одних форматов в другие и интерпретация одних форматов в терминах других - вопросы достаточно хорошо на сей день изученные и отработанные.
(*) Фактически эти средства тесно связаны с понятием «транзакция».
Средства управления транзакциями класса TDatabase:
procedure StartTransaction {стартует транзакцию};
procedure Commit {завершает подтверждением};
procedure Rollback {завершает «откатом»};
BDE поддерживает явное управление только неименованными транзакциями, причем с ограниченным набором уровней изолированности (property TransIsolation). Однако, аккуратно используя объекты типа TQuery, TStoredProc, TUpdateSQL (и TDatabase в Delphi 6) можно запросить выполнение SQL-сервером фактически (почти?) любого SQL-оператора.
(**)Посмотреть поля, их свойства и события можно после «двойного Click» мышкой на объекте TDataSet (TTable или TQuery). Если появившееся окно редактирования полей пустое, то нажав правую кнопку мыши в контекстном меню выбрать Add All Fields.
(*) View виртуальная, но постоянная таблица базы данных. Использование View в качестве рабочей временной таблицы плохая идея. Однако ж в данном конкретном случае мы воспользуемся этой возможностью, дабы не усложнять проблемы...
(*) Международный стандарт ISO/IEC 12207, Стандарты комплекса ГОСТ 34, фирменные методики MSF (MicroSoft Solution Framework), Oracle CDM (Custom Development Metod)...
Зиндер Е.С. Соотнесение и использование стандартов организации жизненных циклов систем. Журнал СУБД N 3, 1997.
Вендеров А.М. CASE-технология. М.:ФиC, 1998.-176 с.
Принципы проектирования и разработки программного обеспечения. Учебный курс MCSD. С.Ф. Уилсон и др. М. 2002. 737 с.
(*) Не удается разработать приемлемо детальную (в определенном смысле) модель процессов предметной области... возникает слишком много вопросов о данных... Однако ж и разработка модели данных предметной области в определенный момент упирается в вопросы о модели процессов... Видимо, с этим объективным обстоятельством связано появление объектной методологии в проектировании программных систем.
Буч Г. Объектно-оpиентиpованный анализ и пpоектиpование. М.: БИНОМ, СПб: Невский диалект, 1998. - 560 с.
Рамбо Дж., Якобсон А., Буч Г. UML: специальный справочник. СПб.: Питер, 2002. 656 с.
Ларман К. Применение UML и шаблонов проектирования. М.: Издательский дом «Вильямс», 2002. 624 с.
Якобсон А., Буч Г., Рамбо Дж. Унифицированный процесс разработки программного обеспечения. СПб.: Питер, 2002. 496 с.
http://www.rational.com , http://www.omg.org
(*) Наименование поставщика могло измениться. Но это уже другая проблема хранить или не хранить хронологию таких изменений, в какой мере хранить и для каких реквизитов... это вопрос о хронологических базах данных. В эти проблемы мы пока не станем втягиваться...
...кстати, в нашем примере БД «замят» вопрос о поле «N счета», чей это реквизит поставщика или конкретной сделки с поставщиком или...
(*) Базовый набор зависимостей F можно трактовать как набор базовых задач предметной области, F - как набор всех задач. На этих соображениях можно построить соответствующий язык запросов для решения задач предметной области.
Тыугу Э.Х. Концептуальное программирование. М.:Наука,1984. 256 с.
Канович М.И. Логические методы синтеза программ. Калинин. 1986.
(**) Джексон Г. Проектирование реляционных баз данных для использования на микроэвм. М.:Мир,1991. 252 с.