|
Программирование >> Sql: полное руководство
/* Извлекаем запись о технологе, содержащую коллекцию проектов */ select name, projects into empl name, proj coll from technicians where empl nura = 1234; /* Добавляем в список проектов данного технолога проект gonzo */ insert into table(ргоз со11) values (gonzo); /* Просматриваем список проектов */ foreach proj cursor for select * into a project from table(proj coll) if (a project = atlas then begin update table(proj coll) (project) set project = bmgo where current of proj cursor; exit foreach; end; end if; end foreach; /* Обновляем запись в базе данных модифицированным списком проектов */ update technicians set project = proj coll where einpl num = 1234; Этот Пример демонстрирует несколько аспектов обработки коллекций в хранимых процедурах Informix. Прежде всего, коллекция извлекается из базы данных и помещается в переменную специального типа (collection). Для хранения коллекций можно использовать и переменные, явно объявленные как set, multiset или list. Хранящаяся в переменной коллекция может обрабатываться как обыкновенная таблица. Например, для добавления в коллекцию нового проекта достаточно выполнить инструкцию insert, а для поиска и изменения существующего проекта - позиционную инструкцию update. Обратите внимание на то, что в цикле foreach каждый элемент коллекции по очереди извлекается в переменную, чтобы хранимая процедура могла его обработать. Наконец, содержимое переменной может использоваться для обновления столбца, содержащего коллекцию. В Oracle для обработки массивов переменной длины применяется схожий подход. Отдельные элементы массива абстрактного типа данных доступны через их индексы. Типичная процедура доступа к элементам массива переменой длины в Oracle такова: 1. Извлекаем из таблицы строку, содержащую массив переменной длины, и помещаем ее в локальную переменную, тип которой соответствует структуре строки таблицы или набора извлекаемых из нее столбцов. 2. Выполняем цикл for с переменной-счетчиком п, значение которой изменяется от единицы до числа, соответствующего количеству элементов массива. Чтобы узнать размер массива, нужно обратиться к специальному атрибуту столбца, в котором он содержится, - count. 3. в цикле for для обращения к конкретному элементу массива указывается имя переменой массива и индекс этого элемента. Аналогичным образом можно обрабатывать и вложенные таблицы, хотя обычно это делается проще. Как правило, вначале таблицу делают плоской с помощью SQL-запроса с оператором the, а потом обрабатывают результаты в цикле for. Обработка результирующей плоской таблицы тоже может быть непростым делом. В частности, хранимая процедура может проверять, поступила ли очередная обрабатываемая ею запись из той же строки главной таблицы, что и предыдущая, и если да, то выполнять некоторую специальную обработку, например подсчет промежуточных итогов Таким образом, обработка массивов переменной длины и вложенных таблиц в хранимых процедурах Oracle напоминает типичные вложенные циклы в программах формирования отчетов на языке COBOL тридцатилетней давности. Как видите, обработка коллекций и их отдельных элементов требует довольно сложного программирования - как правило, здесь не обойтись SQL-запросами, пусть даже и с использованием специальных расщирений SQL. Именно поэтому объектно-реляционные СУБД часто критикуют за уход от простоты реляционной модели и возврат к явной навигации по базе данных, которая использовалась для доступа к дореляционным базам данных. Приведенные в этой главе примеры показывают, что в этих утверждениях есть по меньшей мере некоторая доля правды. Пользовательские типы данных в объектно-реляционных СУБД обычно предусмотрен механизм определения пользовательских типов данных. Например, приложению для работы с геофафической информацией может пофебоваться тип данных location, состоящий из значений широты и долготы, каждое из которых в свою очередь состоит из часов, минут и секунд. Для эффективной обработки данньгх этого типа приложению может пофебоваться определить специальные функции, например функцию distance (x, y), вычисляющую расстояние между двумя геофафическими точками. Смысл некоторых всфоенных операций, таких как проверка на равенство (=), также должен быть изменен для типа location. Одним из способов поддержки пользовательских типов данных в Informix Universal Server является ключевое слово opaqqe. Для СУБД тип данных, созданный как opaque, непрозрачен . Она может хранить и извлекать данньге этого типа, но что они собой представляют и как обрабатываются, она не знает. Говоря объектно-ориентированным языком, данньге типа opaque полностью инкапсулированы. Пользователь должен явно (во внешних процедурах, написанных на С или другом языке профаммирования) определить сфуктуру данных для этого типа, описать операции, которые могут над ним выполняться (например, операцию сравнения двух значений), и функции для преобразования этого типа данных между внешним и внуфенним представлениями. Таким образом, тип данных, имеющий категорию opaque, реализует низкоуровневую возможность расширения базовых возможностей СУБД за счет дополнительных типов данных, которые вьп-лядят и интерпретируются как всфоенные. Более широкие возможности определения пользовательских типов данных в Informix обеспечивает ключевое слово distinct. Определение типов данных как distinct позволяет сделать их несовместимыми, даже если они созданы на базе одного и того же всфоенного типа данных Informix. Например, названия городов и компаний в базе данных логически являются данными разных типов. Названия города и компании нельзя сравнивать между собой, но если определить содержащие их столбцы как varchar (20), СУБД позволит это сделать. Для обеспечения более строгой целостности базы данных можно назначить каждому из этих элементов данных собственный тип, имеющий категорию distinct: CREATE DISTINCT TYPE CITY TYPE AS VARCHAR(20); CREATE DISTINCT TYPE CO NAME TYPE AS VARCHAR(20); Теперь при создании таблиц можно использовать для столбцов, содержащих названия компаний и городов, типы данных city type и co name type. Если попытаться сравнить столбцы этих двух типов, СУБД выдаст сообщение об ощибке. Их можно сравнивать, но только после явного приведения к какому-то одному типу. Таким образом, ключевое слово distinct помогает поддерживать целостность базы данных и предотвращать ошибки в программах и запросах, которые с ней работают. Методы и хранимые процедуры в объектно-ориентированных языках программирования объекты инкапсулируют данные и код их обработки; детали организации данных и программные инструкции для манипулирования ими скрыты от пользователя. Взаимодействовать с объектом можно только посредством его методов - специальных общедоступных подпрограмм, принадлежащих объекту (или, более точно, классу объектов). Например, один метод объекта, представляющего клиента компании, может возвращать лимит его кредита. Другой метод может изменять лимит кредита. Само же значение лимита инкапсулировано в объекте - оно скрыто от пользователя, который не знает, в каком виде хранятся данные, и не может получить к ним непосредственный доступ. Данные в таблице классической реляционной базы данных не инкапсулированы. И данные, и их структура доступны внешним пользователям. Фактически одним из главных преимуществ реляционной модели является именно то, что с помощью языка SQL пользователь может формулировать произвольные запросы к базе данных. А если вспомнить о наличии общедоступного системного каталога реляционной базы данных, то контраст с объектно-ориентированной архитектурой становится еще более очевидным. База данных с системным каталогом предоставляет пользователю или приложению полную информацию о своей структуре, так что даже приложение, не знающее ее структуры заранее, легко может с помощью SQL-запросов определить, что в ней находится! Можно ли приблизить реляционную архитектуру к объектной в отношении инкапсуляции? Оказывается, да, и довольно простым способом. Хранимые процедуры совместно со схемой безопасности позволяют имитировать инкапсуляцию данных и методов. Теоретически всем пользователям реляционной базы данных можно предоставить лишь разрешения на выполнение ограниченного набора хранимых процедур и никаких разрешений на непосредственный доступ к таблицам. Тогда способ работы пользователей с базой данных будет близок к работе с настоящим объектом: только регламентированные действия и никакого доступа к его данным и коду. Однако на практике разработчикам приложений, как правило, требуется возможность самим писать хранимые процедуры. Кроме того, профаммам формирования запросов и генераторам отчетов разрешается получать доступ к структуре базы данных. Oracle формализует соответствие между методами объектов и хранимыми процедурами, позволяя явно определять хранимые процедуры как функции-члены АТД.
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |