- •1.Традиционные файловые системы
- •1.1.Подход, используемый в файловых системах
- •2.Системы с базами данных
- •2.1.База данных
- •2.2.Система управления базами данных ─ субд
- •2.3.Разработка базы данных смена парадигмы
- •3.Преимущества и недостатки субд
- •4.Модели данных
- •4.1.Объектные модели данных
- •4.2.Модели данных на основе записей
- •4.2.1 Иерархическая модель данных
- •4.2.2 Сетевая модель данных
- •4.2.3 Реляционная модель данных
- •4.2.4 Свойства отношений
- •4.2.5 Реляционная целостность
- •Целостность сущностей
- •Ссылочная целостность
- •Корпоративные ограничения целостности.
- •5.Функции субд
- •6.Компоненты субд
- •7.Системные каталоги
- •8.Инструкции sql
- •8.1.Имена
- •8.2.Имена таблиц
- •8.3.Имена столбцов
- •8.4.Типы данных
- •8.5.Константы
- •9.Инструкция select
- •9.1.Предложение select
- •9.2.Предложение from
- •9.3.Результаты запроса на выборку
- •9.4.Простые запросы
- •9.5.Вычисляемые столбцы
- •9.6.Выборка всех столбцов
- •9.7.Повторяющиеся строки
- •9.8.Отбор строк (предложение where)
- •9.8.1 Сравнение
- •9.8.2 Проверка на принадлежность значений (оператор between and)
- •9.8.3 Проверка на членство в множестве (оператор in)
- •9.8.4 Проверка на соответствие шаблону (оператор like)
- •10.Запросы с объединением таблиц
- •10.1.Производительность при обработке многотабличных запросов
- •11.Статистические (агрегатные) функции
- •12.Запросы с группировкой (предложение group by)
- •12.1.Условие отбора групп (предложение having)
- •13.Подчиненные запросы (подзапросы)
- •13.1.Условия отбора в подчиненном запросе
- •13.1.1 Проверка на существование (предикат exists)
- •13.1.2 Многократное сравнение (предикаты any и all)
- •Предикат any
- •Предикат all
- •13.1.3 Уровни вложенности запросов
- •14.Представления
- •14.1.Создание представлений
- •14.2.Как субд работает с представлениями
- •14.3.Преимущества представлений
- •14.4.Недостатки представлений
- •14.5.Обновление представлений
- •14.6.Контроль над обновлением представлений (предложение with check option)
- •15.Добавление новых данных
- •15.1.Однострочная инструкция insert
- •15.2.Добавление значений null
- •15.3.Добавление всех столбцов
- •15.4.Многострочная инструкция insert
- •16.Удаление существующих данных
- •16.1.Удаление всех строк
- •16.2.Инструкция delete с подчиненным запросом
- •17.Обновление существующих данных
- •17.1.Обновление всех строк
- •17.2.Инструкции update с подчиненным запросом
- •18.Условия целостности данных
- •18.1.Обязательное наличие данных
- •18.2.Условия на значения
- •18.3.Целостность таблиц (сущностей)
- •18.4.Проблемы, связанные со ссылочной целостностью
- •18.5.Правила удаления и обновления
- •18.6.Каскадные удаления
- •18.7.Ссылочные циклы
- •19.Язык определения данных
- •19.1.Создание базы данных
- •19.2.Создание таблиц (инструкция create table)
- •19.2.1 Определения столбцов
- •19.2.2 Определение первичного и внешнего ключей
- •19.2.3 Условия уникальности и ограничения на значения столбцов
- •19.3.Удаление таблицы (инструкция drop table)
- •19.4.Изменение определения таблицы (инструкция alter table)
- •19.4.1 Добавление и удаление столбца
- •19.4.2 Изменение первичных и внешних ключей
- •20.Псевдонимы таблиц (инструкции create / drop synonym)
- •21.Индексы (инструкции create/drop index)
- •22.Транзакции
- •22.1.Инструкции commit и rollback
- •22.2.Модель транзакции в стандарте ansi/iso
- •22.3.Журнал транзакций
- •22.4.Транзакции и работа в многопользовательском режиме
- •22.4.1 Проблема пропавшего обновления
- •22.4.2 Проблема промежуточных данных
- •22.4.3 Проблема несогласованных данных
- •22.4.4 Проблема строк – призраков
- •22.5.Параллельные транзакции
- •22.6.Блокировка
- •22.6.1 Уровни блокировки
- •22.6.2 Жесткая и нежесткая блокировки
- •22.6.3 Тупиковые ситуации
- •22.6.4 Явная блокировка
- •23.Принципы защиты данных, применяемые в sql
- •23.1.Пользователи
- •23.1.1 Аутентификация пользователей
- •23.2.Защищаемые объекты
- •23.3.Привилегии
- •23.3.1 Работа с привилегиями при помощи ролей
- •23.3.2 Роли, определяемые пользователями
- •23.3.3 Разрешение и запрещение ролей
- •23.3.4 Предоставление привилегий (инструкция grant)
- •23.3.5 Передача привилегий (предложение with grant option)
- •23.3.6 Отмена привилегий (инструкция revoke)
- •Инструкция revoke и право предоставления привилегий
- •24.Программирование сервера баз данныхoracle посредством pl/sql
- •24.1.Блоки
- •24.2.Комментарии
- •24.3.Объявления
- •24.3.1 Переменные и константы
- •24.3.2 Подтипы, определяемые пользователями
- •24.3.3 Составные типы, определяемые пользователями
- •Вложенные таблицы
- •Изменяемые массивы
- •24.3.4 Атрибуты
- •24.3.5 Особые замечания относительно вложенных таблиц и изменяемых массивов
- •Инициализация вложенных таблиц и изменяемых массивов
- •Использование методов сборных конструкций со вложенными таблицами и с изменяемыми массивами
- •24.3.6 Курсоры, курсорные типы и курсорные переменные
- •Курсорные типы и переменные
- •24.4.Функциональные возможности программ
- •24.4.1 Управление выполнением программ
- •Условное управление
- •Итерационное управление
- •24.4.2 Взаимодействие с базами данных
- •Стандартный dml
- •Работа с курсорами
- •Работа с курсорными переменными
- •24.4.3 Обработка исключительных ситуаций
- •24.5.Типы программ pl/sql
- •24.5.1 Анонимные блоки
- •24.5.2 Хранимые процедуры и функции
- •Создание процедур
- •Создание функций
- •Вызов процедур и функций
- •Управление блоками в sql*Plus
- •24.5.3 Модули
- •Использование объектов модуля
- •24.5.4 Триггеры баз данных
- •24.6.Служебные модули oracle
- •24.6.1 Модуль dbms_output
- •24.6.2 Динамический sql
- •Модуль dbms_sql
- •Использование dbms_sql
- •24.6.3 Файловый ввод/вывод (модуль utl_file)
- •Безопасность
- •Безопасность базы данных
- •Безопасность операционной системы
- •Исключительные ситуации, устанавливаемые в utl_file
- •Открытие и закрытие файлов
- •Файловый вывод
- •Файловый ввод
- •24.6.4 Взаимодействие между соединениями (модуль dbms_pipe)
- •Посылка сообщений
- •Получение сообщений
- •Создание программных каналов и управление ими
- •Программные каналы
- •Общие и частные каналы
- •Привилегии и безопастность
- •Установление протокола связи
- •Форматирование сообщений
- •Адресация данных
- •25.Создание приложений баз данных средствами odbc
- •25.1.Архитектура odbc
- •25.2.Коды возврата
- •25.3.Основной алгоритм программ odbc
- •25.4.Функции инициализации и завершения
- •25.5.Выполнение операторов
- •25.5.1 Функции управления каталогом
- •25.5.2 Непосредственное выполнение
- •25.5.3 Подготавливаемое выполнение
- •Использование параметров при выполнении.
- •25.6.Выборка результатов.
- •25.6.1 Выборка информации о результирующем множестве
- •25.6.2 Базовые функции выборки данных
- •25.7. Подробный алгоритм использования odbc в прикладных программах
24.6.2 Динамический sql
Из всех SQL-операторов в программах PL/SQL напрямую можно использовать лишь операторы DML и операторы управления транзакциями. Операторы DDL – использовать нельзя. Чтобы пояснить смысл этих ограничений, рассмотрим принципы создания программ PL/SQL.
В любом языке программирования привязка переменных может быть либо ранней, либо поздней. Привязка (binding) переменной – это процесс указания области памяти, соответствующей некоторому идентификатору программы. В PL/SQL в процесс привязки входит также проверка базы данных на наличие полномочий, позволяющих обращаться к объектам схем. В том языке, где используется ранняя привязка (early binding), этот процесс осуществляется на этапе компиляции программы, а в языке, где применяется поздняя привязка (late binding), она откладывается до времени выполнения программы. Ранняя привязка означает, что этап компиляции программы будет занимать большее время (так как при этом нужно привязывать переменные), однако выполняться программа будет быстрее, поскольку к этому моменту привязка будет завершена. Таким образом, поздняя привязка сокращает время компиляции, но увеличивает время выполнения программы.
При разработке PL/SQL было принято решение об использовании ранней привязки, чтобы объекты базы данных к моменту выполнения блока были уже проверены, и чтобы блок мог быть выполнен максимально быстро. Это вполне оправданно, так как блоки PL/SQL можно хранить в базе данных как процедуры, функции, модули и триггеры. Такие объекты хранятся в скомпилированном виде, то есть при необходимости их можно загрузить из базы данных и выполнить. Именно поэтому операторы DDL использовать нельзя. Оператор DDL модифицирует объект базы данных, следовательно, полномочия на объект должны быть подтверждены вновь. Процесс подтверждения полномочий требует привязки идентификаторов, а это уже было сделано во время компиляции.
Операторы DML и операторы управления транзакциями – это единственные операторы, с помощью которых нельзя модифицировать объекты схем или полномочия на объекты схем, поэтому в PL/SQL могут использоваться только они.
Все программы, приведенные выше, являются статическими. Это означает, что структура SQL – операторов известна уже во время компиляции программы. Для примера рассмотрим следующий блок PL/SQL:
declare
v_position staff.position %type := ‘менеджер’;
v_salary staff.salary %type := 500;
begin
update staff
set salary = v_salary;
where position = v_position;
end;/
Оператор UPDATE этого блока – пример статического SQL-оператора. Теперь рассмотрим такой блок:
declare
v_SQLString varchar2(100);
v_SetClause varchar 2(100);
v_WhereClause varchar2( 100);
begin
v_SetClause := ‘SET salary = :salary WHERE’;
v_WhereClause:=’position = :v_position’;
v_SQLString:= ‘UPDATE staff‘ || v_SetClause || v_WhereClause
DoIt(v_SQLString);
end;
Этот блок нельзя запустить на выполнение сразу же после его написания, так как предварительно нужно создать процедуру DoIt().
Комментируя пример, можно отметить, что посредством корректной функции DoIt() всегда можно выполнить любую DML-инструкцию (INSERT, UPDATE, DELETE), задав набор подстрок этой инструкции, а затем, осуществив их конкатенацию (операция, обозначаемая в PL/SQL как ||).
Преимущества такого подхода в контексте рассмотренного примера очевидны: одна функция DoIt() выполняет произвольную SQL-инструкцию по изменению содержимого базы данных. Однако сама функция DoIt() должна осуществлять, во-первых, проверку корректности задания SQL-инструкции, (т.е. выполнять грамматический разбор строки инструкции с целью выявления синтаксических и семантических неточностей в ее задании), а во-вторых, осуществлять связывание ее параметров. Помимо этого функция DoIt() должна “заставить” ORACLE Server выполнить корректно заданную инструкцию. Понятно, что реализовать функцию обрабатывающую любую DML – инструкцию практически очень сложно из-за произвольности количества и типов связываемых параметров различных инструкций. Однако создать функцию наподобие DoIt(), которая бы выполняла бы различные DML – инструкции с фиксированным количеством параметров определенного типа в принципе возможно.
Реализовать такие функции можно средствами динамического SQL. Для динамических операторов устанавливается меньшее число ограничений: многое из того, что необходимо знать во время компиляции, вовсе не обязательно описывать до этапа выполнения программы. Полное описание SQL-оператора можно дать во время его выполнения.
Динамический SQL помимо всего позволяет также выполнять и DDL операторы, создавая их динамически, во время выполнения программы, а затем проводя их грамматический разбор и обработку. Возможность выполнения DDL-инструкций – это также преимущество динамического SQL. Приложение в случае наличия определенных привилегий пользователя всегда может создавать временные таблицы в схеме базы данных и использовать их с целью временного хранения результатов промежуточных вычислений.
Выполнять SQL-конструкции с помощью PL/SQL можно двумя способами. Первый – воспользоваться DBMS_SQL, модулем, поставляемым вместе с PL/SQL 2.1 и выше. Для ORACLE 8 он был расширен новыми средствами, в том числе средствами обработки массивов. В ORACLE 8i появился и второй способ – внутренний динамический SQL. При его использовании динамические операторы управления встраиваются непосредственно в язык и поэтому выполняются значительно быстрее, чем DBMS_SQL. Однако в данном пособии рассматриваются вопросы написания приложений, использующих только модуль DBMS_SQL. Информацию о внутреннем динамическом SQL можно получить из [3].
