70584

УПРАВЛЕНИЕ ДАННЫМИ

Конспект

Информатика, кибернетика и программирование

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

Русский

2014-10-22

1009 KB

0 чел.

МОСКОВСКИЙ АВИАЦИОННЫЙ ИНСТИТУТ

(Государственный технический университет)

Направление 220300- Информационные системы и технологии

Склеймин Ю.Б.

УПРАВЛЕНИЕ ДАННЫМИ

(конспект лекций)

3 семестр

Лекции-22 часа

Лабораторные работы – 12 часов

2008г.


Лекция 1

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

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

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

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

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

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

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

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

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

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

Файловые системы

Историческим шагом явился переход к использованию централизованных систем управления файлами.

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

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

Структуры файлов

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

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

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

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

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

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

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

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

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

Именование файлов

Остановимся коротко на способах именования файлов.

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

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

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

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

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

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

Защита файлов

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

Поэтому в большинстве современных систем управления файлами применяется подход к защите файлов, впервые реализованный в ОС UNIX.

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

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

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

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

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

Области применения файлов

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

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

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

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

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

Потребности информационных систем

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

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

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

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

Предположим, что мы решили основывать эту информационную систему на файловой системе и пользоваться при этом одним файлом, расширив базовые возможности файловой системы за счет специальной библиотеки функций. Поскольку минимальной информационной единицей в нашем случае является сотрудник, естественно потребовать, чтобы в этом файле содержалась одна запись для каждого сотрудника. Какие поля должна содержать такая запись? Полное имя сотрудника (СОТР_ИМЯ), номер его удостоверения (СОТР_НОМЕР), информацию о его соответствии занимаемой должности (для простоты, "да" или "нет") (СОТР_СТАТ), размер зарплаты (СОТР_ЗАРП), номер отдела (СОТР_ОТД_НОМЕР). Поскольку мы хотим ограничиться одним файлом, та же запись должна содержать имя руководителя отдела (СОТР_ОТД_РУК).

Функции нашей информационной системы требуют, чтобы обеспечивалась возможность многоключевого доступа к этому файлу по уникальным ключам (недублируемым в разных записях) СОТР_ИМЯ и СОТР_НОМЕР. Кроме того, должна обеспечиваться возможность выбора всех записей с общем значением СОТР_ОТД_НОМЕР, то есть доступ по неуникальному ключу. Для того, чтобы получить численность отдела или общий размер зарплаты, каждый раз при выполнении такой функции информационная система должна будет выбрать все записи о сотрудниках отдела и посчитать соответствующие общие значения.

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

Первое, что приходит на ум, - это поддерживать два многоключевых файла: СОТРУДНИКИ и ОТДЕЛЫ. Первый файл должен содержать поля СОТР_ИМЯ, СОТР_НОМЕР, СОТР_СТАТ, СОТР_ЗАРП и СОТР_ОТД_НОМЕР, а второй - ОТД_НОМЕР, ОТД_РУК, ОТД_СОТР_ЗАРП (общий размер зарплаты) и ОТД_РАЗМЕР (общее число сотрудников в отделе). Большинство неудобств, перечисленных в предыдущем абзаце, будут преодолены. Каждый из файлов будет содержать только недублируемую информацию, необходимости в динамических вычислениях суммарной информации не возникает. Но заметим, что при таком переходе наша информационная система должна обладать некоторыми новыми особенностями, сближающими ее с СУБД.

Прежде всего, система должна теперь знать, что она работает с двумя информационно связанными файлами (это шаг в сторону схемы базы данных), должна знать структуру и смысл каждого поля (например, что СОТР_ОТД_НОМЕР в файле СОТРУДНИКИ и ОТД_НОМЕР в файле ОТДЕЛЫ означают одно и то же), а также понимать, что в ряде случаев изменение информации в одном файле должно автоматически вызывать модификацию во втором файле, чтобы их общее содержимое было согласованным. Например, если на работу принимается новый сотрудник, то необходимо добавить запись в файл СОТРУДНИКИ, а также соответствующим образом изменить поля ОТД_ЗАРП и ОТД_РАЗМЕР в записи файла ОТДЕЛЫ, описывающей отдел этого сотрудника.

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

Но это еще не все, что обычно требуют от СУБД. Во-первых, даже в нашем примере неудобно реализовывать такие запросы как "выдать общую численность отдела, в котором работает Петр Иванович Сидоров". Было бы гораздо проще, если бы СУБД позволяла сформулировать такой запрос на близком пользователям языке. Такие языки называются языками запросов к базам данных. Например, на языке SQL наш запрос можно было бы выразить в форме:

SELECT ОТД_РАЗМЕР

FROM СОТРУДНИКИ, ОТДЕЛЫ

WHERE СОТР_ИМЯ = "ПЕТР ИВАНОВИЧ СИДОРОВ"

AND СОТР_ОТД_НОМЕР = ОТД_НОМЕР

Таким образом, при формулировании запроса СУБД позволит не задумываться о том, как будет выполняться этот запрос. Среди ее метаданных будет содержаться информация о том, что поле СОТР_ИМЯ является ключевым для файла СОТРУДНИКИ, а ОТД_НОМЕР - для файла ОТДЕЛЫ, и система сама воспользуется этим. Если же возникнет потребность в получении списка сотрудников, не соответствующих занимаемой должности, то достаточно предъявить системе запрос

SELECT СОТР_ИМЯ, СОТР_НОМЕР

FROM СОТРУДНИКИ

WHERE СОТР_СТАТ = "НЕТ",

и система сама выполнит необходимый полный просмотр файла СОТРУДНИКИ, поскольку поле СОТР_СТАТ не является ключевым.

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

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

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

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

1. Дайте определение файловой системы.

2. Какие существуют способы именование файлов и  механизмы защиты в файловых системах.

3.Области применения файловых систем.

4. Каковы потребности информационных систем, почему недостаточно систем управления файлами.

Лекция 2

Основные определения

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

Компоненты базы данных:

-  данные,

- аппаратное обеспечение,

- программное  обеспечение,

- пользователи.

Компоненты БД

Аппаратное обеспечение:

- Накопители;

- Контроллеры;

- Процессоры;

Данные

Программное обеспечение:

-СУБД(Сервер);

-Инструментальные средства(Процессоры языков запросов, генераторы отчетов и тд.)

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

- Прикладные программисты;

- DBA;

- Конечные пользователи;

Данные

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

Аппаратное обеспечение

К аппаратному обеспечению системы относится следующее:

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

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

Программное обеспечение

Между собственно физической базой данных (т.е. данными, которые реально хранятся на компьютере) и пользователями системы располагается уровень программного обеспечения, который можно называть пo-разному: диспетчер базы данных (database manager), сервер базы данных (database server) или система управления базами данных, СУБД (DataBase Management SystemDBMS). Все запросы пользователей на получение доступа к базе данных обрабатываются СУБД. Все имеющиеся средства добавления файлов (или таблиц), выборки и обновления данных в этих файлах или таблицах также предоставляет СУБД. Основная задача СУБД — дать пользователю базы данных возможность работать с ней, не вникая во все подробности работы на уровне аппаратного обеспечения. (Пользователь СУБД более отстранен от этих подробностей, чем прикладной программист, применяющий языковую среду программирования.) Иными словами, СУБД позволяет конечному пользователю рассматривать базу данных как объект более высокого уровня по сравнению с аппаратным обеспечением, а также предоставляет в его распоряжение набор операций, выражаемых в терминах языка высокого уровня.

Необходимо отметить еще две особенности.

СУБД - это наиболее важный, но не единственный программный компонент системы. В числе других компонентов можно назвать утилиты, средства разработки приложений, средства проектирования, генераторы отчетов и диспетчер транзакций (transaction manager), или диспетчер обработки транзакций (transaction processing monitorTP monitor).

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

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

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

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

Первая группа — прикладные программисты, которые отвечают за написание прикладных программ, использующих базу данных. Для этих целей применимы такие языки, как COBOL, PL/I, C++, Java или какой-нибудь высокоуровневый язык четвертого поколения. Прикладные программы получают доступ к базе данных посредством выдачи соответствующего запроса к СУБД (обычно это некоторый оператор SQL). Подобные программы могут быть простыми пакетными приложениями или же интерактивными приложениями, предназначенными для поддержки работы конечных пользователей. В последнем случае они предоставляют пользователям непосредственный оперативный доступ к базе данных через рабочую станцию, терминал или персональный компьютер. Большинство современных приложений относится именно к этой категории.

Вторая группа — конечные пользователи, которые работают с системой баз данных в интерактивном режиме. Конечный пользователь может получать доступ к базе данных, применяя одно из интерактивных приложений, упомянутых выше, или же интерфейс, интегрированный в программное обеспечение самой СУБД. Безусловно, подобный интерфейс также поддерживается интерактивными приложениями, но эти приложения не создаются пользователями-программистами, а являются встроенными в СУБД. Большинство СУБД включает по крайней мере одно такое встроенное приложение, а„ именно— процессор языка запросов, позволяющий пользователю в диалоговом режиме вводить запросы к базе данных (их часто иначе называют предложениями или командами), например, с операторами SELECT или INSERT. Язык SQL представляет собой типичный пример языка запросов к базе данных. (Общепринятый термин язык запросов не совсем точно отражает рассматриваемое понятие, поскольку слово запрос подразумевает лишь выборку информации, в то время как с помощью этого языка выполняются также операции обновления, вставки, удаления и др.)

Кроме языка запросов, в большинстве систем дополнительно предоставляются специализированные встроенные интерфейсы, в которых пользователь в явном виде не использует предложения, или команды с такими операторами, как SELECT и insert. Работа с базой данных осуществляется за счет выбора пользователем необходимых элементов меню или заполнения требуемых полей в предоставленных формах. Такие некомандные интерфейсы, основанные на меню и формах, облегчают работу с базами данных для тех, кто не имеет опыта работы с информационными технологиями (или ИТ; часто употребляется также сокращение ИС — информационные системы; эти понятия практически эквивалентны). Командный интерфейс, т.е. язык запросов, напротив, требует некоторого профессионального опыта работы с ИТ (но, безусловно, не такого большого, какой необходим для написания прикладных программ на языке программирования). Однако командный интерфейс более гибок, чем некомандный, к тому же языки запросов обычно включают определенные функции, отсутствующие в интерфейсах, основанных на использовании меню или форм.

• Третья группа — администраторы базы данных, или АБД.

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

(Примерами являются банковские системы, системы продажи железнодорожных и авиационных билетов и т.д.)

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

Реляционная система - это система, основанная  на следующих принципах:

1)  данные для пользователя передаются в виде таблиц (и никак иначе) ;

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

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

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


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

ST_FAM

Сергей

Иван

и др.

S#

ST_NAME

AV_CNT

Домены

Первичный

ключ

S#

ST_FAM

ST_NAME

AV_CNT

S1

Степанов

Руслан

4.1

S2

Иванов

Иван

3.8

S3

Смирнов

Сергей

4.18

S4

Губанов

Владимир

3.7

S5

Толмачев

Сергей

4.0

К

а

р

д

и      ч

н      и

а      с

л      л

ь      о

н

о

е

Отношение S

Кортежи

| <----------------------------------- Степень ----------------------------------->|

Атрибуты

Отношение    -  Таблица;

Кортеж - строка таблицы,

атрибут - столбец;

Количество кортежей - кардинальное число;

Количество атрибутов - степень;

Первичный ключ - столбец или комбинация столбцов, такая, что в любой момент времени не существует двух строк,

содержащих одинаковое значение в этом столбце или комбинации столбцов;

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

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

На практике системы баз данных могут быть легко распределены по категориям в  соответствии со структурами данных и операторами, которые они предоставляются пользователю. Теперь мы можем различать реляционные и нереляционные системы по следующим признакам. Как уже отмечалось, пользователь реляционной системы видит данные в виде таблиц и никак иначе. Пользователь нереляционной системы, напротив, видит данные, представленные в других структурах— либо вместо таблиц реляционной системы, либо наряду с ними. Для работы с этими другими структурами применяются иные операции. В частности, в иерархической системе (например, в СУБД IMS фирмы IBM) данные представляются пользователю в форме набора древовидных структур (иерархий), а среди операций работы с иерархическими структурами есть операции перемещения (навигации) по иерархическим указателям, позволяющие переходить вверх и вниз по ветвям деревьев. Реляционные системы, как мы видели, не имеют таких указателей, и это очень важная их отличительная особенность (по крайней мере, в них отсутствуют указатели, видимые для пользователя, иными словами, указатели на уровне модели, но могут быть предусмотрены указатели на уровне физической реализации).

На основании изложенного можно сделать вывод, что системы баз данных могут быть легко распределены по категориям в соответствии со структурами данных и операциями, которые они предоставляют пользователю. Прежде всего, старые (дореляционные) системы можно разделить на три большие категории6: системы с инвертированными списками (inverted list), иерархические (hierarchic) и сетевые (network). {Примечание. Термин сетевая система в данном случае не имеет ничего общего с коммуникационной сетью.) Эти категории подробно  рассматривать не будем , поскольку, их можно считать устаревшими.

Следует отметить, что сетевые системы иногда называют системами CODASYL или системами DBTG (Data Base Task Group) в честь предложившего их подразделения организации CODASYL (Conference on Data Systems Language). Пожалуй, наиболее известной из таких систем была IDMS корпорации Computer Associates International, Inc. Подобно иерархическим системам (но в отличие от реляционных), все подобные системы предоставляют пользователю доступ к указателям.

Первые реляционные продукты начали появляться в конце 1970-х и начале 1980-х го-

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

DB2  (всевозможные версии) корпорации IBM;

 Ingres II корпорации Computer Associates International, Inc.;

Informix Dynamic Server корпорации Informix Software, Inc.;

Microsoft SQL Server корпорации Microsoft;

Oracle 8i корпорации Oracle;

Sybase Adaptive Server компании Sybase, Inc.

В последнее время стали появляться объектно-ориентированные и объектно-реляционные продукты: первые объектные системы были выпущены в конце 1980-х и начале 1990-х годов, а объектно-реляционные системы были созданы в конце 1990-х годов. Большинство объектно-реляционных СУБД основываются на расширенных оригинальных реляционных продуктах, как в случае с DB2 или Informix. Существующие объектно-ориентированные системы иногда представляют собой попытки создать нечто совершенно отличное от других систем, как это имеет место в случае с системой GemStone корпорации GemStone Systems, Inc. и системой Versant ODBMS компании Versant Object Technology.

В дополнение к различным уже упоминавшимся выше подходам, в течение нескольких лет проводились исследования множества альтернативных схем, включая многомерный (multi-dimensional) подход и логический (logic-based) подход, называемый еще дедуктивным или экспертным. Кроме того, в связи с наблюдающимся в последнее время стремительным ростом World Wide Web и расширением области применения языка XML, проявляется значительный интерес к направлению научной деятельности, которое получило (не совсем удачное) название полуструктурированный подход.

Рассмотрим основные подсистемы реляционной СУБД  (RDBMS);

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

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

На рисунке показаны основные подсистемы ядра СУБД.

Процессор языка программирования

Безопасность

Ввод-вывод

Управление

памятью

СУБД

(RDBMS)

Управление хранением данных

Управление

блокировками

Управление

транзакциями

Контроль распределенных

операций

Ведение журналов и восстановление

Управление хранением данных во внешней памяти

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

Управление транзакциями

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

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

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

С управлением транзакциями в многопользовательской СУБД связаны важные понятия сериализации транзакций и сериального плана выполнения смеси транзакций.

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

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

Oпределение ACID и стоящие за ним свойства.

Итак, стоит начать с определения ACID:

  •  Atomicity — транзакции атомарны, то есть либо все изменения транзакции фиксируются (commit), либо все откатываются (rollback);
  •  Consistency — транзакции не нарушают согласованность данных, то есть они переводят базу данных из одного корректного состояния в другое. Тут можно упомянуть допустимые значения полей, внешние ключи и более сложные ограничения целостности;
  •  Isolation — работающие одновременно транзакции не влияют друг на друга, то есть многопоточная обработка транзакций производится таким образом, чтобы результат их параллельного исполнения соответствовал результату их последовательного исполнения;
  •  Durability — если транзакция была успешно завершена, никакое внешнее событие не должно привести к потере совершенных ей изменений.


Каждое из этих требований выгледит более чем рациональным, особенно если оно затрагивает такие важные сферы, как банковские операции и другие операции с валютой: согласитесь, будет очень неприятно, если с вашего счета деньги спишутся, а на счет магазина они не придут (нарушение «atomicity»), или в результате сбоя АБС будет потеряна информация о том, что вам на счет зачислили зарплату (нарушение «durability»).

Если начать рассуждать о том, как же работают СУБД, поддерживающие ACID транзакции, больше всего вопросов вызовет свойство Isolation: современные СУБД поддерживают сотни и тысячи одновременных транзакций, и все они обращаются к одним и тем же таблицам. Как же сделать так, чтобы они друг другу не мешали?
Здесь на помощь приходит MVCC (MultiVersion Concurrency Control), то есть контроль конкурентного доступа к данным через создание множества “версий” изменяемых данных. В упрощенном виде этот механизм можно представить следующим образом: все операции с данными можно условно разделить на чтение (select), вставку (insert), удаление (delete), обновление (update). Вот что происходит при этих операциях:

  •  Select — считываются валидные записи таблицы. Запись считается валидной, если она создана транзакцией, которая была зафиксирована (commit) до начала текущей транзакции;
  •  Insert — новая запись просто добавляется в свободное место таблицы;
  •  Delete — запись в таблице помечается как не валидная, при этом сама запись не удаляется;
  •  Updateкомбинация delete и insert. Сначала старая версия записи помечается как не валидная, затем добавляется новая запись с обновленными данными.

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


Журнализация

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

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

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

Во всех случаях придерживаются стратегии "упреждающей" записи в журнал (так называемого протокола Write Ahead Log - WAL). Грубо говоря, эта стратегия заключается в том, что запись об изменении любого объекта БД должна попасть во внешнюю память журнала раньше, чем измененный объект попадет во внешнюю память основной части БД. Известно, что если в СУБД корректно соблюдается протокол WAL, то с помощью журнала можно решить все проблемы восстановления БД после любого сбоя.

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

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

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

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

  1.  Дайте определение базы данных.
  2.  Что является компонентами базы данных.
  3.  Перечислите основные понятия реляционной модели данных.
  4.  Назовите основные подсистемы реляционной СУБД.

Лекция 3

Поддержка языков БД (процессор языка программирования)

Для работы с базами данных используются специальные языки, в целом называемые языками баз данных. В ранних СУБД поддерживалось несколько специализированных по своим функциям языков. Чаще всего выделялись два языка - язык определения схемы БД (SDL - Schema Definition Language) и язык манипулирования данными (DML - Data Manipulation Language). SDL служил главным образом для определения логической структуры БД, т.е. той структуры БД, какой она представляется пользователям. DML содержал набор операторов манипулирования данными, т.е. операторов, позволяющих заносить данные в БД, удалять, модифицировать или выбирать существующие данные. Мы рассмотрим более подробно языки ранних СУБД в следующей лекции.

В современных СУБД обычно поддерживается единый интегрированный язык, содержащий все необходимые средства для работы с БД, начиная от ее создания, и обеспечивающий базовый пользовательский интерфейс с базами данных. Стандартным языком наиболее распространенных в настоящее время реляционных СУБД является язык SQL (Structured Query Language). В нескольких лекциях этого курса язык SQL будет рассматриваться достаточно подробно, а пока мы перечислим основные функции реляционной СУБД, поддерживаемые на "языковом" уровне (т.е. функции, поддерживаемые при реализации интерфейса SQL).

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

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

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

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

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

Типовая организация современной СУБД

Естественно, организация типичной СУБД и состав ее компонентов соответствует рассмотренному нами набору функций. Напомним, что мы выделили следующие основные функции СУБД:

управление данными во внешней памяти;

управление буферами оперативной памяти;

управление транзакциями;

журнализация и восстановление БД после сбоев;

поддержание языков БД.

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

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

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

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

Словарь данных

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

Такая независимость данных возможна благодаря СЛОВАРЮ ДАННЫХ РСУБД, который хранит мета-данные (данные о данных) для всех объектов, расположенных в базе данных. Словарь данных РСУБД - множество таблиц, которое храниться в специальной области БД и ведется ядром СУБД.

(т.к. словарь интегрирован в определяемую им БД, значит должен содержать описание самого себя )

Сравнение файловой системы и СУБД.

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

- Файловая система (далее ФС) - “ближе к диску”, т.е. функционирует на более низком уровне и требует от пользователя учета физических особенностей хранения данных (блочный или побайтный ввод-вывод, режимы буферизации, предельные размеры файлов и т.д.);

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

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

- ФС - нет настоящего словаря данных;

- ФС - независимость и переносимость данных обеспечивается хуже, чем СУБД.


Варианты организации доступа к данным

Персональная  БД(информационная система):

Файл(файлы) БД хранятся на локальном диске рабочей станции. Только один пользователь имеет доступ к данным.

Преимущества:

Недостатки:

Многопользовательская  БД(информационная система) файловый вариант:

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

Преимущества:

Недостатки:

Высокий сетевой трафик.

В каждом случае целостность данных определяется логикой приложения.

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

Архитектура  клиент/сервер

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

Открытые системы

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

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

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

Практической опорой системных и прикладных программных средств открытых систем является стандартизованная операционная система. В настоящее время такой системой является UNIX. Фирмам-поставщикам различных вариантов ОС UNIX в результате длительной работы удалось придти к соглашению об основных стандартах этой операционной системы. Сейчас все распространенные версии UNIX в основном совместимы по части интерфейсов, предоставляемых прикладным (а в большинстве случаев и системным) программистам. Как кажется, несмотря на появление претендующей на стандарт системы Windows NT, именно UNIX останется основой открытых систем в ближайшие годы.

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

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

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

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

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

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

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

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

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

Примерами сервером могут служить:

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

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

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

файловый сервер, поддерживающий общее хранилище файлов для всех рабочих станций;

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

Сервер локальной сети предоставляет ресурсы (услуги) рабочим станциям и/или другим серверам.

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

Системная архитектура "клиент-сервер"

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

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

Интерфейс серверной части определен и фиксирован. Поэтому возможно создание новых клиентских частей существующей системы (пример интероперабельности на системном уровне).

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

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

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

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

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

Серверы баз данных

Термин "сервер баз данных" обычно используют для обозначения всей СУБД, основанной на архитектуре "клиент-сервер", включая и серверную, и клиентскую части. Такие системы предназначены для хранения и обеспечения доступа к базам данных.

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

Принципы взаимодействия между клиентскими и серверными частями

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

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

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

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

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

Преимущества протоколов удаленного вызова процедур

Упоминавшиеся выше протоколы удаленного вызова процедур особенно важны в системах управления базами данных, основанных на архитектуре "клиент-сервер".

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

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

Типичное разделение функций между клиентами и серверами

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

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

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

Требования к аппаратным возможностям и базовому программному обеспечению клиентов и серверов

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

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

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

-Сервер - это собственно СУБД. Он поддерживает все основные функции СУБД, а именно:

определение данных;

обработку данных;

защиту и целостность данных;

и т.д.;

Клиенты - это различные приложения, которые выполняются “над” СУБД: приложения, написанные пользователями(на процедурном языке (с, паскаль) или специальном (FoxPro и др)), предоставляемые поставщиками СУБД или сторонними поставщиками ПО.

 

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

(клиент и сервер выполняются на разных машинах)

Преимущества архитектуры клиент/сервер:

Возможность параллельной обработки:

Выполнение сервера и клиента осуществляется разными машинами параллельно. Это должно уменьшить время ответа  и увеличить производительность системы.

 

Машина сервера м.б.  приспособлена для работы с СУБД и может обеспечить лучшую производительность.

 

Несколько разных машин клиентов могут иметь доступ к одной и той же машине сервера.

!! При обработке запросов по сети передаются результаты выполнения запросов и сами тексты запросов. Обработку данных выполняет процессор сервера!!

Варианты

на одном сервере 1 БД;

на одном сервере несколько БД;

разные БД на разных серверах;(распределенная система баз данных)

Рисунок(1 сервер, несколько клиентов);

Рисунок(несколько серверов, несколько клиентов);

3-х(N - ) Уровневая система клиент сервер

Рисунок

1) Сервер БД

2) Сервер приложений

3) Клиент

EX: Сервер приложений - WEB сервер

Клиент - Browser HTML

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

  1.  Дайте определение словаря данных и поясните его функции.
  2.  Сравните файловую систему и СУБД.
  3.  Перечислите варианты организации доступа к данным.
  4.  Сформулируйте преимущества и недостатки архитектуры клиент сервер.

Лекция 4.

Уточнение понятия реляционной модели данных.

Определение базовых понятий реляционных баз данных было дано на первых лекциях.

Были определены следующие понятия:

тип данных,

домен,

атрибут,

кортеж,

первичный ключ

отношение.

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

Домен

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

Следует отметить также семантическую нагрузку понятия домена: данные считаются сравнимыми только в том случае, когда они относятся к одному домену. В нашем примере значения доменов "Номера пропусков" и "Номера групп" относятся к типу целых чисел, но не являются сравнимыми. Заметим, что в большинстве реляционных СУБД понятие домена не используется, хотя в Oracle V7 оно уже поддерживается.

Схема отношения, схема базы данных

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

Схема БД (в структурном смысле) - это набор именованных схем отношений.

В конце 60-х годов появились работы, в которых обсуждались возможности применения различных табличных моделей данных, т.е. возможности использования привычных и естественных способов представления данных. Наиболее значительной из них была статья сотрудника фирмы IBM д-ра Э.Кодда (Codd E.F., A Relational Model of Data for Large Shared Data Banks. CACM 13: 6, June 1970), где, вероятно, впервые был применен термин "реляционная модель данных".

Будучи математиком по образованию Э.Кодд предложил использовать для обработки данных аппарат теории множеств (объединение, пересечение, разность, декартово произведение). Он показал, что любое представление данных сводится к совокупности двумерных таблиц особого вида, известного в математике как отношение – relation (англ.).

Кортеж, отношение

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

Отношение - это множество кортежей, соответствующих одной схеме отношения.

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

Однако в реляционных базах данных это не принято. Имя схемы отношения в таких базах данных всегда совпадает с именем соответствующего отношения-экземпляра.

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

Реляционная база данных - это набор отношений, имена которых совпадают с именами схем отношений в схеме БД.

Фундаментальные свойства отношений

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

Отсутствие кортежей-дубликатов

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

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

Потенциальные ключи

Пусть R – отношение с атрибутами A1, A2, ..., An. Говорят, что множество атрибутов K=(Ai, Aj, ..., Ak) отношения R является возможным (потенциальным) ключом R тогда и только тогда, когда удовлетворяются два независимых от времени условия:

1. Уникальность: в произвольный заданный момент времени никакие два различных кортежа R не имеют одного и того же значения для Ai, Aj, ..., Ak.

2. Минимальность: ни один из атрибутов Ai, Aj, ..., Ak не может быть исключен из K без нарушения уникальности. Т.е. в набор атрибутов первичного ключа не должны входить такие атрибуты, которые можно отбросить без ущерба для основного свойства - однозначно определять кортеж.

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

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

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

Отсутствие упорядоченности кортежей

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

Отсутствие упорядоченности атрибутов

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

Атомарность значений атрибутов

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

Можно сказать, что здесь мы имеем бинарное отношение, значениями атрибута ОТДЕЛЫ которого являются отношения. Заметим, что исходное отношение СОТРУДНИКИ является нормализованным вариантом отношения ОТДЕЛЫ:

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

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

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

Целостность сущности и ссылок

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

Второе требование называется требованием целостности по ссылкам и является несколько более сложным. Очевидно, что при соблюдении нормализованности отношений сложные сущности реального мира представляются в реляционной БД в виде нескольких кортежей нескольких отношений. Например, представим, что нам требуется представить в реляционной базе данных сущность ОТДЕЛ с атрибутами ОТД_НОМЕР (номер отдела), ОТД_КОЛ (количество сотрудников) и ОТД_СОТР (набор сотрудников отдела). Для каждого сотрудника нужно хранить СОТР_НОМЕР (номер сотрудника), СОТР_ИМЯ (имя сотрудника) и СОТР_ЗАРП (заработная плата сотрудника). Как мы вскоре увидим, при правильном проектировании соответствующей БД в ней появятся два отношения: ОТДЕЛЫ ( ОТД_НОМЕР, ОТД_КОЛ ) (первичный ключ - ОТД_НОМЕР) и СОТРУДНИКИ ( СОТР_НОМЕР, СОТР_ИМЯ, СОТР_ЗАРП, СОТР_ОТД_НОМ ) (первичный ключ - СОТР_НОМЕР).

Как видно, атрибут СОТР_ОТД_НОМ появляется в отношении СОТРУДНИКИ не потому, что номер отдела является собственным свойством сотрудника, а лишь для того, чтобы иметь возможность восстановить при необходимости полную сущность ОТДЕЛ. Значение атрибута СОТР_ОТД_НОМ в любом кортеже отношения СОТРУДНИКИ должно соответствовать значению атрибута ОТД_НОМ в некотором кортеже отношения ОТДЕЛЫ. Атрибут такого рода называется внешним ключом, поскольку его значения однозначно характеризуют сущности, представленные кортежами некоторого другого отношения (т.е. задают значения их первичного ключа). Говорят, что отношение, в котором определен внешний ключ, ссылается на соответствующее отношение, в котором такой же атрибут является первичным ключом.

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

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

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

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

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

Основные свойства реляционной БД.

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

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

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

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

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

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

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

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

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


Произведение отношений

A

X

B

Y

C

Соединение

отношений

A1

B1

B1

C1

A1

B1

C1

A2

B1

B2

C1

A2

B1

C1

A3

B2

B3

C2

A3

B2

C1

T1.B1=T2.B1

Деление отношений

A

X

X

A

A

Y

Y

A

Z

B

X

C

Y

Рис.  Некоторые операции реляционной алгебры

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

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

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

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

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

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

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

  1.  Перечислите свойства отношений.
  2.  Дайте определение потенциального (возможного) ключа отношения.
  3.  Перечислите свойства потенциального ключа, дайте определение первичного ключа.
  4.  Перечислите три части реляционной модели.


Лекция 5.

Базисные средства манипулирования реляционными данными

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

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

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

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

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

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

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

Заметим, что крайне редко алгебра или исчисление принимаются в качестве полной основы какого-либо языка БД. Обычно (как, например, в случае языка SQL) язык основывается на некоторой смеси алгебраических и логических конструкций. Тем не менее, знание алгебраических и логических основ языков баз данных часто бывает полезно на практике.

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

Реляционная алгебра

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

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

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

объединения отношений;

пересечения отношений;

взятия разности отношений;

прямого произведения отношений.

Специальные реляционные операции включают:

ограничение отношения;

проекцию отношения;

соединение отношений;

деление отношений.

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

Общая интерпретация реляционных операций

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

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

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

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

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

------------------------

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

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

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

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

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

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

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

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

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

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

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

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

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

Особенности теоретико-множественных операций реляционной алгебры

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

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

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

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

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

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

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

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

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

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

По поводу теоретико-множественных операций реляционной алгебры следует еще заметить, что все четыре операции являются ассоциативными. Т. е., если обозначить через OP любую из четырех операций, то (A OP B) OP C = A (B OP C), и следовательно, без введения двусмысленности можно писать A OP B OP C (A, B и C - отношения, обладающие свойствами, требуемыми для корректного выполнения соответствующей операции). Все операции, кроме взятия разности, являются коммутативными, т.е. A OP B = B OP A.

Специальные реляционные операции

В этом подразделе мы несколько подробнее рассмотрим специальные реляционные операции реляционной алгебры: ограничение, проекция, соединение и деление.

Операция ограничения

Операция ограничения требует наличия двух операндов: ограничиваемого отношения и простого условия ограничения. Простое условие ограничения может иметь либо вид (a comp-op b), где а и b - имена атрибутов ограничиваемого отношения, для которых осмысленна операция сравнения comp-op, либо вид (a comp-op const), где a - имя атрибута ограничиваемого отношения, а const - литерально заданная константа.

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

Пусть UNION обозначает операцию объединения, INTERSECT - операцию пересечения, а MINUS - операцию взятия разности. Для обозначения операции ограничения будем использовать конструкцию A WHERE comp, где A - ограничиваемое отношение, а comp - простое условие сравнения. Пусть comp1 и comp2 - два простых условия ограничения. Тогда по определению:

A WHERE comp1 AND comp2 обозначает то же самое, что и (A WHERE comp1) INTERSECT (A WHERE comp2)

A WHERE comp1 OR comp2 обозначает то же самое, что и (A WHERE comp1) UNION (A WHERE comp2)

A WHERE NOT comp1 обозначает то же самое, что и A MINUS (A WHERE comp1)

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

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

Операция взятия проекции

Операция взятия проекции также требует наличия двух операндов - проецируемого отношения A и списка имен атрибутов, входящих в заголовок отношения A.

Результатом проекции отношения A по списку атрибутов a1, a2, ..., an является отношение, с заголовком, определяемым множеством атрибутов a1, a2, ..., an, и с телом, состоящим из кортежей вида <a1:v1, a2:v2, ..., an:vn> таких, что в отношении A имеется кортеж, атрибут a1 которого имеет значение v1, атрибут a2 имеет значение v2, ..., атрибут an имеет значение vn. Тем самым, при выполнении операции проекции выделяется "вертикальная" вырезка отношения-операнда с естественным уничтожением потенциально возникающих кортежей-дубликатов.

Операция соединения отношений

Общая операция соединения (называемая также соединением по условию) требует наличия двух операндов - соединяемых отношений и третьего операнда - простого условия. Пусть соединяются отношения A и B. Как и в случае операции ограничения, условие соединения comp имеет вид либо (a comp-op b), либо (a comp-op const), где a и b - имена атрибутов отношений A и B, const - литерально заданная константа, а comp-op - допустимая в данном контексте операция сравнения.

Тогда по определению результатом операции сравнения является отношение, получаемое путем выполнения операции ограничения по условию comp прямого произведения отношений A и B.

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

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

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

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

Операция деления отношений

Эта операция наименее очевидна из всех операций реляционной алгебры и поэтому нуждается в более подробном объяснении. Пусть заданы два отношения - A с заголовком {a1, a2, ..., an, b1, b2, ..., bm} и B с заголовком {b1, b2, ..., bm}. Будем считать, что атрибут bi отношения A и атрибут bi отношения B не только обладают одним и тем же именем, но и определены на одном и том же домене. Назовем множество атрибутов {aj} составным атрибутом a, а множество атрибутов {bj} - составным атрибутом b. После этого будем говорить о реляционном делении бинарного отношения A(a,b) на унарное отношение B(b).

Результатом деления A на B является унарное отношение C(a), состоящее из кортежей v таких, что в отношении A имеются кортежи <v, w> такие, что множество значений {w} включает множество значений атрибута b в отношении B.

Предположим, что в базе данных сотрудников поддерживаются два отношения: СОТРУДНИКИ ( ИМЯ, ОТД_НОМЕР ) и ИМЕНА ( ИМЯ ), причем унарное отношение ИМЕНА содержит все имена, которыми обладают сотрудники организации. Тогда после выполнения операции реляционного деления отношения СОТРУДНИКИ на отношение ИМЕНА будет получено унарное отношение, содержащее номера отделов, сотрудники которых обладают всеми возможными в этой организации именами.

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

  1.  Перечислите теоретико-множественные реляционные операции.
  2.  Перечислите специальные реляционные операции.
  3.  Как выполняется операция прямого произведения отношений.
  4.  Как выполняются операции ограничения отношения и операция проекции отношения?


Лекция № 6

Основные компоненты, входящие в состав приложений VFP

Приложение на VFP состоит из следующих компонентов:

- все описание приложения храниться в специальном файле проекта (расширение PJX)

В VFP принципиально изменена система организации данных. Теперь она приблизилась к теоретическим основам реляционной модели и позволяет более естественно выполнять операции реляционной алгебры.

Основная единица хранения данных это таблица, в столбцах и строках которой содержатся данные, как это и было раньше в dbf-файле. Таблица сохранила расширение файла dbf и имеет прямую совместимость со “старыми” dbf-файлами. Таблицы объединяются в базу данных (БД), в которой можно описать все связи, устанавливаемые между полями отдельных таблиц, правила проверки, определяющие реакцию системы на вносимые изменения, добавление или удаление данных и правила проверки целостности данных в БД. Файлы баз данных имеют расширение dbc и при открытии автоматически поддерживают все перечисленные установки для входящих в нее таблиц. При необходимости мы можем создать и таблицы, не входящие в БД, свободные таблицы.

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

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

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

Кандидат (Candidate) аналогичен первичному, но позволяет иметь несколько индексов этого типа для одной таблицы независимо от того, включена она в БД или нет.

Регулярный (Regular) обычный тип индекса, поддерживаемый в предыдущих версиях.

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

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

допускаются длинные имена таблиц;

каждому полю и таблице можно давать комментарии;

позволяется задавать длинные имена полей;

для полей помимо идентификаторов появились заголовки, которые могут использоваться как в окне Browse, так и в качестве заголовков для колонок в объекте Grid;

введены значения по умолчанию для полей;

добавлены два новых типа индексов: первичный и кандидат;

предусмотрены правила проверки для полей и записей при изменении и вводе новых данных;

имеются триггеры для поддержания целостности данных;

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

имеются процедуры БД для описания сложных условий правил проверки;

появились соединения с внешними источниками данных;

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

Все объекты хранятся в таблицах(за исключением файлов PRG и TXT)

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

Индексах, связях между таблицами, и тд.

Интерфейс управляемый событиями.

Основные элементы языка программирования Visual FoxPro.

- типы данных;

- переменные и массивы;

-рабочие области;

-операторы поиска и перемещения по записям;

-операторы циклов;

-управляющие операторы;

Аналогично многим языкам высокого уровня язык Visual Foxpro работает с переменными некоторого фиксированного набора типов. Т.К. основная цель языка VSFP - обработка данных из таблиц то, соответственно, и типы переменных совпадают с возможными типами полей в таблицах VFP.  Имена полей могут содержать до 254 символов, но не должны содержать пробелы, не могут начинаться с цифры и включать специальные символы кроме символов подчеркивания.

Поля могут быть следующих типов:

ТИП

ОБОЗНАЧЕНИЕ

ДЛИНА В БАЙТАХ

Character

C

1-254

Character(binary)

C

1-254

Memo

M

Не ограничена

Memo(binary)

M

Не ограничена

Numeric

N

1-20 цифр, 0-19 дробных деся-тичных знаков (хранятся значения от -0.99E19 до 0.99E20)  Целые числа храняться в этом же формате.

Float

F

20 цифр, 0-19 дробных десятичных знаков (хранятся значения от -0.99E19 до 0.99E20)

Double

B

8 (фиксированная длина, допускаются значения от -4.9Е-324 до 1.8Е308)

Integer

I

4 (фиксированная длина, допускаются значения от -2 147 483 647 до 2 147 483 647)

Currenсy

Y

8 (фиксированная длина, допускаются значения от -9.2Е14 до 9.2Е14)

Date

D

8 (фиксированная длина, допускаются значения от 01.01.100 до 31.12.9999)

DateTime

T

8 (фиксированная длина, допускаются значения от 01.01.100 до 31.12.9999 плюс время от 00.00.00  до 23.59.59)

Logical

L

1 (фиксированная длина)

General

G

Не ограничена

Переменные  в VSFP не являюся жестко типизованными - тип переменной определяется последним присвоенным значением.

Переменные создаются либо описанием операторами Public, Private, либо оператором присваивания.

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

 DECLARE/DIMENSION <переменная> (<вырN1>[,<N2>])

 [,<переменная> (<вырN1>[,<N2>])]

Нумерация элементов массива начинается с 1.

Сразу после описания все элементы массива получают тип LOGICAL и значение .F.

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

Разрешается повторное описание существующего массива без потери имеющихся данных. 

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

VSFP Может одновременно работать с большим количеством таблиц. Каждая таблица открывается в так называемой рабочей области, открывая новую таблицу Вы либо выбираете определенную рабочую область командой SELECT, либо таблица будет открыта в текущей рабочей области. Всего VSFP имеет 32767 рабочих областей. При запуске  по умолчанию активизируется рабочая область 1. Таблица в текущей области открывается командой:

USE <имя таблицы>.

Открытие таблицы в конкретной области:

USE <имя таблицы> IN <номер рабочей области>.

Открытие таблицы в свободной области с наименьшим номером:

 USE <имя таблицы> IN 0.

Открытой таблице VSFP назначает псевдоним (Alias) - имя длиной до 10 символов, служащее для ссылок на эту таблицу:

 USE <имя таблицы> IN 0 ALIAS <псевдоним>.

Дополнение:

 Над переменными и полями таблиц могут выполняться следующие операции:

Математические(перечислены в порядке приоритетов):

** или ^ - возведение в степень;

* - умножение, / - деление;

+ - сложение, - -вычитание;

Логические(в порядке приоритетов):

NOT - НЕ(другая форма - !);

AND - логическое И;

OR - логическое ИЛИ;

Знаки логических операций (кроме  !) окаймляются точками или пробелами.

Отношения:

< - меньше, > - больше, =  - равно,  # - не равно,

<= - не больше, >= - не меньше.

Знаки отношения применимы как к числовым выражениям, так и к датам и символьным выражениям.

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

 $ - сравнение символьных строк. Операция  A$B  даст значение .T. если A идентично B,

либо A входит в B,  и .F. в противном случае.

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

Сцепления:

+ - соединение двух или более строк в одну;

-   то же, но пробелы в конце первой стороки помещаются в конец итоговой строки;

Оператор присваивания

<перем>=<выраж>

STORE <выраж> TO <список перем>

 Структура команды -

команды ориентированные на обработку файлов БД , в самом общем виде имеют следующий синтаксис:

НАЗВАНИЕ  [<границы>]  [<список выражений>]

 [FOR <условие>]    [ WHILE <условие>]

где  НАЗВАНИЕ - имя команды;

      <границы> - диапазон действия команды

   ALL

   REST

   NEXT N

   RECORD N

 FOR <условие> - выполнение команды только для записей, отвечающих <условию>

WHILE <условие> - выполнение команды до тех пор, пока не перестанет выполняться условие;

FOR и WHILE могут присутствовать в команде одновременно. В этом случае WHILE  условие имеет преимущество перед FOR условием.

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

Рассмотрим  команды перемещения указателя текущей записи в таблице. (знакомые по практическим занятиям;) Запись на которой находиться указатель, является текущей,  и только к ней возможен  непосредственный  доступ. Команды перемещения по записям:

GO TOP [IN <ВырN/ВырС>] - переход к первой записи таблицы;[в указанной области];

GO BOTTOM  [IN <ВырN/ВырС>] - переход к последней записи;

GO <ВырN> [IN <ВырN/ВырС>] - переход к записи с номером <ВырN>;

SKIP <ВырN> [IN <ВырN/ВырС>] - переход к записи, отстоящей от текущей на <ВырN> записей; В данной команде <ВырN> может быть отрицательным, что означает движение указателя назад;

SKIP - без параметра аналогично SKIP 1;

Для контроля положения указателя и наличия записей в таблице предусмотрены функции:

RECNO([ <ВырN/ВырС>])  - возвращает номер текущей записи;

RECCOUNT([ <ВырN/ВырС>]) - Возвращает общее число записей в таблице, включая записи, помеченные к удалению;

EOF([ <ВырN/ВырС>]) - Возвращает  .T. если достигнут конец таблицы, если нет возвращает .F.

ВOF([ <ВырN/ВырС>]) - Возвращает  .T. если достигнуто начало таблицы, если нет возвращает .F.

Поиск данных в таблицах

Команда LOCATE  осуществляет последовательный поиск одной самой первой записи в таблице, удовлетворяющей заданному FOR - условию, среди записей , находящихся  в заданных границах, и до тех пор, пока соблюдается  WHILE - условие(если есть);

LOCATE   [FOR <условие>]  [<границы>]   [ WHILE <условие>]

Если границы и while - условие отсутствуют, поиск ведется во всей таблице,  начиная с первой записи;  Если запись найдена функция FOUND() - оценивающая результат поиска, возвращает .T.

указатель записей устанавливается на эту запись. При неудачном поиске FOUND()=. F. EOF() = .T.;

Продолжение поиска начатого командой LOCATE возможно с использованием команды:

 CONTINUE

Пример использования команды LOCATE

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

USE customer  && Open Customer table

SET TALK OFF

STORE 0 TO gnCount

LOCATE FOR ALLTRIM(UPPER(customer.city)) = 'Москва'

DO WHILE FOUND( )

gnCount = gnCount + 1

? company

CONTINUE

ENDDO

? 'Всего заказчиков в Москве: '+ LTRIM(STR(gnCount))

SEEK <выражение>

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

SEEK eExpression

[ORDER nIndexNumber | IDXIndexFileName

| [TAG] TagName [OF CDXFileName]

[ASCENDING | DESCENDING]]

[IN nWorkArea | cTableAlias]

Циклы:

DO WHILE <условие>

<команды>

[exit]

[loop]

EndDO

<команды > выполняются когда <условие> истинно.

[EXIT] - Прерывает выполнение цикла(управление передается оператору следующему за enddo, endfor, endscan)

[LOOP] - переход к началу цикла(на проверку условия)

Пример DO WHILE ... ENDDO

В примере суммируется количество товаров на складе цена которых превышает 20 рублей

USE products  && Opens Products table

SET TALK OFF

gnStockTot = 0

DO WHILE .T.    && Begins loop

IF EOF( )

 EXIT

ENDIF

IF unit_price < 20

 SKIP

 LOOP

ENDIF

gnStockTot = gnStockTot + in_stock

SKIP

ENDDO           && Ends loop

CLEAR

? 'Всего товаров стоимостью больше 20 руб.:'

?? gnStockTot

 Цикл FOR

FOR <перем>=<вырN1> TO <вырN2> [STEP <вырN3>]

 <команды>

[exit]

[loop]

EndFOR

<Перем> - используется в качестве управляющего параметра цикла для которого N1 является начальным значением, N2- конечным, а N3 шагом изменения переменной. По умолчанию шаг изменения параметра цикла =1.

[EXIT] - Прерывает выполнение цикла(управление передается оператору следующему за enddo, endfor, endscan)

[LOOP] - переход к началу цикла(на проверку условия)

Пример FOR ... ENDFOR

* Пример 1

CLEAR

FOR gnCount = 1 TO 10

? gnCount

ENDFOR

* Пример 2

SET TALK OFF

CLOSE DATABASES

OPEN DATABASE (HOME( ) + 'samples\data\testdata')

USE customer  && Opens Customer table

STORE 2 TO gnI  && Initial value

STORE 10 TO gnJ  && Final value

STORE 2 TO K  && Step value

FOR gnCount = gnI TO gnJ STEP K

GOTO gnCount  && Move record pointer

DISPLAY company && Display company name

ENDFOR

Цикл SCAN

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

SCAN   [<границы>]  [FOR <условие>]   [ WHILE <условие>]

 <команды>

[exit]

[loop]

 ENDSCAN

[EXIT] - Прерывает выполнение цикла(управление передается оператору следующему за enddo, endfor, endscan)

[LOOP] - переход к началу цикла(на проверку условия)

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

  1.  Перечислите основные компоненты входящие в состав проекта Visual Foxpro.
  2.  Какие типы данных могут использоваться в таблицах Visual Foxpro?
  3.  Какой оператор используется для описания массивов?
  4.  Перечислите операторы организации циклов.

Лекция 7

Команды управления ходом выполнения программы:

If

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

IF lExpression [THEN]

Commands

[ELSE

Commands]

ENDIF

Параметры

lExpression - логическое выражение. Если lExpression истинно (.T.), любые команды следующие за IF или THEN и предшествующие ELSE или ENDIF выполняются.

· Если lExpression ложно (.F.) и ELSE присутствует, выполняются команды следующиее за ELSE и предшествующие ENDIF.

Оператор do case

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

Синтаксис

DO CASE

CASE lExpression1

 Commands

[CASE lExpression2

 Commands

 ...

CASE lExpressionN

 Commands]

[OTHERWISE

 Commands]

ENDCASE

Аргументы

CASE lExpression1 Commands ...Когда обнаруживается первое истинное (.T.) CASE-выпражение, выполняется следующий за ним набор команд. Команды выполняются до следующего оператора CASE или ENDCASE.

Исполняется только один набор команд, даже если в других CASE – логическое выражение будет истинным.

OTHERWISE Commands   Если все из CASE выражений примут значение ложно (.F.), то будут выполнены команды указанные после OTHERWISE.

Пример

DO CASE ... ENDCASE

STORE CMONTH(DATE( )) TO month  && Название месяца для текущей даты

 

DO CASE  && Begins loop

 

CASE INLIST(month,'January','February','March')

 STORE 'Отчет за первый квартал' TO rpt_title

 

 CASE INLIST(month,'April','May','June')

 STORE ' Отчет за второй квартал ' TO rpt_title

 

 CASE INLIST(month,'July','August','September')

 STORE ' Отчет за третий квартал ' TO rpt_title

 

 OTHERWISE

 STORE ' Отчет за четвертый квартал ' TO rpt_title

ENDCASE  && Ends loop

WAIT WINDOW rpt_title NOWAIT

Команды удаления данных

ERASE  (DELETE FILE)

Удаляет файл(файлы ) с диска

Синтаксис

ERASE FileName | ? [RECYCLE]

FileName   Указывает файл который будет удален. Необходимо указание полного пути к файлу если он расположен не в текущем каталоге.

FileName – может содержать символы обобщения такие как * и ?.

Если в качестве имени файла указать ‘?’ будет выведен диалог для выбора удаляемого файла.

RECYCLE   Удаляемый файл помещается в Windows 95 Recycle Bin (может быть восстановлен).

ZAP

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

Синтаксис

ZAP     [IN nWorkArea | cTableAlias]

IN nWorkArea  указывает номер рабочей области.

IN cTableAlias   указывает алиас таблицы.

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

После выполнения ZAP записи не могут быть восстановлены.

DELETE

Помечает записи как удаленные.

Синтаксис

DELETE

[Scope] [FOR lExpression1] [WHILE lExpression2]

[IN nWorkArea | cTableAlias]

[NOOPTIMIZE]

Scope   Указывает диапазон записей помечаемых к удалению. Могут использоваться: ALL, NEXT N, RECORD N, и REST.

Если аргументы не указаны –помечается текущая запись.

PACK

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

Синтаксис

PACK [MEMO] [DBF]

Выполнение команды PACK требует монопольного доступа к таблице.

Если у таблицы имеются открытые индексы – при выполнении команды они будут перестроены.

RECALL

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

Синтаксис

RECALL

[Scope] [FOR lExpression1] [WHILE lExpression2]

 [NOOPTIMIZE]

Аргументы

Scope   Указывает диапазон восстанавливаемых записей. Могут использоваться: ALL, NEXT N, RECORD N, и REST.

Если аргументы не указаны –снимается пометка с текущая запись.

RECALL – может восстановить записи в таблице если для нее не выполнялись команды ZAP или PACK

Команды изменения данных

REPLACE

Изменяет значения в полях таблицы.

Синтаксис

REPLACE FieldName1 WITH eExpression1 [ADDITIVE]

[, FieldName2 WITH eExpression2 [ADDITIVE]] ...

[Scope] [FOR lExpression1] [WHILE lExpression2]

[IN nWorkArea | cTableAlias]

[NOOPTIMIZE]

Аргументы

FieldName1 WITH eExpression1 [, FieldName2 WITH eExpression2 ... ]   Указывает что данные в FieldName1 заменяются значением Expression1; данные в FieldName2 заменяются значением eExpression2; и т.д.

В случае если значение выражения превышает разрядность числового(numeric) поля, REPLACE выполняет следующие шаги:

1.  REPLACE округляет значение выражения до количества десятичных знаков в поле таблицы.

2. Если значение не размещается, REPLACE сохраняет значение используя представление вида мммЕ пп.

3. Если значение не размещается, REPLACE заменяет содержимое поля звездочками.

Scope   Указывает диапазон изменяемых записей. Могут использоваться: ALL, NEXT N, RECORD N, и REST.

По умолчанию REPLACE изменяет текущую запись (NEXT 1).

IN nWorkArea   Указывает номер рабочей области в которой будут модифицированы записи.

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

Если nWorkArea и cTableAlias не указаны, обновляются записи в текущей рабочей области.

Функции VFP

Математические

ABS(num) – Возвращает абсолютное значение аргумента(модуль)

ACOS(num ) Возвращает значение arccos(num)

ASIN(num ) Возвращает значение arcsin(num)

ATAN(num ) Возвращает значение arctg(num)

ATN2(num1, num2 ) Возвращает значение arctg(num1/num2); num2 мб =0

BETWEEN(num1, num2, num3 )

BITAND(num1, num2)

BITCLEAR(num1, num2) Устанавливает в 0 указанный бит (num2-от 0 до 31) в выражении num1

BITLSHIFT(num1, num2) Сдвиг влево выражения num1 на num2 позиций

BITNOT(num1) Побитная операция NOT над num1

BITOR(num1, num2)

BITRSHIFT(num1, num2) Сдвиг вправо выражения num1 на num2 позиций

BITSET(num1, num2) Устанавливает в 1 указанный бит (num2-от 0 до 31) в выражении num1

BITTEST(num1, num2) Возвращает .T. если указанный бит в num1 установлен в 1; иначе возвращает (.F.).

BITXOR(num1, num2)

CEILING(num1) - округляет число до большего целого.

COS(num1)

DTOR(num1) преобразует  угол из градусов в радианы

EXP(num1)

FLOOR(num1) - возвращает целое число, меньшее или равное num1.

INT(num1)

LOG(num1) Возвращает значение натурального логарифма

LOG10(num1) Возвращает значение десятичного логарифма

MAX( )

MIN( )

MOD(nDividend, nDivisor) Делит одно числовое на другое и возвращает остаток.

nDividend Определяет делимое. nDivisor Определяет делитель.

PI( ) – значение 3.14159

RAND( ) Возвращает случайное число между 0 и 1

ROUND(nExpression, nDecimalPlaces) Округляет выражение до указанного количества десятичных знаков.

RTOD( ) преобразует  угол из  радиан в градусов

SIGN( )

SIN( )

SQRT( )

TAN( )

Строковые

ALLTRIM(ВырС ) Удаляет пробелы вначале и в конце символьного выражения

ASC(ВырС ) Возвращает код первого символа  из символьного выражения

AT(ВырС1, ВырС2 [, ВырN])

Возвращает позицию(отсчет позиций слева-направо) первого вхождения одного символьного выражения (ВырС1) в другое символьное выражение(ВырС2); ВырN-номер вхождения;

AT_C() тоже что и AT() но для двухбайтовых символов.

ATC( ) тоже что и AT() но не различает строчные и заглавные буквы.

ATCC() – ATC() – для двухбайтовых символов.

ATLINE(ВырС1, ВырС2) возвращает номер строки из ВырС2, в которой встретилось выражение ВырС1

ATCLINE( )тоже, что ATLINE но не различает строчные и заглавные буквы.

BETWEEN(ВырС1, ВырС2, ВырС3)

CHR(ВырN) – возвращает символ заданный кодом ВырN

CHRTRAN( )

CPCONVERT( ) - Преобразует символьные выражения в другую кодовую таблицу

CPCONVERT(nCurrentCodePage, nNewCodePage, cExpression)

INLIST (eExpression1, eExpression2 [, eExpression3 ...])

Определяет, соответствует ли выражение одному из выражений в множестве.

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

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

eExpression2 [, eExpression3 ...] Определяет множество выражений, среди которых производиться поиск. (не более 24 выражений )

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

ISALPHA( )

ISDIGIT( )

ISLOWER( )

ISUPPER( )

LEFT(ВырС, ВырN) – Возвращает ВырN символов из ВырС считая слева – направо.

LEN(ВырС) Возвращает количество символов в ВырN

LIKE(ВырС1, ВырС2) Определяет есть ли в ВырС2 подстрока соответствующая образцу ВырС1.

LIKE(ВырС1, ВырС2)

В выражении ВырС1 допустимо использование любой комбинации символов обобщения

? и *.

LOWER( )

LTRIM( )

MAX( )

MIN( )

OCCURS(cSearchExpression, cExpressionSearched)

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

Аргументы

cSearchExpression Определяет выражение, которое разыскивается внутри cExpressionSearched.

Функция возвращает 0 если cSearchExpression не найдено внутри cExpressionSearched.

PADC(eExpression, nResultSize [, cPadCharacter] ); PADL( ); PADR( )

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

cPadCharacter до указанной длины слева (PADL), справа (PADR), или с двух сторон(PADC).

RAT( )  Тоже, что AT(), но символы считаются справа налево.

RATLINE( )

REPLICATE( )

RIGHT( )

RTRIM( )

SPACE( )

STR (nExpression [, nLength [, nDecimalPlaces]])

Преобразует числовое выражение в симвльное.

Синтаксис

STR (nExpression [, nLength [, nDecimalPlaces]])

nExpression - числовое выражение.

nLength Определяет длину возвращаемой строки.

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

STRCONV( )

STRTRAN( )

STUFF(cExpression, nStartReplacement, nCharactersReplaced, cReplacement)

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

CExpression - строка в которой происходит замена.

nStartReplacement определяет позицию в cExpression, с которой начинается замена.

nCharactersReplaced Определяет количество символов, которое будет заменено. Если nCharactersReplaced - 0, строка cReplacement будет вставлена в cExpression

.CReplacement строка замены. Если cReplacement – пустая строка, то число символов, указанное nCharactersReplaced будет удалено из cExpression.

SUBSTR( )

SYS(10)  -

SYS(15)

SYS(2007) – Возвращает значение CRC для строки аргумента

TRANSFORM( )

TRIM( )

TXTWIDTH( )

UPPER( )

Работа с датами

BETWEEN( )

CDOW(dExpression | tExpression) Возвращает день недели из Date или DateTime выражения. (По английски)

CMONTH(dExpression | tExpression ) Возвращает название месяца из Date или DateTime выражения. (По английски)

CTOD(cExpression ) Преобразует символьное выражение в выражение типа Date

CTOT(cExpression ) Преобразует символьное выражение в выражение типа DateTime

DATE( ) Возвращает текущую системную дату.

DATETIME( ) Возвращает текущую системную дату и время.

DAY(dExpression | tExpression ) Возвращает номер дня в месяце(число от 1 до 31)

DMY(dExpression | tExpression) Возвращает символьную строку содержащую дата например, 31 May 1996.

DOW(dExpression | tExpression [, nFirstDayOfWeek]) Возвращает номер дня недели.

EMPTY(dExpression | tExpression)

FDATE(cFileName) Возвращает дату последней модификации файла.

GOMONTH(dExpression | tExpression, nNumberOfMonths)

Возвращает дату, отстоящую от указанной на заданное число месяцев.

nNumberOfMonths - число месяцев.

INLIST( ) см. выше

MAX( ) ------”-----

MDY(dExpression | tExpression) Возвращает символьную строку в формате месяц-день-год для указанной даты.

MIN( ) см. выше

MONTH(dExpression | tExpression) Возвращает номер месяца в году.(от 1 до 12)

SYS(1)  - возвращает системную дату

SYS(2) возвращает текущее время в секундах

SYS(10) возвращает системную дату в виде символьной строки.

SYS(11)

WEEK(dExpression | tExpression [, nFirstWeek] [, nFirstDayOfWeek]) Возвращает номер недели в году.

dExpression | tExpression  выражение типа Date или DateTime.

YEAR(dExpression | tExpression) Возвращает год для указанной даты.

Преобразование типов

CHR(nANSICode) Возвращает символ соответствующий заданному коду

CTOD(cExpression) Преобразует символьное выражение в выражение типа date

DTOC( ) Преобразует выражение типа date в символьное выражение

MTON( ) Преобразует выражение типа Currency в выражение типа Numeric

NTOM( ) Преобразует выражение типа Numeric в выражение типа Currency

NVL (eExpression1, eExpression2)

Возвращает отличное от NULL значение из двух выражений.

eExpression1, eExpression2 NVL() возвращает eExpression2, если eExpression1 содержит NULL значение. NVL() возвращает eExpression1, если eExpression1 – отличное от NULL значение. eExpression1 и eExpression2 могут быть любого типа. NVL() возвращает .NULL. если и eExpression1 и eExpression2 оба содержат NULL значение.

STR( ) см. выше

SYS(10) см. выше

TRANSFORM(eExpression, cFormatCodes) Возвращает символьную строку содержащую результат преобразования выражения eExpression с использованием шаблона cFormatCodes.

TTOC(tExpression [, 1 | 2] ) Преобразует выражение типа DateTime в символьную строку.

TTOD(tExpression) Преобразует выражение типа DateTime в тип Date.

VAL(cExpression) Возвращает числовое значение полученное из символьного выражения.

Проверка файлов и дисков

FCHSIZE (nFileHandle, nNewFileSize)

Изменяет размер файла, открытого на низком уровне.

NFileHandle указатель на файл, возвращается функцией FOPEN() или FCREATE().

NNewFileSize Определяет новый размер файла в байтах.

FCLOSE(nFileHandle) Закрывает файл, открытый на низком уровне.

FCREATE (cFileName [, nFileAttribute])

Создает и открывает файл на низком уровне.

CFileName Определяет имя создаваемого файла.

NFileAttribute Определяет атрибуты создаваемого файла.

0  (по умолчанию) Чтение -запись

1  Только для чтения

2  Скрытый

3  только для чтения, скрытый

4  cистемный

5  только для чтения / системный

6  Системный / скрытый

7  только для чтения /скрытый/системный

FEOF(nFileHandle) Проверяет достигнут или нет конец файла

FFLUSH(nFileHandle) Записывает на диск файловый буфер для файла открытого на низком уровне.

FGETS(nFileHandle [,nBytes]) Возвращает строку считанную из файла

FOPEN(cFileName [, nAttribute]) Открывает файл на низком уровне

FPUTS(nFileHandle, cExpression [, nCharactersWritten]) Записывает строку символов в файл

FREAD(nFileHandle, nBytes) Считывает указанное число байт из файла

FSEEK (nFileHandle, nBytesMoved [, nRelativePosition])

Перемещает указатель в файле, открытом на низком уровне.

NFileHandle указатель файла

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

NRelativePosition   относительно чего перемещается указатель файла:

0  (Значение по умолчанию) начало файла.

1  Текущее положение указателя файла

2  Конец файла

FTIME(cFileName) Возвращает время последней модификации файла.

FWRITE(nFileHandle, cExpression [, nCharactersWritten]) Записывает последовательность байт в файл открытый на низком уровне.

HEADER([nWorkArea | cTableAlias]) Возвращает число байт в заголовке указанной таблицы.

DELETED([cTableAlias | nWorkArea]) Возвращает логическое значение показывающее удалена текущая запись или нет.

FCOUNT([cTableAlias | nWorkArea]) Возвращает число полей в указанной таблице.

FIELD(nFieldNumber [, nWorkArea | cTableAlias]) Возвращает имя поля заданного номером в указанной таблице

FSIZE(cFieldName [, nWorkArea | cTableAlias] | cFileName) Возвращает размер в байтах указанного поля

LUPDATE([nWorkArea | cTableAlias]) Возвращает дату последнего обновления таблицы.

Функции времени

CTOT(cCharacterExpression) Преобразует символьное выражение в тип DateTime

DATETIME( ) Возвращает системные дату и время в переменную типа DateTime

HOUR(tExpression) Возвращает количество часов из переменной типа DateTime

MINUTE(tExpression) Возвращает количество минут из переменной типа DateTime 

SEC(tExpression) Возвращает количество секунд из переменной типа DateTime 

SECONDS( ) Возвращает текущее время в секундах

TIME([nExpression]) Возвращает текущее время в виде символьной строки (hh:mm:ss)

Функция анализа условий

IIF(логВыраж, Выр1, Выр2)

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

логВыраж Определяет логическое выражение, которое IIF() проверяет.

Выр1, Выр2, если логВыраж истинно, то возвращается Выр1. Если логВыраж ложно(.F)., то возвращается Выр2.

Функции анализа типа и наличия данных

TYPE(ВырC) –имя переменной должно быть заключено в апострофы(иначе возвращаемое значение - U)

Character C

Numeric (also float, double, and integer) N

Currency Y

Date D

DateTime T

Logical L

Memo M

Object O

General G

Undefined type of expression  U

Empty(Выр)

Возвращает значение .T. если переданный аргумент:

Character Пустая строка, строка пробелов, табуляций, CR, LF, или любая комбинация из них.

Numeric 0

Currency 0

Float 0

Integer 0

Double 0

Date Empty (ò.å. CTOD(''))

DateTime Empty (ò.å. CTOT(''))

Logical False (.F.)

Memo Empty (no contents)

Функции подстановок

Оператор - &

EVALUATE(cExpression)

вычисляет выражение и возвращает результат.

Функции и команды для  работы с массивами

ACOPY (SourceArrayName, DestinationArrayName

 [, nFirstSourceElement [, nNumberElements [, nFirstDestElement]])]

Копирует элементы из одного массива в другой.

SourceArrayName – исходный массив

DestinationArrayName – результирующий массив.

Массивы могут быть одно - или двумерные. Если результирующий массив не существует, VFP автоматически создает его.

NFirstSourceElement - первый элемент в исходном массиве, который будет скопирован;

NNumberElements - число элементов для копирования. Если nNumberElements -1, все элементы исходного массива, начиная с элемента nFirstSourceElement  будут скопированы.

NFirstDestElement Определяет первый элемент в результирующем массиве.

 

ADEL (ArrayName, nElementNumber [,] 2)

Удаляет элемент из одномерного массива, или строки или столбцы из двумерного массива.

ArrayName Определяет массив из которого удаляются элемент, строка, или столбец.

nElementNumber Определяет номер элемента, строки, или столбца для удаления.

ADIR (ArrayName [, cFileSkeleton [, cAttribute]])

Заносит информацию о файлах в массив и возвращает число файлов.

ArrayName – имя массива.

Следующая таблица описывает содержание и тип данных каждого столбца в массиве:

Столбец

Информация

Тип данных

1

Имена файла

Строка символов

2

Размер файла

Числовой

3

Дата последней модификации

Дата

4

Время последней модификации

Строка символов

5

Атрибуты файла

Строка символов

CFileSkeleton – шаблон имени файла. Разрешается использовать символы обощения * и ?.

CAttribute может содержать любую комбинацию символов D, H, и S.

AELEMENT( )

AFIELDS(ArrayName [, nWorkArea | cTableAlias]) Размещает информацию о структуре таблицы в массиве и возвращает число полей.

AINS(ArrayName, nElementNumber [, 2]) Добавляет элемент в одномерный массив, или строку или столбец в двумерный массив.

ALEN (ArrayName [, nArrayAttribute])

Возвращает число элементов, строк, или столбцов в массиве.

ArrayName – имя массива.

NArrayAttribute Определяет что  возвращает ALEN () число элементов, строк или столбцов в массиве.

0  Возвращает число элементов в массиве.

1  Возвращает число строк в массиве.

2  Возвращает число столбцов в массиве.

ASCAN(ArrayName, eExpression [, nStartElement [, nElementsSearched]])

Просматривает массив в поисках элемента содержащего значение заданное выражением eExpression. Если элемент найден возвращается его номер или 0 в противном случае.

ASORT(ArrayName [, nStartElement [, nNumberSorted [, nSortOrder]]])

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

ASUBSCRIPT( )

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

DECLARE /DIMENSION

См. выше

COPY TO ARRAY

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

Синтаксис

COPY TO ARRAY ArrayName

[FIELDS FieldList]

[Scope] [FOR lExpression1] [WHILE lExpression2]

 [NOOPTIMIZE]

Аргументы

ArrayName Определяет массив, в который копируются данные.

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

APPEND FROM ARRAY

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

Синтаксис

APPEND FROM ARRAY ArrayName

[FOR lExpression]

 [FIELDS FieldList]

Аргументы

ArrayName Определяет имя массива, который содержит данные для добавления в таблицу.

Если присутствует список FieldList, то только указанные поля переносятся из массива в таблицу.

 

Пара команд SCATTER - GATHER 

SCATTER

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

Синтаксис

SCATTER

[FIELDS FieldNameList

| FIELDS LIKE Skeleton | FIELDS EXCEPT Skeleton] [MEMO]

TO ArrayName | TO ArrayName BLANK | MEMVAR | MEMVAR BLANK

 | NAME ObjectName

Аргументы

FIELDS FieldNameList Определяет поля, которые будут переданы в переменные или массив.

FIELDS LIKE Skeleton | FIELDS EXCEPT Skeleton] можно избирательно переносить поля в переменные или массив включением предложения LIKE ИЛИ EXCEPT или обоих.

Шаблон имени поля поддерживает символы обобщения.

Предложение LIKE может быть объединено с предложением EXCEPT:

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

GATHER

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

Синтаксис

GATHER FROM ArrayName | MEMVAR | NAME ObjectName

[FIELDS FieldList | FIELDS LIKE Skeleton | FIELDS EXCEPT Skeleton]

 [MEMO]

Аргументы

FROM ArrayName Определяет массив, данные  из которого заменяют данные в текущей записи таблицы. Значение первого элемента массива заменяет первое поле в текущей записи; значение второго элемента массива заменяет второе поле, и так далее.

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

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

  1.  Перечислите операторы управления ходом выполнения программы.
  2.  Какие команды используются для удаления данных?
  3.  Оператор Replace – его назначение и синтаксис.
  4.  Сформулируйте классификацию функций Visual Foxpro.

Лекция 8

Элементы объектно-ориентированного программирования в VFP 

Хотя Visual FoxPro поддерживает стандартное процедурное программирование Xbase, новые расширения языка дают пользователям мощность и гибкость объектно-ориентированного программирования, что предопределяет изменение всей логики и методики разработки прикладной программы.

Классы и объекты — два фундаментальных понятия объектно-ориентированного программирования. Класс содержит информацию о том, как объект должен выглядеть и вести себя. Другими словами, класс — это прообраз объекта. Visual FoxPro дает возможность пользователям создавать объекты как с помощью визуальных средств, так и программно на основании базовых классов, список которых приведен в табл. 1. Более подробная информация по классам Visual FoxPro приведена ниже.

Таблица 1. Базовые классы Visual FoxPro

CheckBox

EditBox

ListBox Shape

Column

Form

OLEBoundControl Spinner

CommandButton

FormSet

OLEContainerControl TextBox

CommandGroup

Grid

OptionButton Timer

CombcBox

Header

OptionGroup ToolBar

Container

Image

Page

Control

Label

PageFrame

Custom

Line

Separator

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

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

Таблица 2. Основные события Visual FoxPro

Событие

Описание

Load

Форма или набор форм загружаются в память

Unload

Форма или набор форм удаляются из памяти

Init

Объект создается

Destroy

Объект удаляется из памяти

Click

Пользователь щелкает на объекте основной кнопкой мыши

DblClick

Пользователь дважды щелкает на объекте основной кнопкой мыши

RightClick

Пользователь щелкает на объекте дополнительной кнопкой мыши

GotFocus

Объект выделяется либо действиями пользователя (с помощью клавиатуры или мыши), либо программно (используя метод SetFocus)

LostFocus

Объект перестает быть выделенным либо действиями пользователя (выделяется другой объект), либо программно (используя метод SetFocus)

KeyPress

Пользователь нажимает или отпускает клавишу

MouseDown

Пользователь нажимает кнопку мыши, когда указатель мыши находится на объекте

MouseMove

Пользователь перемещает мышь над объектом

MouseUp

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

InteractiveChange

Значение объекта изменяется интерактивно

ProgrammaticChange

Значение объекта изменяется программно

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

Рассмотрим некоторые из возможностей объектной модели Visual FoxPro.

Наследование

Наследование — одна из наиболее мощных возможностей объектно-ориентированного программирования. Заново созданный объект может наследовать характеристики (то есть свойства и методы) от предшественника — другого объекта. Хотя объекты могут наследовать характеристики от родительских классов, они также могут и не принимать во внимание наследование. Это позволяет разработчикам устранить потребность в двойном коде, когда необходимы подобные функциональные возможности, и настроить объекты для использования в конкретных условиях. Visual FoxPro  полностью поддерживает наследование и, в случае надобности, его отмену либо программно, либо с помощью интерфейса.

Создание подклассов

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

Инкапсуляция

Объектно-ориентированное программирование также позволяет пользователям помещать атрибуты (свойства) и правила поведения (методы) в объекты. В Visual FoxPro программисты могут разместить информацию об объекте так, чтобы доступ к ней был невозможен. Это позволяет создавать “черные ящики”, которые скрывают информацию. Даже если внутренняя реализация объекта и управление им может быть полностью скрыта, объект “знает” все, что ему требуется “знать”, чтобы вести себя в соответствии с задуманным алгоритмом.

Полиморфизм

Visual FoxPro дает программистам возможность пользоваться преимуществами полиморфизма. Полиморфизм полезен, когда специфическая функция должна вести себя по-разному при различных обстоятельствах. Например, произвольный метод Append может быть полиморфен в зависимости от типа объекта (скажем, различные кнопки в пользовательской форме для добавления данных в различные таблицы), который вызвал метод Append. Это динамическое связывание функциональных возможностей позволяет создавать структурные классовые иерархии, где базисные скелеты объектов определены в базовом классе, а специализированный код — в полученных подклассах.

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

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

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

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

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

Таблица 3. Типы данных элементов управления

Элемент управления

Допустимые типы данных

CheckBox

Логический, числовой

ComboBox

Символьный, числовой

CommandButton

Числовой

Command Group

Символьный, числовой

EditBox

Символьный

Grid

Символьный, числовой

ListBox

Символьный, числовой

OptionButton

Числовой

OptionGroup

Символьный, числовой

Spinner

Числовой

TextBox

Любой тип данных

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

  1.  Перечислите возможности объектно-ориентированного программирования Visual Foxpro.
  2.  Какие базовые классы существуют в Visual Foxpro.
  3.  Перечислите основные события Visual Foxpro.
  4.  С какими типами данных могут работать элементы управления.

Заметим, что литературы на русском языке, посвященной тематике СУБД, очень много. Невозможно порекомендовать одну или несколько книг, содержание которых покрывало бы материал данного курса. К числу лучших относятся книги К. Дейта "Введение в системы баз данных" (имеет много переизданий) и книга Дж. Ульмана "Основы систем баз данных"

Список литературы

1) К.Дж. Дейт  Введение в системы баз данных, 8-е издание.: Пер. с англ. — Москва: Издательский дом "Вильяме", 2005. 

2)М. Ричардс и др. “ORACLE 7.3 Энциклопедия пользователя”.

Киев, изд. Диасофт, 1997г

3)Омельченко Л. Н., Шевякова Д. А. Самоучитель Visual FoxPro 9.0.

СПб: БХВ-Петербург, 2005г.

4)Дж. Грофф, П. Вайнберг. SQL: Полное руководство; Пер. с англ., Киев: Издательская группа BHV, 2001г.


Оглавление

[1]
Лекция 1

[2] Лекция 2

[3] Лекция 3

[4] Лекция 4.

[5]
Лекция 5.

[6] Лекция № 6

[7] Лекция 7

[8] Лекция 8


 

А также другие работы, которые могут Вас заинтересовать

9865. СССР и международный кризис 1939-1941 гг. 28.17 KB
  СССР и международный кризис 1939-1941 гг. Вторая мировая война началась 1 сентября 1939 г. - фашистская Германия напала на Польшу, Англия и Франция объявили войну Германии. Как и в Первую мировую войну, воевали между собой две коалиции капиталистиче...
9866. Общественная и духовная жизнь России в 19 веке. Русский либерализм 31.7 KB
  Общественная и духовная жизнь России в 19 веке. Русский либерализм. Либерализм был изначально продуктом западной цивилизации, построенной на индивидуализме и рациональном познании мира. Истоки западного либерализма следует искать в античном наследии...
9867. Информационные ресурсы местного самоуправления в регионе 101 KB
  Развитие торговли, которая становится основой жизни городских общин Германии в IX-XI вв., вызвало потребность не только охраны от внешних врагов, но и защиты свободы и независимости от местных феодалов, внутренней самоорганизации и самоуправления. Так, экономическое развитие обуславливает становление свободных общин...
9868. Общественная и духовная жизнь России в 19 веке. Русский Радикализм 36.35 KB
  Общественная и духовная жизнь России в 19 веке. Русский Радикализм. Радикал (от латинского radicalis - коренной) - сторонник крайних, решительных действий и взглядов. Радикализм как общественно-политическое направление нацелено на коренное изменение...
9870. Формы собственности на землю в России 9-17 век особенности крепостного права 29.81 KB
  Формы собственности на землю в России 9-17 век особенности крепостного права. В IX-XII веках экономику Древнерусского государства можно охарактеризовать как раннефеодальную. В это время еще только закладываются основы прочной системы взаимоотношений...
9871. Понятие о скважине, ее элементах и параметрах, характеризующих пространственное положение ствола 15.35 KB
  Понятие о скважине, ее элементах и параметрах, характеризующих пространственное положение ствола. Скважина - это горная выработка приблизительно имеющая форму цилиндра. Может быть длиной до...
9872. Свойства бурового раствора, порядок их определения 15.9 KB
  Свойства бурового раствора, порядок их определения. Основные параметры, которые характеризуют свойство БР относятся: плотность, условная вязкость, показатель фильтрации, СНС, толщины глинистой корки, содержание песка, содержание водородных ионов. 1....
9873. Профили наклонно-направленных скважин. Предельно допустимые темпы искривления 15.19 KB
  Профили наклонно-направленных скважин. Предельно допустимые темпы искривления. Направленной называют скважину, которую бурили вдоль запроектированной пространственной трассы и попали в заданную цель, а ее забой и фильтровая зона не только располагаю...