Глава 2 РАСПРЕДЕЛЕННАЯ СИСТЕМА УПРАВЛЕНИЯ БАЗАМИ ДАННЫХ ORACLE 2.1. Структура экземпляров Oracle. Экземпляр Oracle — сложный комплекс структур памяти и процессов операционной системы (рис. 2.1). Рис. 2.1. Экземпляр Oracle 2.1.1. Глобальная системная область ♦ 75 Экземпляр Oracle Каждая база данных (БД) Oracle имеет связанный с ней экземпляр. Организация экземпляра позволяет СУБД обслуживать множество типов транзакций, обеспечивать высокую производительность, целостность данных и безопасность. Термин процесс означает любую задачу, выполняемую без вмешательства пользователя. Открытие БД Oracle включает три стадии. 1. Формирование экземпляра Oracle (предустановочная стадия). 2. Установка базы данных экземпляром (установочная стадия). 3. Открытие БД (стадия открытия). Экземпляр, в котором нет базы данных, называется незанятым (idle), но он занимает память и не выполняет никакой работы. Экземпляр может подсоединиться только к одной БД, а до тех пор, пока не будет использован Parallel Server, БД может быть подключена только к одному экземпляру Oracle. Экземпляр — это мозг системы обработки данных. В экземпляре выполняются все операции, в то время как в БД хранятся все данные. Большинство настроек экземпляра связано с компонентами в глобальной системной области. Но кроме них существуют и некоторые опции настройки, касающиеся фоновых процессов. 2.1.1. Глобальная системная область. В SGA (System Global Area) хранятся структуры памяти, необходимые для манипулирования данными, анализа предложений SQL и кэширования транзакций. К этой области одновременно имеет доступ множество процессов, которые могут считывать данные из нее или модифицировать их. Все операции с БД используют информацию, находящуюся в SGA. SGA выделяется сразу же после создания экземпляра еще на предустановочной стадии. Освобождается эта область только после полного выключения экземпляра. Экземпляр Oracle представляет собой сложный комплекс взаимодействующих процессов. SGA состоит из следующих компонентов: • разделяемый пул (SHARED POOL); • кэш-буфер данных (DATABASE BUFFER CACHE); • буфер журнала транзакций (REDO LOG BUFFER); 76 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.1. Структура экземпляров Oracle. • структуры сервера многозадачной THREADED SERVER — MTS). среды (MULTI- Разделяемый пул Разделяемый пул (рис. 2.1) содержит кэш библиотеки, кэш словаря и управляющие структуры сервера (такие, как набор символов БД). Кэш библиотеки хранит план выполнения предложений SQL. Здесь содержатся заголовки пакетов PL/SQL и процедур, выполнявшихся ранее. Кэш словаря хранит строки словаря данных, которые были использованы для лексического анализа предложений SQL. Сервер Oracle использует кэш библиотеки для повышения скорости выполнения операторов SQL. Размер разделяемого пула задается параметром SHARED POOL SIZE в файле INIT.ORA. Размерность значения параметра — байты. Объем пула необходимо заказывать. Кэш-буфер данных Кэш-буфер данных состоит из блоков памяти того же размера, что и блоки ORACLE. Все данные, с которыми работает СУБД, первым делом загружаются в кэш-буфер. В этих же блоках памяти выполняется и любое обновление данных. Поэтому очень важно правильно установить размер буфера. СУБД переносит данные на диск — в соответствии с порядком их размещения в списке LRU (LEAST RECENTLY USED). Этот список отслеживает обращение к блокам данных и учитывает частоту обращений. Если выполняется обращение к блоку данных, хранящемуся в кэш-буфере, то оно помещается в тот конец списка, который носит название MRU (MOST RECENTLY USED). Если серверу требуется место в кэш-буфере для загрузки нового блока, то он решает этот момент с помощью списка LRU — какой из блоков перенести на диск, чтобы освободить место для нового. Блоки, наиболее отстоящие в списке от MRU, — кандидаты на удаление из кэш-буфера. Таким образом, дольше всего остаются в кэш-буфере те блоки, к которым чаще всего выполняется обращение. Модифи- 2.1.2. Фоновые процессы Oracle ♦ 77 Множество фоновых процессов Oracle цированные блоки называются грязными (dirty) и помещаются в соответствующий dirty-список. Буфер журнала транзакций Данные о транзакциях хранятся в этом буфере до тех пор, пока не будут переписаны в файл оперативного журнала транзакций. После заполнения буфера его содержимое переносится в файл журнала транзакций. Размер буфера журнала транзакций задается параметром LOG_BUFFER. Значение параметра указывает размер буфера в байтах. В результате вы получите время, которое пользовательские процессы находились в состоянии ожидания при обращении к буферу журнала транзакций. 2.1.2. Фоновые процессы Oracle. В процессе работы СУБД ORACLE просматривает тысячи записей в таблицах данных, отвечает на сотни запросов пользователей одновременно. Вся работа распределяется между множеством программ, которые работают независимо одна от другой, причем у каждой своя роль. В совокупности эти программы называются фоновыми процессами ORACLE. Множество фоновых процессов Oracle включает: • SMON и PMON, • RECO, • DBWR, • SNPn, • LGWR, • Dnnn, • ARCH, • LCKn, • СКРТ, • Pnnn Также нужно обратить внимание на процессы USER и SERVER, выполняющие обработку транзакций конечного пользователя БД. Хотя эти процессы и не квалифицируются как фоновые, они играют значительную роль в функционировании системы. Процессы PMON и SMON выполняют автоматическую “уборку” после внезапно прекратившихся или завершившихся ава- 78 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.1. Структура экземпляров Oracle. рийно процессов. После запуска БД процесс SMON (System Monitor) выполняет автоматическое восстановление экземпляра. Если при последнем выключении БД что-либо не было завершено, SMON автоматически запускает незавершенные операции. PMON — Process Monitor (Монитор процессов) выполняет автоматическую “уборку” после внезапно прекратившихся или завершившихся аварийно процессов. Эта “уборка” включает удаление сеанса, блокировок, которые были им установлены, непринятых транзакций, освобождение ресурсов глобальной системной области, выделенных этому процессу. Фоновые процессы SMON и PMON должны быть непременно пущены при запуске системы. В противном случае система функционировать не будет. Процесс DBWR (DataBase Writer) — отвечает за перенос обновленных блоков, занесенных в dirty-cписок из кэш-буфера данных в файлы данных. Вместо того, чтобы записывать каждый блок на диск сразу, DBWR ждет, пока не будет выполнено одно из условий, а затем просматривает dirty-cписок и все отмеченные в нем блоки переписывает на диск. Процесс LGWR (Log Writer) — четвертый и последний фоновый процесс, запуск которого обязателен для работы СУБД ORACLE. Этот процесс отвечает за перезапись информации из буфера журнала транзакций, который находится в глобальной системной области, в файлы оперативного журнала. ORACLE не считает транзакцию выполненной до тех пор, пока процесс LGWR не перезапишет данные о ней из буфера журнала транзакций в файл. Этот процесс редко служит причиной осложнений в работе. Фоновые процессы-диспетчера Dnnn. Остановимся подробнее на этих процессах. Все процессы сервера могут закрепляться за определенными пользовательскими процессами, либо использоваться несколькими процессами пользователя. В последнем случае они называются “разделяемые” (shared) процессами или серверами. Для работы с применением разделяемого сервера необходима установка Multi Threaded Server (MTS). При использовании разделяемых процессов, в системе должен существовать как минимум один про- 2.1.2. Фоновые процессы Oracle ♦ 79 Дополнительный фоновый процесс ARCH (Archiver) цесс диспетчер. Процесс-диспетчер передает запросы пользователей в очередь SGA и возвращает ответы сервера соответствующему процессу пользователя. Фоновый процесс Dnnn, где nnn — это число, задаваемое в файле init.ora. Параметр указывает протокол, который будет использован диспетчером и количество процессов. Дополнительный фоновый процесс ARCH (Archiver) отвечает за копирование полностью заполненного оперативного журнала транзакций в архивные файлы журналов транзакций. Во время перезаписи в архив никакой другой процесс не может получить доступ к журналу. Во время копирования в архив система должна находиться в состоянии ожидания. CKPT (Check Point) — это дополнительный фоновый процесс, который отвечает за обработку контрольных точек. Необходимость в нем возникает, когда надо снизить нагрузку на LGWR. Процесс RECO (Recovery) отвечает за восстановление незавершенных транзакций в распределенной системе БД. Когда возникает подозрительная транзакция, RECO выполняет свои функции автоматически без вмешательства администратора БД. Процесс SNPn (Snapshot) выполняет автоматические обновления снимков БД и запускает процедуры в соответствии с расписанием, зафиксированным в пакете DBMS_JOB. В файле init.ora задается количество запускаемых процессов SNPn и длительность интервала, в течение которого процесс “засыпает” прежде чем выполнить задание. Процесс LCKn (Parallel Server Lock) — в среде, производящей параллельное обслуживание нескольких экземпляров БД, на LCKn возлагается ответственность за координацию блокировок устанавливаемых разными экземплярами БД. Если в системе нет параллельного обслуживания, то запуск LCKn не нужен. Процессы параллельных запросов (Parallel Query) получили в системе наименование Pnnn. Сервер Oracle запускает и останавливает процессы Pnnn в зависимости от активности работы с БД и настройки опций параллельных запросов. Эти процессы принимают 80 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.1. Структура экземпляров Oracle. участие в формировании индексов, таблиц и запросов. Количество запускаемых процессов определяется двумя параметрами: PARALLEL_MIN SERVERS и PARALLEL_MAX SERVERS, определяющими, соответственно, минимальное и максимальное количество запускаемых процессов. 2.1.3. Процессы пользователя и сервера Приложения и утилиты связываются с СУБД посредством процессов пользователя. Каждый процесс пользователя подключается к процессу сервера. Процесс сервера анализирует и выполняет переданные ему операторы SQL и возвращает результат процессу пользователя. Кроме того, процесс сервера считывает блоки данных из файлов данных и размещает их в кэш-буфере данных. Приложения и клиентские части связываются с сервером Oracle посредством “процессов пользователя”. Каждый процесс пользователя имеет подключение к процессу сервера (рис. 2.1), который может быть либо жестко связан с одним процессом пользователя, либо распределяться между многими. Процесс сервера, анализирует и выполняет переданные ему операторы SQL и возвращает результат процессу пользователя. Так же процесс сервера считывает блоки данных из файла данных и размещает их в кэш-буфере данных. Каждому процессу пользователя выделяется область памяти, которая называется “глобальной областью процесса” — PGA (Process Global Area). Содержимое PGA зависит от режима подключения процесса пользователя к процессу сервера. Если процесс пользователя имеет выделенный процесс сервера, то в PGA размещается информация о текущем сеансе работы пользователя, стек и информация о состоянии курсора. Если же процесс пользователя связан с разделяемым процессом сервера, то информация о текущем сеансе и текущем состоянии курсора хранится в SGA. В общем, это не очень существенно, хотя некоторое увеличение размера SGA все же потребуется. В этом и состоит разница между двумя типами взаимодействия клиента и сервера в БД Oracle. 2.2. Основные объекты СУБД ORACLE ♦ 81 Таблица, представление, пользователь 2.2. Основные объекты СУБД ORACLE. Oracle поддерживает реляционную модель данных, поэтому, естественно, что к числу основных объектов Oracle относятся: таблица, представление, пользователь. Таблица, представление, пользователь Таблица (TABLE) является базовой структурой реляционной модели. Вся информация в базе данных хранится в таблицах. Таблицы состоят из множества поименованных столбцов или атрибутов. Множество значений столбца определено с помощью ограничений целостности, то есть поддерживается ограниченная концепция домена. Полное имя таблицы в базе данных состоит из имени схемы, в данной реализации совпадающем с именем пользователя, создавшего таблицу, и собственно имени таблицы. Таблица может быть пустой или состоять из одной или более строк значений атрибутов. Строки значений атрибутов таблицы называются также кортежами. Представление (VIEW) — это поименованная, динамически поддерживаемая сервером выборка из одной или нескольких таблиц. Оператор SELECT, определяющий выборку, ограничивает видимые пользователем данные. Сервер гарантирует актуальность представления, то есть формирование представления (материализация соответствующего запроса), производится каждый раз при использовании представления. Используя представления, администратор безопасности ограничивает доступную пользователям часть базы данных только теми данными, которые реально необходимы для выполнения его работы. Пользователь (USER) — объект, обладающий возможностью создавать и использовать другие объекты ORACLE, а также запрашивать выполнение функций сервера. К числу таких функций относятся организация сессии, изменение состояния сервера и базы данных, запрос на выполнение операторов SQL и др. Для упрощения решения задач идентификации и именования в базе данных ORACLE поддерживает объекты: последовательность и синоним. 82 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.2. Основные объекты СУБД ORACLE. Последовательность (SEQUENCE) — это объект, обеспечивающий генерацию уникальных номеров в условиях многопользовательского асинхронного доступа. Обычно элементы последовательности используются для вставки уникальных идентификационных номеров для элементов таблиц базы данных. Синоним (SYNONYM) — это альтернативное имя-псевдоним объекта ORACLE, который позволяет пользователям базы данных иметь доступ к данному объекту. Синоним может быть частным и общим. Общий (public) синоним позволяет всем пользователям базы данных обращаться к соответствующему объекту по альтернативному имени. Для управления эффективностью доступа к данным Oracle поддерживает объекты: индекс, табличная область и кластер. Индекс (INDEX) — это объект базы данных, создаваемый для повышения производительности выборки данных. Индекс создается для столбцов таблицы или для представления в пространстве базы данных и обеспечивает более быстрый доступ к данным базы данных за счет хранения прямых ссылок на место расположения строк, содержащих требуемые данные. Табличная область (TABLESPACE) — именованная часть базы данных, используемая для распределения памяти для таблиц и индексов. Кластер (CLUSTER) — объект, задающий способ совместного хранения данных нескольких таблиц, содержавших информацию, обычно обрабатываемую совместно. Кластеризация столбцов таблиц позволяет уменьшить время выполнения выборки. Строки таблиц, имеющие одинаковое значение в кластеризованных столбцах, хранятся в базе данных специальным образом. Для эффективного управления разграничением доступа к данным Oracle поддерживает объект роль. Роль (ROLE) — именованная совокупность привилегий, которые могут быть предоставлены пользователям или другим ролям. 2.2. Основные объекты СУБД ORACLE ♦ 83 Cнимок и связь базы данных ORACLE поддерживает несколько стандартных или предопределенных ролей. Специфичными для распределенных систем являются объекты ORACLE: снимок и связь базы данных. Cнимок и связь базы данных Снимок (SNAPSHOT) — локальная копия таблицы удаленной базы данных, которая используется либо для тиражирования (копирования) всей или части таблицы, либо для тиражирования результата запроса данных из нескольких таблиц. Снимки могут быть модифицируемыми или предназначенными только для чтения. Снимки только для чтения возможно периодически обновлять, отражая изменения основной таблицы. Изменения, сделанные в модифицируемом снимке, распространяются на основную таблицу и другие копии. Связь базы данных (DATABASE LINK) — это объект базы данных, который позволяет обратиться к объектам удаленной базы данных. Имя связи базы данных можно рассматривать как ссылку на параметры механизма доступа к удаленной базе данных (имя узла, протокол и т.п.). Использование одного имени упрощает работу с объектами удаленной базы данных. Для программирования алгоритмов обработки данных, реализации механизмов поддержки целостности базы данных Oracle использует объекты: процедура, функция, пакет и триггер. Процедура (PROCEDURE) — это поименованный, структурированный набор переменных и операторов SQL и PL/SQL, предназначенный для решения конкретной задачи. Функция (FUNCTION) — это поименованный, структурированный набор переменных и операторов SQL и PL/SQL, предназначенный для решения конкретной задачи и возвращающий значение переменной. Пакет (PACKAGE) — это поименованный, структурированный набор переменных, процедур и функций, связанных единым функциональным замыслом. Например, ORACLE поставляет пакет DBMS_OUTPUT, в котором собраны процедуры и функции, предназначенные для организации ввода-вывода. 84 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL Триггер (TRIGGER) — это хранимая процедура, которая запускается (автоматически выполняется) тогда, когда происходит связанное с триггером событие. Обычно события связаны с выполнением операторов INSERT, UPDATE или DELETE в некоторой таблице. 2.3. Язык PL/SQL 2.3.1. Типы данных ORACLE. Существует следующие типы данных в PL/SQL: • скалярный (простой) тип; • составной тип — запись; • ссылочный — указатель на объект программы; • LOB (LOCATORS) — графические образы. Скалярные (простые) типы Строковые типы Тип CHARACTER — используется для хранения строк фиксиро- ванной длины. Синтаксис: CHARACTER[(длина)] CHAR[(длина)] Максимальное значение параметра длина — 255 символов. Тип VARCHAR используется для хранения строк переменной длины. Следующие предложения эквивалентны: VARCHAR[(длина)] CHAR VARYING[(длина)] CHARACTER VARYING[(длина)] Если длина строки не указана явно, она полагается равной единице во всех случаях. Максимальное значение параметра длина — 2000 символов для всех трех случаев. Пример 2.3.1 Str1 CHAR(15) Str2 CHARACTER VarSts1 VARCHAR(15) VarStr2 CHARACTER VARYING(10) 2.3.1. Типы данных ORACLE ♦ 85 Числовые типы Есть тип, характерный только для ORACLE VARCHAR2[(длина)] С помощью этого типа резервируется необходимое пространство для хранения строк максимальной длины 32767 байт, хотя максимальная ширина столбца базы данных типа VARCHAR2 равна 2000 байт. Тип LONG. Для хранения больших строк переменной длины используется тип LONG[(длина)]. Если параметр длина не указан, то предполагается, что у строки длина 2 мегабайта, максимальная длина — 2 гигабайта. Числовые типы. Тип INTEGER используется для представления чисел от –231 до 231 Синтаксис: INTEGER, INT Пример 2.3.2 varint INTEGER varint2 INT Тип NUMBER [Только для ORACLE] — используется для пред- ставления чисел с заданной точностью. Синтаксис: NUMBER[(точность[,масштаб])] Если значение параметра точность не указано явно, оно полагается равным 38. Значение параметра масштаб по умолчанию предполагается равным 0. Значение параметра точность может изменяться от 1 до 38; значение параметра масштаб может изменяться от –84 до 128. Использование отрицательных значений масштаба означает сдвиг десятичной точки в сторону старших разрядов. Например, определение NUMBER(7, –3) означает округление до тысяч. Tипы DECIMAL и NUMERIC — полностью эквивалентны типу NUMBER. Синтаксис: DECIMAL[(точность[,масштаб])] DEC[(точность[,масштаб]) NUMERIC[(точность[,масштаб])] 86 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL Пример 2.3.3 Varcounter NUMBER Vardec1 DEC Vardec2 DEC(7) Vardec3 DECIMAL(7,3) Varnum NUMERIC Битовые строки Тип RAW [Только для ORACLE] — используется для хранения битовых строк переменной длины. Отличие типа RAW от типов CHAR, VARCHAR2 состоит в том, что для типов символьных строк ORACLE (точнее SQL*Net) производит автоматическое преобразование данных при их передаче между клиентом и сервером. Синтаксис: RAW[(длина)] Параметр длина измеряется в байтах. Максимальное значение параметра длина — 255 байт. Тип LONG RAW [Только для Oracle] — используется для хране- ния больших битовых строк переменной длины. Синтаксис: LONG RAW[(длина)] Параметр длина измеряется в байтах. Если длина строки не указана явно, она полагается равной 2 мегабайтам. Максимальное значение параметра длина — 2 гигабайта символов. Для переменных типа LONG RAW невозможно построение индекса. Пример 2.3.4 Bit1 RAW(15) Verylong1 LONG RAW(100000) Типы дата и время Тип DATE [Только для Oracle] — используется для хранения да- ты и времени. Поддерживаются даты с 1 января 4712 г. до н.э. до 31 декабря 4712 г. н.э. Для начального присваивания даты обычно используется функция ТО_DATE('символьная_строка_даты', 'формат_даты') 2.3.1. Типы данных ORACLE ♦ 87 Метод %TYPE При определении даты без уточнения времени по умолчанию принимается время полуночи. Функция SYSDATE присваивает переменной текущее значение даты и времени. Синтаксис: DATE Пример 2.3.5 BIRTHDAY DATE Наличие специального типа для хранения даты и времени позволяет поддерживать специальную арифметику дат и времен. Добавление к переменной типа DATE целого числа означает увеличение даты на соответствующее число дней, а вычитание выполняется как определение более ранней даты. Рассмотрим несколько примеров. Пример 2.3.6 SQL>select sysdate from dual; SYSDATE 15-NOV-98 SQL>select sysdate+20 “sysd+20” from dual; sysd+20 05-DEC-98 SQL>select sysdate-20 “sysd-20” from dual; sysd-20 26-OCT-98 Метод %TYPE. Предопределенный метод %TYPE позволяет определить тип переменной, совпадающий с типом атрибута некоторой таблицы, например: V_ENAME EM.ENAME%TYPE; V_MIN_BALANCE EM.BALANCE%TYPE := 10 В этом примере объявляется переменная V_ENAME того же типа, что и поле ENAME в таблице EM, а переменная V_MIN_BALANCE того же типа, что поле BALANCE в таблице EM. Однако для колонок NOT NULL нельзя пользоваться этим методом. 88 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL Составные типы К составным типам относятся: • PL/SQL записи; • PL/SQL таблицы; • таблица записей. Записи Запись — это группа родственных данных, каждое из которых имеет имя и тип. PL/SQL запись содержит скаляр, запись или поле из PL/SQL таблицы. Синтаксис команды создания PL/SQL записи: --Создание типа type_name TYPE type_name is record (field_declaration[, field_declaration]...); --Создание переменной типа type_name identifier type_name; где field_declaration есть: field_name {field_type|variable%type |table.column%type|table%rowtype} [[not null] {:=default}|expr] где field_name — имя поля, field_type — его тип, expr — начальное значение field_name. Пример 2.3.7 Type emp_record_type is record (ename varchar2(10), job varchar2(9), sal number(7,2)); emp_record emp_record_type; Метод %ROWTYPE Предопределенный метод %ROWTYPE может применяться как ко всей таблице, так и к ее отдельным полям (атрибутам). При использовании этого метода с таблицей или представлением объявляется запись той же структуры, что и таблица или представление, при этом поля записи имеют имена и типы полей таблицы или представления. 2.3.2. Таблицы ♦ 89 Cинтаксис оператора определения таблиц Пример 2.3.8 Declare Emp_record emp%rowtype; После такого описания запись EMP_RECORD имеет те же поля, что и запись EMP. Использование %ROWTYPE имеет ряд преимуществ: • число и тип колонок базы данных может быть неизвестен; • число типов колонок базы данных может меняться; • этот атрибут полезен, когда колонка определяется с помощью SELECT утверждения. Если метод %ROWTYPE применяется к отдельными полям (атрибутам), происходит объявление переменной того же типа, что и столбец в таблице, например: dept_record dept%rowtype 2.3.2. Таблицы. Cинтаксис оператора определения таблиц Таблица является базовой структурой реляционной модели. Полное имя таблицы в базе данных состоит из имени схемы, как правило, совпадающем с именем пользователя, и имени таблицы. Оператор определения таблиц имеет следующий синтаксис: CREATE TABLE[имя_схемы.]имя таблицы ({ограничение_целостности_таблицы|имя_столбца тип_данных_столбца [DEFAULT выражение] [ограничение_целостности_столбца...]},...) [{CLUSTER имя_кластера(имя_столбца[,...])| {PCTFREE целое|PCTUSED целое| INITRANS целое|MAXTRANS целое| TABLESPACE имя_табличной_области| STORAGE размер памяти| {RECOVERABLE|UNRECOVERABLE}}...] [PARALLEL возможность_параллельной_обработки] [{ENABLE проверяемые_ограничения_целостности | DISABLE игнорируемые_ограничения_целостности}...] 90 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL [AS запрос] [GACHE|NOCACHE] Ключевое слово DEFAULT указывает на то, что при вводе данных соответствующему столбцу будет присвоено значение, определенное переменной выражение, если в операторе INSERT не указано явно другое значение столбца. Тип данных выражение должен соответствовать типу данных столбца и выражение не должно содержать ссылок на другие выражения. Ключевые слова PCTFREE, PCTUSED, INITRANS, MAXTRANS, TABLESPACE, STORAGE, RECOVERABLE, UNRECOVERABLE характеризуют пространство, распределяют его при работе с таблицей. Ключевое слово PCTFREE определяет процент пространства блока, который резервируется для модификации таблицы. Допустимые значения от 0 до 99. Значение по умолчанию 10, то есть при заполнении каждого блока 10% пространства остается не использованным. Это пространство используется для записи в него данных при выполнении в дальнейшем модификации строк таблицы. Ключевое слово PCTUSED определяет минимальный процент использования пространства блока, при котором в него вводятся данные, по умолчанию 40, то есть если в блоке занято менее 40% пространства, в него вводятся данные при выполнении операции вставки. Сумма значений параметров PCTFREE и PCTUSED не должна превышать 100. Ключевое слово INITRANS определяет начальное число параллельных транзакций, которые могут выполняться для модификации данных блока. Значение по умолчанию 1. Ключевое слово MAXTRANS определяет максимальное число параллельных транзакций, которые могут выполняться для модификации данных блока. В большинстве случаев явное задание этих параметров не требуется. Ключевое слово TABLESPACE определяет имя табличной области, в которой будет размещена таблица. Если значение параметра не определено, то таблица размещается в табличной области, задан- 2.3.2. Таблицы ♦ 91 Иимя табличной области (ключевое слово TABLESPACE) ной по умолчанию для пользователя, который является владельцем схемы, содержащей таблицу. Иимя табличной области (ключевое слово TABLESPACE) Ключевое слово STORAGE определяет объем внешней памяти, выделяемый под таблицу. Для больших таблиц целесообразно явно выделять требуемую память, чтобы уменьшить число запросов на динамическое выделение пространства. Ключевые слова RECOVERABLE и UNRECOVERABLE. Для управления записью в журнальный файл контрольной информаRECOVERABLE, ции используются ключевые слова UNRECOVERABLE. Значение UNRECOVERABLE может быть использовано только с ключевым словом AS подзапрос, при этом операция создания таблицы выполняется быстрее за счет исключения записи управляющей информации в журнал. Но при этом автоматическое восстановление операции создания таблицы в случае сбоя становится невозможным. Ключевое слово CLUSTER указывает привязку столбцов таблицы к кластеру. Обычно столбцы кластера образуют из элементов первичного ключа. Ключевое слово ENABLE указывает на включение ограничений целостности для данной таблицы. Соответствующее ограничение целостности должно быть определено в данном предложении создания таблицы. По умолчанию все ограничения целостности, определенные в предложении, включаются. Ключевое слово DISABLE указывает на выключение ограничений целостности для данной таблицы. Соответствующее ограничение целостности должно быть определено в данном предложении создания таблицы. Ключевое слово AS запрос включает в создаваемую таблицу строки, являющиеся результатом выполнения запроса. Необходима определенная осторожность при использовании вставки строк через подзапрос и определение ограничений целостности в том же предложении. Если результат запроса не соответствует ограничениям це- 92 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL лостности, то Oracle не создает таблицу и возвращает сообщение об ошибке. Ключевое слово CACHE указывает на то, что блоки, выбираемые из таблицы, помечаются в системном кеше, как наиболее используемые. Оно рекомендуется для маленьких таблиц, используемых для преобразования кодов в значения. По умолчанию используется NOCACHE, для которого выбранные блоки помещаются в конец таблицы частот обращений к кешу. Оператором DECLARE можно создать PL/SQL таблицу следующим образом: TYPE type_name IS TABLE OF {column_type|variable%TYPE |table.column%TYPE}[not null] [index by binary_integer]; identifier type_name; Пример 2.3.9 TYPE ename_table_type is table of emp.ename%type index by binary_integer; ename_table ename_table_type; Структура созданной PL/SQL таблицы показана на рис. 2.2. PRIMARY KEY COLUMN 1 2 Jones Smith BINARY_INTEGER SCALAR Рис. 2.2. Структура PL/SQL таблицы Приведем еще пример создания PL/SQL таблицы. Пример 2.3.10 Declare TYPE ename_table_type is table of emp.ename%type 2.3.2. Таблицы ♦ 93 Табличные функции index by binary_integer; TYPE hiredate_table_type is table of date index by binary_integer; ename_table ename_table_type; hiredate_table hiredate_table_type; begin ename_table(1):=‘Cameron’; hiredate_table(8):=sysdate+7; ... end; Следующие функции облегчают работу с таблицами: • EXISTS (N) — возвращает TRUE, если n-ый элемент в таблице существует; • COUNT — возвращает количество элементов в данный момент в PL/SQL таблице; • FIRST and LAST — возвращает первый и последний (самый маленький или самый большой) индексы в PL/SQL таблице; • PRIOR(N) — возвращает значение индекса, предшествующего индексу N в PL/SQL таблице; • NEXT — возвращает значение индекса, следующего за индексом N в PL/SQL таблице; • EXTEND(n,i) — увеличивает размер таблицы, присоединяет n копий i–го элемента PL/SQL таблицы; • TRIM(N) — удаляет N элементов из конца PL/SQL таблицы; • DELETE(N) — удаляет N элементов из PL/SQL таблицы. Табличные функции Например, следующим образом можно определить таблицу, каждый элемент которой является записью: Declare TYPE dept_table_type is table of dept%Rowtype index by binary_integer; dept_table dept_table_type; --Каждый элемент таблицы является записью Пример 2.3.11 Declare type e_table_type is table of emp.ename%type 94 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL index by binary_integer; e_tab e_table_type; В заключение повторим, что составной тип в PL/SQL есть: • PL/SQL запись; • PL/SQL таблица; • PL/SQL таблица записей. При определении составного типа необходимо использовать предопределенный метод %ROWTYPE. Пример 2.3.12 DEPT_RECORD DEPT%ROWTYPE; EMP_RECORD EMP%ROWTYPE; DEPT_RECORD содержит ту же информацию, что и поле dEPt таблицы, аналогично EMP_RECORD содержит ту же информацию, что и записи EMP таблицы. 2.3.3. Структура программы на PL/SQL. Язык PL/SQL является составной частью во многих продуктах Oracle. Сервер Oracle включает поддержку языка PL/SQL, предоставляя пользователю возможность создавать и использовать на сервере процедуры и триггеры базы данных, выполняющие задачи конкретного приложения. Программы, созданные на языке PL/SQL, могут работать совместно в различных частях прикладной системы, построенной на средствах Oracle. Например, в приложении, использующем работу с формами, триггер может вызывать для выполнения некоторого действия хранимую процедуру. Всякая программа на PL/SQL состоит из трех блоков: описаний, исполнительного и блока обработки исключительных ситуаций. Исполнительный блок может быть структурирован с использованием операторных скобок BEGIN и END. Синтаксически программа на PL/SQL оформляется, как представлено на рис. 2.3. 2.3.3. Структура программы на PL/SQL ♦ 95 Типы блоков в PL/SQL DECLARE BEGIN EXCEPTION END; Рис. 2.3. Структура программы на PL/SQL В PL/SQL существует блоки трех типов (рис. 2.4). Безымянный блок [DECLARE] BEGIN --операторы [EXCEPTION] --исключительная ситуация END; PROCEDURE PROCEDURE name IS BEGIN --операторы [EXCEPTION] --исключительная ситуация END; FUNCTION FUNCTION name RETURN datatype IS BEGIN --операторы RETURN value; [EXCEPTION] --исключительная ситуация END; Рис. 2.4. Типы блоков в PL/SQL В блоке DECLARE описываются переменные, константы и определяемые пользователем типы данных. Например, объявление констант происходит следующим образом: Identifier[CONSTANT]datatype[NOT NULL] [:=DEFAULT |expr]; CONSTANT — это ограничение на переменную, которая не меняется в программе, но должна быть инициализирована. Две переменные в разных блоках могут иметь одинаковые имена, перемен- 96 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL ным внутри одного блока не рекомендуется давать те же имена, что и имена столбцов в таблицах в этом блоке. Пример 2.3.13 DECLARE Emp NUMBER(4); BEGIN SELECT emp INTO emp FROM em WHERE ename = ‘Smith’; END; Такое применение переменной EMP разрешено, так как таблица EM определена в другом блоке. Первый оператор BEGIN отмечает начало тела основной программы. В тело программы могут быть вложены другие блоки, ограниченные операторными скобками BEGIN и END. В блоке EXCEPTION определяются фрагменты программного кода для обработки исключительных ситуаций в программе. Последний оператор END указывает конец тела программы. В любые части программы на PL/SQL можно включать комментарии. Текст, который начинается с символов “– –” и продолжается до конца текущей строки, рассматривается как комментарий. Строка, начинающаяся с ключевого слова REM, также рассматривается как комментарий. В блоке программы PL/SQL, ограниченном операторами DECLARE и BEGIN, описываются переменные и константы. Любая переменная или константа должна иметь один из допустимых в Oracle типов. Константа идентифицируется ключевым словом CONSTANT и отличается от переменной тем, что попытка изменить ее значение приводит к сообщению об ошибке. Присваивание значений переменным осуществляется оператором “: =”. Рассмотрим пример простейшей программы, в которой определяются переменные и выполняются действия по вычислению EXP(2) и EXP(3). Команды установки переменных окружения SERVEROUTPUT и ECHO определяют режим вывода на терминал пользователя. 2.3.4. Управление выполнением программы ♦ 97 Поток команд Системная процедура DBMS_OUTPUT.PUT_LINE обеспечивает вывод данных на терминал пользователя, а функция EXP вычисляет экспоненту. Символ “/” указывает на завершение текста процедуры и является командой к интерпретации и выполнению процедуры. Пример 2.3.14 SQL>set serveroutput on; SQL>set echo on; SQL>DECLARE --вход: -------Arg — начальное значение --выход: -------Header1, Header2 — константы для выхода 2 Header1 CONSTANT VARCHAR2(20):='Экспонента двух равна'; 3 Header2 CONSTANT VARCHAR2(20):='Экспонента трех равна'; 4 Arg NUMBER:=2;--здесь задается начальное значение аргумента 5--Исполнительный блок 6 BEGIN 7 DBMS_OUTPUT.PUT_LINE(Headerl || Exp(Arg)); 8 Arg:=Arg+1; 9 DBMS_OUTPUT.PUT_LINE (Header2 || Exp(Arg)); 10 END; 11 / 2.3.4. Управление выполнением программы. Операторы большинства языков программирования, в том числе и языка PL/SQL, выполняются последовательно. Такая схема называется потоком команд. В PL/SQL предусмотрено несколько операторов, с помощью которых можно управлять выполнением программы. Рассмотрим соответствующие программные конструкции. Поток команд Оператор ветвления Применяется одна из следующих форм оператора ветвления: IF — THEN — END IF IF — THEN — ELSE — END IF 98 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL IF — THEN — ELSIF — END IF Оператор IF. . .THEN. . .ELSE позволяет проверить условие и, в зависимости от результатов проверки (TRUE или FALSE), выполнить различные группы операторов. Альтернативная последовательность операторов определяется ключевым словом ELSE. Границы действия оператора IF определяются закрывающей операторной скобкой END IF. Для расширения структуры ветвления дополнительно предусмотрены операторные скобки ELSIF, задающие структуры ветвления более глубокого уровня. Oracle использует следующий синтаксис конструкции ветвления в PL/SQL: IF условие_1 THEN операторы_1; — ветвь 1 ELSIF условие_2 THEN операторы2; — ветвь2 ELSE оператор_n — операторы альтернативы END IF; Обратите внимание, что оператор дополнительного ветвления кодируется ключевым словом ELSIF (а не ELSEIF, как иногда предполагают не очень внимательные пользователи). В предложении IF может быть сколько угодно фраз ELSIF. Рассмотрим пример, иллюстрирующий механизм ветвления в программах на PL/SQL. Программа выводит сообщение о принадлежности к некоторому интервалу. Для ввода данных используется стандартное соглашение PL/SQL: переменная, имя которой предваряется знаком “&”, вводится с терминала пользователя. Пример 2.3.15 SQL>DECLARE --вход: -x — переменная на входе --выход: - Text1,Text2,Text3-строки для вывода 2 x NUMBER;--переменная 3 Text1 VARCHAR2(30):='Переменная>=10'; 4 Text2 VARCHAR2(30):='Переменная в диапазоне 2.3.4. Управление выполнением программы ♦ 99 Оператор цикла от 0 до 10 '; 5 Text3 VARCHAR2(30):='Переменная<=0'; 6 --Исполнительный блок 7 BEGIN 8 x:=&input_Data; 9 DBMS_OUTPUT.PUT_LINE(‘ ‘); 10 IF(x>10) 11 THEN DBMS_OUTPUT.PUT_LINE(Text1); 12 ELSIF(x<0) 13 THEN DBMS_OUTPUT.PUT_LINE(Text2); 14 END IF; 15 END; 16 / Оператор цикла. Организация цикла оформляется в программе на PL/SQL оператором LOOP. В PL/SQL есть три типа оператора цикла: • LOOP; • FOR LOOP; • WHILE LOOP. Цикл LOOP имеет следующий синтаксис: LOOP Операторы ... EXIT [WHEN УСЛОВИЕ]; END LOOP; Последовательность операторов между LOOP и END LOOP многократно повторяется до тех пор, пока условие не примет значение TRUE. Условие может принимать одно из трех значений: TRUE, FALSE, NULL. Этот оператор выполняется, по крайней мере, хотя бы один раз, если будет отсутствовать EXIT, то последовательность операторов будет выполняться бесконечно. Если условие принимает значение TRUE, то будет выполняться следующий за LOOP оператор. 100 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL Цикл FOR LOOP Вторая форма оператора цикла — это цикл с параметром, она имеет вид: FOR counter IN [ REVERSE] lower_bound..upper_bound loop Оператор1; Оператор2; ... END LOOP; REVERSE означает изменение параметра ЦИКЛА от верхней границы до нижней границы, при этом нижняя граница в операторе цикла опять стоит первой. Объявлять параметр цикла counter в операторе DECLARE нет необходимости, он по умолчанию объявляется как целый, lower_bound — нижняя граница изменения параметра цикла, upper_bound — верхняя граница изменения параметра цикла. Например: FOR I IN 2..3 LOOP Оператор1; END LOOP; Последняя форма оператора цикла имеет вид: While условие loop Оператор1; Оператор2; ... END LOOP; Последовательность операторов между LOOP и END LOOP повторяется до тех пор, пока условие имеет значение TRUE. Условие проверяется до выполнения последовательности операторов, если условие принимает значение FALSE, то последовательность операторов перестает выполняться. Этот оператор может ни разу не проработать, если условие перед выполнением оператора имеет значение FALSE. Рассмотрим пример определения числа, факториал которого является наименьшим числом, большим заданной константы (например, 109). 2.3.4. Управление выполнением программы ♦ 101 Цикл FOR LOOP Пример 2.3.16 SQL> DECLARE 2 Arg NUMBER;--Переменная для вычисления факториала 3 I NUMBER;--Переменная-счетчик 4 Limit NUMBER:=1000000000;--Граничное значение 5 Text1 VARCHAR2(80):='Факториал числа, впервые превышающий 1000000000'; 6--Исполнительный блок 7 BEGIN 8 I:=1; 9 Arg:=1; 10 LOOP 11 EXIT WHEN ARG>Limit; 12 I :=I+1; 13 Arg:=Arg*I; 14 END LOOP; 15 DBMS_OUTPUT.PUT_LINE(Text1); 16 DBMS_OUTPUT.PUT_LINE(TO_CHAR(Arg)); 17 DBMS_OUTPUT.PUT_LINE('Искомое число=' || TO_CHAR(I)); 18 END; 19 / 20 — использовали первую форму оператора цикла Модифицируем предыдущий пример, изменив константу и задав условие выхода из цикла ключевым словом WHILE. Пример 2.3.17 SQL> DECLARE 2 Arg NUMBER;--Переменная для вычисления факториала 3 I NUMBER;--Переменная-счетчик 4 Limit NUMBER:=1000000000000;--Граничное значение 5 Text1 VARCHAR2(80):='Факториал числа, впервые превышающий 1000000000000'; 6--Исполнительный блок 7 BEGIN 8 I:=1; 9 Arg:=1; 10 WHILE Arg<Limit LOOP 11 I:=I+1; 102 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL 12 13 14 15 Arg := Arg* I; END LOOP; DBMS_OUTPUT.PUT_LINE(Text1); DBMS_OUTPUT.PUT_LINE(TO_CHAR(Arg)); DBMS_OUTPUT.PUT_LINE('Искомое число=' || TO_CHAR(I)); 17 END; 18 / В результате выполнения программы будут получены следующие результаты: • факториал числа, впервые превышающий 1 000 000 000 000 • 10461394944000 Искомое число = 15 • PL/SQL PROCEDURE SUCCESSFULLY COMPLETED. Цикл, управляемый оператором FOR, используется в том случае, когда точно известно, сколько раз нужно выполнять итерацию цикла. Рассмотрим пример расчета факториала заданного числа. Обратите внимание, что переменную цикла описывать в блоке DECLARE не нужно. Пример 2.3.18 SQL> DECLARE 2 Arg NUMBER:=1;--Переменная для вычисления факториала 3 Limit NUMBER:=20;--Граничное значение 4 Text1 VARCHAR2(30):='Факториал числа 20='; 5 --Исполнительный блок 6 BEGIN 7 FOR I IN 1..Limit LOOP 8 Arg:=Arg*I; 9 END LOOP; 10 DBMS_OUTPUT.PUT_LINE(Text1 || TO_CHAR(Arg)); 11 END; 12 / 2.3.5. Учебная база данных ♦ 103 Описание языка PL/SQL Оператор GOTO Оператор перехода GOTO позволяет осуществить переход по метке, присутствующей в теле программы. С помощью уникального идентификатора, заключенного в двойные угловые скобки, можно пометить любую часть программы PL/SQL для организации безусловного перехода по метке. 2.3.5. Учебная база данных. Описание языка PL/SQL В следующих разделах будем рассматривать описание языка PL/SQL на примере следующей базы данных (табл. 2.1-2.6). Таблица 2.1. Отношение STUDENT (Студент) STUDENT_ID SURNAME NAME STIPEND KURS CITY BIRTHDAY UNIV_ID STUDENT_ID — идентификатор студента, SURNAME — фамилия студента, NAME — имя студента, STIPEND — стипендия, которую получает студент, KURS — курс, на котором учится студент, CITY — город, в котором живет студент, BIRTHDAY — дата рождения студента, UNIV_ID — идентификатор университета, в котором учится студент. Таблица 2.2. Отношение LECTURE (Преподаватель) LECTURE_ID SURNAME NAME CITY UNIV_ID LECTURE_ID — идентификатор преподавателя, SURNAME — фамилия преподавателя, NAME — имя преподавателя, CITY — город, в котором живет преподаватель, UNIV_ID — идентификатор университета, в котором работаетпреподаватель. 104 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL Таблица 3.3. Отношение SUBJECT (Предмет обучения) SUBJ_ID SUBJ_NAME HOUR SEMESTR SUBJ_ID — идентификатор предмета обучения, SUBJ_NAME — наименование предмета обучения, HOUR — количество часов, отводимых на изучение предмета, SEMESTR — семестр, в котором изучается данный предмет. Таблица 3.4. Отношение UNIVERSITY (Университеты) UNIV_ID UNIV_NAME RATING CITY UNIV_ID — идентификатор университета, UNIV_NAME — фамилия студента, RATING — рейтинг университета, CITY — город, в котором расположен университет. Таблица 2.5. Отношение EXAM_MARKS (Экзаменационные оценки) EXAM_ID STUDENT_ID SUBJ_ID MARK EXAM_ID — идентификатор экзамена, STUDENT_ID — идентификатор студента, SUBJ_ID — идентификатор предмета обучения, MARK — экзаменационная оценка, EXAM_DATE — дата экзамена. Таблица 2.6. Отношение SUBJ_LECT (Учебные дисциплины преподавателей) lecture _ID SUBJ_ID LECTURE _ID — идентификатор преподавателя, SUBJ_ID — идентификатор предмета обучения. EXAM_DATE 2.3.6. Курсоры ♦ 105 Явный курсор 2.3.6. Курсоры. Ключевым понятием языка PL/SQL является курсор. Каждое SQL утверждение, выполняемое сервером ORACLE, имеет индивидуальный курсор, связанный с: • неявным курсором, объявленным для всех DML-утверждений; • явным курсором, объявленным и поименованным программистом. Явный курсор – это поименованный запрос, содержащий некоторое фиксированное число строк в выборке. Чаще всего курсор содержит данные одной строки выбираемой таблицы. По существу, курсор является окном, через которое пользователь получает доступ к информации базы данных. Курсоры, в частности, могут использоваться для присваивания конкретных значений переменным программы. Рассмотрим работу явного курсора (рис. 2.5). Объявление курсора происходит следующим утверждением: CURSOR cursor_name IS Select_statement; Рис. 2.5. Работа явного курсора При этом должны выполняться следующие правила: • нельзя включать INTO в предложение курсора; • если требуется использовать последовательность, то необходимо применить ORDER BY в предложении курсора. 106 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL Рассмотрим пример доступа к информации, хранимой в базе данных, с использованием курсоров. Пусть в базе данных хранится таблица LECTURE, сформированная предложениями: CREATE TABLE LECTURE(LECTURE_ID NUMBER, SURNAME VARCHAR2(30), NAME VARCHAR2(10), CITY VARCHAR2(30), UNIV_ID NUMBER); INSERT INTO LECTURE VALUES(1, 'Иванов', 'Иван', 'Воронеж', 100); INSERT INTO LECTURE VALUES(2, 'Петров', 'Петр', 'Москва', 400); INSERT INTO LECTURE VALUES(3, 'Сидоров', 'Юрий', 'Воронеж', 100); Опишем курсор Curl, ориентированный на получение данных из таблицы LECTURE: Declare CURSOR Curl IS SELECT * FROM LECTURE; Первым шагом, необходимым для работы с курсором, является открытие курсора, которое выполняется командой: OPEN Curl; Выборка данных из курсора может быть выполнена в набор переменных подходящих типов, командой FETCH, имеющей следующий синтаксис: Fetch cursor_name into[variable1, variable2,...] |[record_name]; При этом должны соблюдаться следующие правила: • значения текущей строки записываются в переменные; • команда FETCH должна содержать то же самое количество переменных, которое содержит и курсор; • каждая переменная должна соответствовать колонкам; 2.3.6. Курсоры ♦ 107 пример доступа к информации, хранимой в базе данных, с использованием курсоров Например: FETCH Curl INTO Arg1, Arg2, Arg3, Arg4, Arg5; Полностью процедура получения данных из таблицы LECTURE представлена в примере. Пример 2.3.19 SQL> set serveroutput on; SQL> set echo on; SQL> set termout on; SQL> DECLARE 2 Arg1 NUMBER; -- Переменная для первого аргумента 3 Arg2 VARCHAR2(30); -- Переменная для второго аргумента 4 Arg3 VARCHAR2(10); -- Переменная для третьего аргумента 5 Arg4 VARCHAR2(30); -- Переменная для четвертого аргумента 6 Arg5 NUMBER; -- Переменная для пятого аргумента 7 Cursor Curl IS SELECT * FROM LECTURE; -- Определение курсора 8 BEGIN 9 Open Curl; -- Курсор должен быть открыт 10 FOR I IN 1..3 LOOP 11 FETCH Curl INTO Arg1,Arg2, Arg3,Arg4,Arg5; 12 DBMS_OUTPUT.PUT_LINE(TO_CHAR(Arg1) 13 END LOOP; 14 END; 15 / В данной программе неудачно управление счетчиком, поскольку цикл настроен на получение конкретного числа строк, которых может и не быть в таблице. В PL/SQL для курсоров предусмотрены специальные методы %NOTFOUND и %FOUND, принимающие противоположные булевские значения. Метод %NOTFOUND возвращает значение TRUE, если выборка в курсор пустая, то есть не содержит строки. После открытия курсора, но до первой команды FETCH, методы %FOUND, %NOTFOUND принимают неопреде- 108 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL ленное значение (UNKNOWN). Незнание этого факта может привести к достаточно распространенной ошибке. При организации цикла с использованием оператора WHILE и выполнением проверки на истинность %FOUND на входе, цикл не будет выполнен ни разу, несмотря на наличие данных в таблице. Метод %ROWCOUNT возвращает число строк, выбранных после открытия курсора. Бывает полезно использование метода %ISOPEN логического типа, возвращающего TRUE, если курсор открыт: этот метод применяется перед использованием команды FETCH для проверки — открыт ли курсор или нет. С учетом дополнительных объектов и методов PL/SQL рассмотрим новый вариант программы выборки строк таблицы LECTURE c использованием курсоров. Обратите внимание на повторный вывод последней строки. Попытайтесь исправить организацию цикла для устранения повторного вывода. Пример 2.3.20 SQL>set serveroutput on; SQL>set echo on; SQL>set termout on; SQL>DECLARE 2 TYPE Tabl_rec_type IS RECORD -–Определение --нового типа данных 3 (Arg1 LECTURE.LECTURE_ID%TYPE, --Переменная типа --атрибута LECTURE_ID таблицы LECTURE 4 Arg2 LECTURE.SURNAME%TYPE, --Переменная типа --атрибута SURNAME таблицы LECTURE 5 Arg3 LECTURE.NAME%TYPE, --Переменная типа --атрибута NAME таблицы LECTURE 6 Arg4 LECTURE.CITY%TYPE, --Переменная типа --атрибута CITY таблицы LECTURE 7 Arg5 LECTURE.UNIV_ID%TYPE; --Переменная типа --атрибута UNIV_ID таблицы LECTURE 8 Tаb1_гес Tabl_rec_type; --Определение объекта --сконструированного типа 9 Cursor Curl IS SELECT * FROM LECTURE; --Определение курсора 10 BEGIN 2.3.6. Курсоры ♦ 109 пример выборки данных с параметрическим запросом и организацией цикла 11 12 13 14 15 16 17 18 19 Open Curl; --Курсор должен быть открыт FETCH Curl INTO Tabl_rec; LOOP EXIT WHEN (Curl%NOTFOUND); DBMS_OUTPUT.PUT_LINE(Curl%ROWCOUNT || ' ' || Tabl_rec.Arg2 || ' '|| Tabl_rec.Arg3 || ' '|| Tabl_rec.Arg4); FETCH Curl INTO Tabl_rec; END LOOP; END; / Курсор может содержать параметр, синтаксис такого курсора имеет следующий вид: CURSOR cursor_name [(parametr_name datatype,...)] is select_statement; • • параметр добавляется при открытии курсора; каждый раз рекомендуется открывать курсор, когда меняется активное множество элементов. Declare Cursor emp_cursor (p_deptno number, p_job varchar2) is select empno,ename from emp where deptno=p_deptno and job = p_job; begin open emp_cursor(10,’clerk’); Оператор определения курсора может содержать параметрический запрос. Значения параметра задаются при открытии курсора. Рассмотрим пример выборки данных с параметрическим запросом и организацией цикла, исключающей повторный вывод последней строки. 110 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL Пример 2.3.21 SQL> DECLARE 2 TYPE Tabl_rec_type IS RECORD --Определение --нового типа данных 3 (Arg1 LECTURE.LECTURE_ID%TYPE, --Переменная --типа атрибута --LECTURE_ID таблицы LECTURE 4 Arg2 LECTURE.SURNAME%TYPE, --Переменная типа -- атрибута SURNAME таблицы LECTURe 5 Arg3 LECTURE.NAME%TYPE, --Переменная типа --атрибута NAME таблицы LECTURE 6 Arg4 LECTURE.CITY%TYPE, --Переменная типа --атрибута CITY таблицы LECTURE 7 Arg5 LECTURE.UNIV_ID%TYPE); --Переменная типа --атрибута UNIV_ID таблицы LECTURE 8 Tаb1_Rес Tabl_rec_type; --Определение объекта --сконструированногО типа 9 Cursor Cur2(I NUMBER) IS SELECT * FROM LECTURE WHERE CITY=’Воронеж’; --Определение --курсора 10 BEGIN 11 Open Cur2(2); --Курсор должен быть открыт 12 FETCH Cur2 INTO Tab1_rec; 13 WHILE Cur2%FOUND LOOP 14 DBMS_OUTPUT.PUT_LINE(Cur2%ROWCOUNT || ' ' || Tabl_rec.Arg2 || ' ' || Tabl_rec.Arg3 || ' ' || Tabl_rec.Arg4); 15 FETCH Cur2 INTO Tabl_rec; 16 END LOOP; 17 END; 18 / После выбора всех строк из таблицы курсор должен быть закрыт, синтаксис команды: CLOSE cursor_name; Если возникнет необходимость, курсор может быть повторно открыт, однако, после закрытия курсора нельзя пользоваться командой FETCH. 2.3.7. Обработка исключительных ситуаций ♦ 111 Некоторые предопределенные исключительные ситуации PL/SQL Курсоры применяются совместно с командой LOOP, синтаксически это выглядит следующим образом: FOR record_name in cursor_name LOOP If record_name.attribute = 30 then ... end loop; Declare Cursor Curl IS SELECT * FROM LECTURE; BEGIN ... for tab1_rec in Curl loop FETCH Curl INTO Tab1_rec; if tab1_rec.arg1>30 then DBMS_OUTPUT.PUT_LINE(Curl%ROWCOUNT ||' '|| Tab1_rec.Arg2 ||' '||Tab1_rec. Arg3 ||' '||Tab1_rec.Arg4); end loop; end; После инструкции IN можно пользоваться подзапросом для выборки, при этом подзапрос заключается в круглые скобки. 2.3.7. Обработка исключительных ситуаций. Большинство развитых языков программирования обладает встроенными механизмами обработки исключительных ситуаций. Соответствующие языковые средства предусмотрены и в PL/SQL. При возникновении в системе предопределенной или описанной пользователем ситуации происходит автоматическая передача управления в нужный фрагмент блока EXCEPTION программы на PL/SQL, где и происходит предусмотренная обработка возникшей исключительной ситуации. Некоторые предопределенные исключительные ситуации PL/SQL представлены в таблице 2.7. Полный перечень исключительных ситуаций может быть найден в руководстве по языку PL/SQL. 112 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL Таблица 2.7. Некоторые исключительные ситуации Символическое имя предопределенной исключительной ситуации Описание предопределенной исключительной ситуации LOGIN_DENIED Неуспешное подключение к серверу (например, введен неверный пароль) Попытка выполнить действие без подключения к серверу ORACLE Ссылка на недопустимый курсор или недопустимая операция с курсором Не найдены данные, соответствующие оператору SELECT INTO Попытка вставить значение-дубликат в столбец с ограничением на уникальность значения Оператор SELECT INTO возвращает более одной строки в переменную NOT_LOGGED_ON INVALID_CURSOR NO_DATA_FOUND DUP_VAL_ON_INDEX TOO_MANY_ROWS VALUE_ERROR Арифметическая ошибка, ошибка преобразования или усечения TIMEOUT_ON_RESOURCE Блокировка по времени при ожидании ресурса Деление на ноль Неудачная попытка преобразования к типу NUMBER Внутренняя ошибка языка, устанавливается, если PL/SQL недостаточно памяти Внутренняя ошибка PL/SQL Попытка открыть курсор, который уже открыт ZERO_DIVIDE INVALID_NUMBER STORAGE_ERROR PROGRAM_ERROR CURSOR_ALREADY_OPEN Рассмотрим пример программы с обработкой исключительных ситуаций. В тексте программы пропущен оператор открытия курсора, поэтому при обращении к методу %FOUND неоткрытого курсора возникнет исключительная ситуация INVALID_CURSOR. Пример 2.3.22 SQL>DECLARE 2 Arg1 LECTURE.LECTURE_ID%TYPE; 3 Arg2 LECTURE.SURNAME%TYPE; 2.3.7. Обработка исключительных ситуаций ♦ 113 Обработка нестандартных исключительных ситуаций 4 5 6 7 8 9 10 11 12 13 14 15 Arg3 LECTURE.NAME%TYPE; Arg4 LECTURE.CITY%TYPE; Arg5 LECTURE.UNIV_ID%TYPE; Cursor Curl IS SELECT * FROM LECTURE; BEGIN FETCH Curl INTO Arg1,Arg2,Arg3,Arg4,Arg5; WHILE Curl%FOUND LOOP FETCH Curl INTO Arg1,Arg2,Arg3,Arg4,Arg5; END LOOP; EXCEPTION WHEN INVALID_CURSOR THEN DBMS_OUTPUT.PUT_LINE('Ошибка приложения. He открыт курсор'); 16 END; 17 / Для обработки исключительных ситуаций, не входящих в перечень стандартных, можно использовать cпециальный обработчик PL/SQL OTHERS или описать пользовательскую исключительную ситуацию и запрограммировать ее обработку. Ключевое слово OTHERS блока EXCEPTION определяет механизм универсальной обработки исключительных ситуаций, не вошедших в список ситуаций, обрабатываемых явно в блоке EXCEPTION. Введем в текст программы запрещенную операцию деления на ноль и обработаем данную исключительную ситуацию в списке OTHERS. (На самом деле в ORACLE предопределена исключительная ситуация ZERO_DIVIDE, но в данном примере это не важно, а важно то, что ее нет в списке блока EXCEPTION.) Пример 2.3.23 SQL> DECLARE 2 Arg1 LECTURE.LECTURE_ID%TYPE; 3 Arg2 LECTURE SURNAME%TYPE; 4 Arg3 LECTURE.NAME%TYPE; 5 Arg4 LECTURE.CITY%TYPE; 6 Arg5 LECTURE.UNIV_ID%TYPE; 7 Cursor Curl IS SELECT * FROM LECTURE; 8 Arg6 NUMBER:=1; 9 BEGIN Обработка нестандартных исключительных ситуаций 114 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL 10 11 12 13 14 15 16 17 18 19 20 Arg6:=Arg6/0.0; WHILE Curl%FOUND LOOP FETCH Curl INTO Arg1,Arg2,Arg3,Arg4,Arg5; END LOOP; EXCEPTION WHEN INVALID_CURSOR THEN DBMS_OUTPUT.PUT_LINE('Ошибка приложения. He открыт курсор'); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ('Ошибка приложения. He диагностированная ошибка'); END; / Исключительная ситуация, определяемая пользователем, должна быть описана в блоке DECLARE программы. Используется следующий синтаксис описания исключительной ситуации: Имя_исключительной_ситуации EXCEPTION; В программе условие возникновения исключительной ситуации определяется стандартными средствами, обычно операторами IF…THEN. После обнаружения условий возникновения исключительной ситуации она генерируется оператором RAISE, который имеет следующий синтаксис: RAISE Имя_исключительной ситуации; Оператор RAISE генерирует исключительную ситуацию и передает управление на соответствующий обработчик исключительной ситуации, который определен в блоке EXCEPTION. В качестве примера в роли исключительной ситуации рассмотрим превышение значения Arg1 порога, равного 20. Пример 2.3.24 SQL>DECLARE 2 Arg1 LECTURE.LECTURE_ID%TYPE; 3 Arg2 LECTURE.SURNAME%TYPE; 4 Arg3 LECTURE.NAME%TYPE; 5 Arg4 LECTURE.CITY%TYPE; 2.3.7. Обработка исключительных ситуаций ♦ 115 Упражнения 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 Arg5 LECTURE.UNIV_ID%TYPE; Special_case EXCEPTION; --Пользовательская --исключительная ситуация Cursor Curl IS SELECT * FROM LECTURE; BEGIN OPEN Curl; FETCH Curl INTO Arg1,Arg2,Arg3,Arg4,Arg5; WHILE Curl%FOUND LOOP FETCH Curl INTO Argl,Arg2,Arg3,Arg4,Arg5; IF Arg1>20 THEN RAISE Special_case; END IF; END LOOP; EXCEPTION WHEN Special_case THEN DBMS_OUTPUT.PUT_LINE('Пользовательская Исключительная ситуация’); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Oшибка приложения. He диагностированная ошибка'); END; / Упражнения. 2.1. Сделать выборку из таблицы STUDENT с использованием курсора и цикла с методом %FOUND или %NOTFOUND для получения данных о студентах, живущих в Москве. 2.2. Сделать выборку из таблицы SUBJECT с использованием курсора и цикла с методом %FOUND или %NOTFOUND для получения данных о предметах во 2-ом семестре. 2.3. Сделать выборку из таблицы UNIVERSITY с использованием курсора и цикла с методом %FOUND или %NOTFOUND для получения данных об университетах с рейтингом большим 200. 2.4. Сделать выборку из таблицы EXAM_MARKS с использованием курсора и цикла с методом %FOUND или %NOTFOUND для получения сведений об экзаменах, сданных в определенную дату. 116 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL 2.5. Сделать выборку из таблицы SUBJ_LECT с использованием курсора и цикла с методом %FOUND или %NOTFOUND для получения данных о преподавателях, читающих предмет с данным номером. 2.6. Сделать выборку из таблицы STUDENT с использованием курсора и цикла с методом %FOUND или %NOTFOUND для получения данных о студентах, живущих в Москве, и использовать пользовательскую исключительную ситуацию для исключения среди выбранных студентов тех, у которых стипендия меньше 200. 2.7. Сделать выборку из таблицы SUBJECT с использованием курсора и цикла с методом %FOUND или %NOTFOUND для получения данных о предметах во 2-ом семестре с использованием пользовательской исключительной ситуации для исключения из полученного списка предметов с количеством часов 72. 2.8. Сделать выборку из таблицы UNIVERSITY с использованием курсора и цикла с методом %FOUND или %NOTFOUND для получения данных об университетах с рейтингом большим 200 и исключить с помощью пользовательской исключительной ситуации данные об университетах, расположенных в Воронеже. 2.9. Сделать выборку из таблицы EXAM_MARKS с использованием курсора и цикла с методом %FOUND или %NOTFOUND для получения сведений об экзаменах, сданных в определенную дату, и исключить с помощью пользовательской исключительной ситуации данные об оценках, полученных по заданному номеру предмета. 2.10. Сделать выборку из таблицы SUBJ_LECT с использованием курсора и цикла с методом %FOUND или %NOTFOUND для получения данных о преподавателях, читающих предмет с данным номером, и исключить из полученного множества данные с помощью пользовательской исключительной ситуации о преподавателях с заданной фамилией. 2.3.8. Создание пользовательских процедур и функций ♦ 117 Хранимые процедуры и функции 2.3.8. Создание пользовательских процедур и функций. Подпрограммы (процедуры и функции) в PL/SQL бывают хранимые и локальные. Хранимые подпрограммы во многом отличаются от локальных. Если подпрограмма должна будет вызываться из многих блоков, то ее делают хранимой, она хранится в базе данных. Короткие процедуры и функции рекомендуется объявлять локально в блоке, если они вызываются только из одного конкретного фрагмента программы. Хранимые подпрограммы (процедуры и функции) хранятся в базе данных в откомпилированном виде и могут вызываться из любого блока. В этом разделе будем рассматривать хранимые подпрограммы. Хранимые процедуры и функции – это объекты базы данных и, следовательно, они создаются командой CREATE и уничтожаются командой DROP. При создании процедуры и функции должны быть определены: имя объекта, перечень и тип параметров и логика работы процедуры или функции, описанные на языке PL/SQL Чтобы создать процедуру или функцию, необходимо иметь системные привилегии CREATE PROCEDURE. Для cоздания процедуры, функции или пакета в схеме, отличной от текущей схемы пользователя, требуются системные привилегии CREATE ANY PROCEDURE. После определения имени новой процедуры или функции необходимо задать ее имена, типы и виды параметров. Для каждого параметра должен быть указан один из видов параметра — IN, OUT или IN OUT. Вид параметра IN предполагает, что значение параметра должно быть определено при обращении к процедуре и не изменяется процедурой. Попытка изменить в теле процедуры параметр вида IN приведет к сообщению об ошибке. Вид параметра OUT предполагает изменение значения параметра в процессе работы процедуры, то есть параметр вида ОUТ — это возвращаемый параметр. Параметр IN OUT — это параметр, которому при вызове должно быть присвоено значение, которое может быть изменено в теле процедуры. Па- 118 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL раметры процедур или функций имеют виды, присвоенные по умолчанию. Дополнительно к определениям, необходимым для процедуры, в определении функции должен быть указан тип данных единственного возвращаемого функцией значения. Возврат значения функции выполняется командой PL/SQL RETURN. Оператор определения процедуры ORACLE использует следующий синтаксис: CREATE[OR REPLACE]PROCEDURE [имя_схемы.]имя_процедуры [(имя_параметра[{IN | OUT | IN OUT}] тип_данных [,имя_параметра[{IN | OUT | IN OUT}] тип_данных...])] {IS | AS} npoгpaммa_нa_PL/SQL Ключевое слово OR REPLACE указывает на безусловное замещение старого текста процедуры. Если ключевое слово OR REPLACE не указано, и процедура определена, то замещения старого значения кода процедуры не происходит, и возвращается сообщение об ошибке. В описании переменных процедуры не используется ключевое слово DECLARE. Блок определения данных начинается сразу после ключевого слова AS (или IS, по выбору пользователя). Рассмотрим пример создания процедуры, которая заносит в таблицу значения, зависящие от числового параметра. Пусть таблица сформирована предложением: CREATE TABLE SUBJ_LECT(LECTURE_ID NUMBER, SUBJ_ID NUMBER); Протокол создания процедуры представлен в примере 2.3.25. Пример 2.3.25 SQL>CREATE OR REPLACE PROCEDURE InsRec 2 (Arg1 IN NUMBER,Arg2 IN NUMBER) 3 AS 4 Coeff CONSTANT NUMBER:=0.5; 5 BEGIN 6 INSERT INTO SUBJ_LECT 2.3.8. Создание пользовательских процедур и функций ♦ 119 Пример обнаружения и исправления ошибки 7 8 END; / VALUES(Coeff*Arg1,Coeff*Arg2); Исполнение созданной процедуры INSREC может быть выполнено оператором ЕХЕС языка PL/SQL. Последующая выборка из таблицы SUBJ_LECT иллюстрирует изменения в базе данных, осуществленные вызовом процедуры INSREC. SQL> ЕХЕС InsRec (240,120); Чтобы уточнить выявленные в процессе синтаксического анализа ошибки, можно воспользоваться командой PL/SQL SHOW ERRORS. Эта команда показывает ошибки, обнаруженные в процессе выполнения CREATE PROCEDURE, CREATE FUNCTION, CREATE PACKAGE, CREATE PACKAGE BODY И CREATE TRIGGER. Если команда SHOW ERRORS используется без параметров, то возвращаются ошибки последней компилированной процедуры, функции, пакета, тела пакета или триггера. Рассмотрим пример обнаружения и исправления ошибки. В процедуре, представленной выше, добавим ошибочный оператор, изменяющий значение параметра вида IN, который не должен изменяться. Пример 2.3.26 Пример обнаружения и исправления ошибки SQL>CREATE OR REPLACE PROCEDURE InsRec 2 (Arg1 IN NUMBER, Arg2 IN NUMBER) 3 AS 4 Coeff CONSTANT NUMBER:=0.5; 5 BEGIN 6 Arg1:=Arg1+200; 7 NSERT INTO SUBJ_LECT VALUES(Coeff*Arg1, Coeff*Arg2); 8 END; 9 / Протокол выполнения: SQL>show errors Errors for PROCEDURE INSREC: 120 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL LINE/COL ERROR 6/1 PLS-00363: expression 'ARG1' cannot be used as an assignment target 6/1 PL/SQL: Statement ignored Напомним, что функции PL/SQL отличаются от процедур тем, что возвращают в вызывающую среду значение параметра. Оператор определения функции ORACLE использует следующий синтаксис: CREATE [OR REPLACE] FUNCTION [имя_схемы.]имя_функции [(имя_параметра[{IN | OUT | IN OUT}] тип_данных [,имя_параметра[{IN | OUT | IN OUT}] тип_данных...])] RETURN тип_данных {IS | AS} npoгpaммa_na_PL/SQL Описание типа данных для возвращаемого функцией значения требуется обязательно. При описании переменных функции так же, как и при описании переменных процедуры, не используется ключевое слово DECLARE. Блок определения данных начинается сразу после ключевого слова IS (или AS, по выбору пользователя). Рассмотрим пример создания функции, которая вычисляет сумму значений атрибутов, таких, что один из атрибутов попадает в заданный параметрами функции интервал. Пусть таблица сформирована предложением как, в примере 2.3.27. Пример 2.3.27 SQL>CREATE OR REPLACE FUNCTION SumRecInt 2 (Arg1 IN NUMBER,Arg2 IN NUMBER) 3 RETURN NUMBER 4 AS 5 Sum_Var NUMBER:=0.0; 6 BEGIN 8 SELECT Sum(LECTURE_ID) INTO Sum_Var FROM SUBJ_LECT WHERE SUBJ_ID BETWEEN Arg1 AND Arg2; 8 RETURN Sum_Var; 2.3.8. Создание пользовательских процедур и функций ♦ 121 Упражнения 2.11–2.20 9 END; 10 / Получим: FUNCTION CREATED Если характер использования приложений изменился, то для освобождения ресурсов базы данных может потребоваться уничтожить процедуру или функцию. В собственной схеме пользователю не требуются дополнительные привилегии для уничтожения процедуры или функции. Для уничтожения процедуры или функции в схеме другого пользователя необходимо наличие привилегии DROP ANY PROCEDURE. Для уничтожения процедуры ORACLE использует следующий синтаксис: DROP PROCEDURE [имя_схемы.]имя_процедуры Рассмотрим пример уничтожения функции Oracle. SQL>DROP FUNCTION SumRecInt Function dropped; Упражнения Упражнения 2.11—2.20 2.11. Описать процедуру, которая заносит данные в таблицу STUDENT в зависимости от параметров процедуры, вызвать эту процедуру. 2.12. Описать процедуру, которая заносит данные в таблицы STUDENT и EXAM_MARKS с соблюдением ссылочной целостности, в зависимости от параметров процедуры, вызвать эту процедуру. 2.13. Описать процедуру, которая заносит данные в таблицы STUDENT и SUBJECT с соблюдением ссылочной целостности, в зависимости от параметров процедуры, вызвать эту процедуру. 2.14. Описать процедуру, которая заносит данные в таблицы STUDENT и UNIVERSITY с соблюдением ссылочной цело- 122 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL 2.15. 2.16. 2.17. 2.18. 2.19. 2.20. стности, в зависимости от параметров процедуры, вызвать эту процедуру. Описать процедуру, которая заносит данные в таблицу LECTURE в зависимости от параметров процедуры, вызвать эту процедуру. Описать и вызвать функцию, которая вычисляет сумму баллов для студентов, номера которых находятся в заданном интервале в таблице EXAM_MARKS. Описать и вызвать функцию, которая вычисляет для студентов, номера которых находятся в данном диапазоне, максимальный балл по заданному предмету (с некоторым номером) в таблице EXAM_MARKS. Описать и вызвать функцию, которая определяет для студентов с заданной фамилией сумму баллов по заданному предмету в таблице EXAM_MARKS. Описать и вызвать функцию, которая вычисляет для студентов, номера которых находятся в данном диапазоне, максимальный балл по заданному названию предмета. Описать и вызвать функцию, которая вычисляет для студентов, номера которых находятся в данном диапазоне, средний балл по заданному названию предмета. 2.3.9. Пакеты PL/SQL. Модуль — это конструкция PL/SQL, которая позволяет хранить связанные объекты в одном месте. Модули бывают только хранимыми и никогда локальными. Модуль — это именованный раздел объявлений. Все, что может входит в раздел объявлений блока, может входить и в модуль: типы, переменные, процедуры, функции, курсоры. Размещение их в модуле полезно, так как это позволит ссылаться на них из других блоков PL/SQL, в модулях можно описывать и глобальные переменные для PL/SQL. Процедуры, функции и глобальные переменные, объединенные общим функциональным замыслом, часто оформляют в виде единого объекта базы данных — пакета. Особенностью пакетов PL/SQL является раздельная компиляция и хранение интер- 2.3.9. Пакеты PL/SQL ♦ 123 Поддержка перегружаемых функций и процедур фейсной и исполнительной частей пакета. Пакет как объект состоит из двух частей: спецификации пакета и тела пакета. В спецификации пакета хранится описание процедур, функций, глобальных переменных, констант и курсоров, которые доступны для внешних приложений. В теле пакета определяются все процедуры, функции и переменные, включая те, которые не были определены в спецификации пакета. Процедуры, функции и переменные, определенные в теле пакета, но не описанные в его спецификации, являются локальными. Внешние по отношению к пакету приложения не имеют права на использование локальных объектов пакета. Локальные объекты предназначены исключительно для использования только процедурами и функциями самого пакета. Особенностью пакетов PL/SQL является поддержка перегружаемых функций и процедур. Процедуры или функции могут иметь одинаковое имя, но различный по типу или количеству набор аргументов. В момент обращения к конкретной процедуре или функции по числу и типу передаваемых аргументов автоматически определяется требуемая процедура или функция, которая и исполняется. Поддержка перегружаемых процедур, в частности, используется в стандартном пакете DBMS_OUTPUT для единой формы обращения к процедуре PUT_LINE для вывода данных различных типов. Поддержка перегружаемых функций и процедур Напомним, что для создания пакета пользователь должен иметь привилегию CREATE PROCEDURE. Создание пакета в схеме другого пользователя требует наличия привилегии CREATE ANY PROCEDURE. Оператор определения интерфейсной части (спецификации) пакета ORACLE использует следующий синтаксис: CREATE [OR REPLACE] PACKAGE [имя_схемы.]имя_пакета {IS | AS} спецификация_пакета_на_PL/SQL Ключевое слово OR REPLACE указывает на безусловное замещение старого текста спецификации пакета. Если ключевое слово OR REPLACE не указано, и пакет определен в системе, то замещения 124 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL старого значения спецификации пакета не происходит, и возвращается сообщение об ошибке. Спецификация пакета начинается с описания констант и переменных. При описании переменных пакета ключевое слово DECLARE не используется. Рассмотрим пример создания спецификации пакета, которая состоит из описания константы, функции и процедуры. Пример 2.3.28 SQL>CREATE OR REPLACE PACKAGE PAC 2 AS 3 PAC_CONST CONSTANT NUMBER:=20; 4 FUNCTION MUL(Arg1 NUMBER, Arg2 NUMBER) 5 RETURN NUMBER; 6 PROCEDURE AUDIT; 7 END; 8 / Оператор определения исполнительной части (тела) пакета ORACLE использует следующий синтаксис: CREATE [OR REPLACE] PACKAGE BODY [имя_схемы.]имя_пакета {IS | AS} cneцификация_naкema_нa_PL/SQL Ключевое слово OR REPLACE указывает на безусловное замещение старого текста тела пакета. Если ключевое слово OR REPLACE не указано, и пакет определен в системе, то замещения старого значения тела пакета не происходит, и возвращается сообщение об ошибке. Определение тела пакета начинается с описания констант и переменных. Константы и переменные, описанные в спецификации пакета, являются глобальными и в теле пакета повторно не описываются. При описании констант и переменных пакета ключевое слово DECLARE не используется. Пример создания тела пакета Рассмотрим пример создания тела пакета, спецификация которого приведена выше. Пусть функция пакета MUL выполняет умножение аргументов на константу пакета, а процедура AUDIT фик- 2.3.9. Пакеты PL/SQL ♦ 125 Пример создания тела пакета сирует факт обращения к функции MUL записью в таблицу значения счетчика обращений и текущей даты. Предполагается, что таблица TABAUD с соответствующими типами данных атрибутов к моменту создания тела пакета создана. Протокол создания тела пакета приведен ниже. При описании функций и процедур пакета в отличие от описаний одиночных функций и процедур оператор CREATE не используется. Пример 2.3.29 SQL>CREATE OR REPLACE PACKAGE BODY PAC 2 AS 3 PAC_COUNT NUMBER:=0; 4 FUNCTION MUL(Arg1 NUMBER, Arg2 NUMBER) 5 RETURN NUMBER IS 6 BEGIN 7 AUDIT; 8 RETURN Arg1* PAC_CONST+Arg2*PAC_CONST; 9 END; 10 PROCEDURE AUDIT IS 11 BEGIN 12 PAC_COUNT:=PAC_COUNT+1; 13 INSERT INTO TabAUD VALUES (PAC_COUNT, SYSDATE); 14 COMMIT; 15 END; 16 END; 17 / Package body created. Константа или переменная, описанная в спецификации пакета, может быть доступна из пользовательской программы (конечно, если процедуре или функции такой доступ разрешен). Чтобы обратиться к глобальной переменной или константе пакета, нужно указать в качестве префикса имя пакета. Ниже приведен пример, иллюстрирующий возможность доступа к глобальной константе пакета и невозможность доступа к частной переменной пакета. 126 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL SQL>EXEC DBMS_OUTPUT.PUT_LINE(PAC.PAC_CONST); 20.0 PL/SQL procedure successfully completed. SQL>EXEC DBMS_OUTPUT.PUT_LINE(PAC.PAC_COUNT); begin dbms_output.put_line(pac.pac_count); end; ERROR at line 1; ORA-06550: line I, column 34: PLS-00302: component 'PAC_COUNT' must be declared ORA-06550: line I, column 7: PL/SQL: Statement ignored Чтобы вызвать процедуру или функцию пакета, в вызове нужно указать в качестве префикса имя пакета. В заключение раздела рассмотрим пример использования функции созданного пакета. SQL>EXEC DBMS_OUTPUT.PUT_LINE(PAC.MUL(lll,222)); PL/SQL procedure successfully completed. При использовании переменных пакета инициализация локальных переменных пакета происходит при запуске сервера Oracle. В данном случае, после останова и повторного запуска сервера, счетчик обращений PAC_COUNT будет установлен в нулевое состояние. Если по смыслу решаемой задачи требуется независимое от остановов сервера приращение счетчика, можно воспользоваться таким объектом, как последовательность. Для освобождения ресурсов сервера может потребоваться уничтожить пакет. В собственной схеме пользователю не требуются дополнительные привилегии для уничтожения пакета. Для уничтожения пакета в схеме другого пользователя необходима привилегия DROP ANY PROCEDURE. Для уничтожения спецификации пакета и тела пакета Oracle использует следующий синтаксис: DROP PACKAGE [BODY] [имя_схемы.]имя_пакета 2.3.9. Пакеты PL/SQL ♦ 127 Упражнения 2.21–2.26 Необязательное ключевое слово BODY указывает, что уничтожается только тело пакета. Если ключевое слово BODY опущено, то удаляется и спецификация, и тело пакета. Параметр имя_пакета задает имя уничтожаемого пакета. Пример уничтожения пакета рассматривается ниже: SQL > DROP PACKAGE PAC; Package dropped Упражнения Упражнения 2.21—2.26 2.21. Создать пакет, состоящий из функции с параметрами, процедуры без параметров. Функция подсчитывает количество студентов, получающих стипендию, заданную параметром. Процедура подсчитывает число обращений к функции и заносит это число, размер стипендии, количество студентов, получающих ее, в новую таблицу, созданную заранее. 2.22. Создать пакет, состоящий из функции с параметрами, процедуры без параметров. Функция подсчитывает количество студентов, живущих в городе, заданном параметром. Процедура подсчитывает количество обращений к функции и заносит это количество, название города, количество студентов, живущих в этом городе, в новую таблицу, созданную заранее. 2.23. Создать пакет, состоящий из функции с параметрами, процедуры без параметров. Функция подсчитывает количество предметов, по которым получена оценка, заданная параметром, более чем у 20 человек. Процедура подсчитывает число обращений к функции и заносит это число, оценку и количество предметов в новую таблицу, созданную заранее. 2.24. Создать пакет, состоящий из функции с параметрами, процедуры без параметров. Функция подсчитывает количество университетов с рейтингом, заданным параметром. Процедура подсчитывает количество обращений к функции и заносит это количество, величину рейтинга, количество университетов с этим рейтингом в новую таблицу, созданную заранее. 2.25. Создать пакет, состоящий из функции с параметрами, процедуры без параметров. Функция подсчитывает количество пре- 128 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL подавателей, работающих в университете, заданным параметром. Процедура подсчитывает количество обращений к функции и заносит это количество, номер университета, количество преподавателей в новую таблицу, созданную заранее. 2.26. Создать пакет, состоящий из функции с параметрами, процедуры без параметров. Функция подсчитывает количество предметов, прочитанных в семестре, номер которого задан параметром, с количеством часов, заданным другим параметром. Процедура подсчитывает число обращений к функции и заносит это число, номер семестра, количество часов и количество предметов в новую таблицу, созданную заранее. 2.3.10. Триггеры базы данных Триггер базы данных – это процедура PL/SQL, которая автоматически запускается при возникновении определенных событий, связанных с выполнением операций вставки, удаления или модификации данных таблицы. Событие, управляющее запуском триггера, описывается в виде логических условий. Когда возникает событие, соответствующее условиям триггера, сервер ORACLE автоматически запускает триггер, то есть интерпретирует код программы триггера, записанный на языке PL/SQL. Обычно триггеры используют для выполнения сложных проверок ограничений целостности, многоаспектных проверок выполнения правил разграничения доступа и т.п. Триггер запускается при выполнении одной из трех операций изменения содержимого таблицы: INSERT, DELETE или UPDATE. Триггер может запускаться и несколькими операторами, но хотя бы один оператор из тройки должен быть обязательно указан в условии запуска триггера. Если перечень операторов, запускающих триггер, включает оператор UPDATE, то для условий срабатывания могут быть указаны конкретные изменяемые столбцы. Код триггера может выполняться либо до, либо после тех операторов, которые инициировали запуск триггера. Например, если триггер запускается для проверки полномочий пользователя на 2.3.10. Триггеры базы данных ♦ 129 Операторные триггеры и строчные триггеры право выполнения операции, то, конечно, нужно использовать триггер с запуском до выполнения операции (с ключевым словом BEFORE). Если триггер применяется для формирования данных для аудиторской записи, то разумно использовать триггер с запуском после выполнения операции (с ключевым словом AFTER). Код триггера может быть ассоциирован либо с операцией над таблицей в целом, либо с каждой строкой, над которой выполняется операция. В зависимости от этого триггеры подразделяют на операторные триггеры и строчные триггеры. Операторные триггеры обычно используют для проверки правил разграничения доступа, оперирующих таблицей в целом, а строчные триггеры часто используют для проверки ограничений целостности при вставке строк. Условие запуска строчного триггера может быть уточнено дополнительным логическим условием. Чтобы создать триггер, необходимо иметь системные привилегии CREATE TRIGGER. Для создания триггера в схеме, отличной от текущей схемы пользователя, требуются системные привилегии CREATE ANY TRIGGER. Оператор определения триггера ORACLE использует следующий синтаксис: Операторные триггеры и строчные триггеры CREATE[OR REPLACE] TRIGGER[имя схемы.]имя_триггера {BEFORE | AFTER} {INSERT | DELETE | UPDATE[OF имя_столбца[,имя_столбца...]]} [OR {INSERT | DELETE | UPDATE[OF имя_столбца[,имя_столбца...]]}...] ON [имя_схемы.]{имя_таблицы | имя_представления} [FOR EACH ROW] [WHEN условие] cneцификации_naкema_нa_PL/SQL Ключевое слово OR REPLACE указывает на безусловное замещение старого текста триггера. Если ключевое слово OR REPLACE не указано, и триггер определен в системе, то замещения старого значения триггера не происходит, и возвращается сообщение об ошибке. 130 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL Ключевые слова BEFORE или AFTER указывают на выполнение кода триггера либо до, либо, соответственно, после операторов манипулирования данными, инициировавших запуск триггера. Ключевые слова INSERT, DELETE или UPDATE определяют конкретный оператор, запускающий триггер. Для оператора UPDATE могут быть указаны столбцы, изменение которых запускает триггер. Если конкретные столбцы не указаны, то триггер запускает изменение любого столбца. Необязательное ключевое слово OR присоединяет дополнительный оператор, запускающий триггер. Ключевое слово ON задает имя таблицы или представления, ассоциированного с триггером. Необязательное ключевое слово FOR EACH ROW определяет триггер как строчный. Необязательное ключевое слово WHEN задает дополнительное логическое условие, сужающее область действия триггера. Прежде чем перейти к примеру, построения триггера, приведем некоторые дополнительные сведения об обработке исключительных ситуаций в ORACLE. Процедура RAISE_APPLICATION_ERROR применяется для подключения к механизму обработки ошибок пользовательских точек входа. С ее помощью можно обработать до 1000 определяемых пользователем ошибок с номерами в диапазоне от -20000 до -20999. Вызов процедуры RAISE_APPLICATION_ERROR приводит к генерации исключительной ситуации и завершению выполнения вызвавшей процедуру программы (сравните с рассмотренным выше оператором PL/SQL RAISE). При этом в среду, вызвавшую программу, возвращается номер и текстовое сообщение о типе ошибки. Рассмотрим пример триггера, который выполняется, если значение вводимого атрибута “уклоняется по модулю” от среднего значения для текущего состояния таблицы больше, чем на 30. Пусть таблица Tab1 сформирована предложениями: CREATE TABLE Таb1(At1 NUMBER); INSERT INTO Таb1 VALUES(10); 2.3.10. Триггеры базы данных ♦ 131 Протокол создания триггера INSERT INTO Таb1 VALUES(30); INSERT INTO Таb1 VALUES(50); Протокол создания триггера представлен ниже. При срабатывании триггера предусмотрена генерация стандартной обработки ошибки, которой присваивается номер -20002 с соответствующим диагностирующим сообщением. Обратите внимание на предопределенную переменную:new.At1, содержащую (по ее смыслу) вводимое значение атрибута At1. Пример 2.3.30 SQL>CREATE OR REPLACE TRIGGER TRIG_TBI 2 BEFORE INSERT ON Таb1 3 FOR EACH ROW 4 DECLARE 5 StatAvg NUMBER; 6 StatN NUMBER; 7 BEGIN 8 SELECT COUNT(At1),SUM(At1) INTO StatN, StatAvg 9 FROM Tab1; 10 IF (ABS(StatAvg-StatN*(:new.At1))>30*StatN) 11 THEN RAISE_APPLICATION_ERROR(-20002, 'Слишком большое уклонение'); 12 END IF; 13 END; 14 / Trigger created. Работу механизма триггера проиллюстрируем на примере. При вводе значения, достаточно близкого к среднему (в данном случае 40), триггер не запускается, и “ничего не происходит”. При вводе значения атрибута, равного 90, соответствующая статистика указывает на большое уклонение, происходит срабатывание триггера, и новая строка не включается. Операция выборки подтверждает ожидаемое изменение в таблице. SQL>insert into tab1 values(40); I row created. SQL>insert into tab1 values(90); insert into tab1 values(90) 132 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL ERROR at line 1: ORA-20002: Слишком большое уклонение ORA-06512: at “SYSTEM. TRIG_TBI”, line 9 ORA-04088: error during execution of trigger 'SYSTEM .TRIG_TBI' SQL>select * from tab1; Следующий пример иллюстрирует возможность обработки исключительной ситуации средствами пользовательской исключительной ситуации. В данном случае создается триггер, который при превышении заданного порога уклонения вводимого значения атрибута выводит диагностическое сообщение. При этом данные в таблицу вводятся. Пример 2.3.31 SQL>CREATE OR REPLACE TRIGGER TRIG_TB2 2 BEFORE INSERT ON Таb1 3 FOR EACH ROW 4 DECLARE 5 StatAvg NUMBER; 6 StatN NUMBER; 7 Special_case EXCEPTION; --Пользовательская --исключительная ситуация 8 BEGIN 9 SELECT COUNT(At1),SUM(At1) INTO StatN, StatAvg 10 FROM Tab1; 11 IF (ABS(StatAvg – StatN*(:new.At1))>30) 12 THEN RAISE Special_case; 13 END IF; 14 EXCEPTION 15 WHEN Special_case THEN 16 DBMS_OUTPUT.PUT_LINE('Слишком большое уклонение'); 17 WHEN OTHERS THEN 18 DBMS_OUTPUT.PUT_LINE('He диагностированная ошибка триггера'); 19 END; 20 / Trigger created. 2.3.10. Триггеры базы данных ♦ 133 Ограничения использования предложений языка SQL в коде триггера Oracle При вводе значения атрибута, равного 90, происходит срабатывание триггера TRIG_TB2. Выводится диагностическое сообщение, и вводится новая строка. Представленная операция выборки подтверждает ожидаемое изменение в таблице. SQL> insert into tabl values(90); Слишком большое уклонение В отличие от процедур, функций и пакетов сервер ORACLE не хранит код триггера в виде скомпилированного блока PL/SQL. При первом запуске триггера его код считывается из словаря данных, компилируется, и скомпилированная версия сохраняется в области SGA. Поэтому для часто используемых триггеров целесообразно код, отвечающий за процедурную часть триггера, включать в хранимую процедуру, а в теле триггера оставлять только запись условий запуска и вызовы соответствующих процедур и функций. На предложения языка SQL, включенные в код триггера ORACLE, наложены следующие ограничения. Тело триггеpa не может включать в себя явное использование управляющих операторов COMMIT, ROLLBACK и SAVEPOINT, операторов языка определения данных CREATE, ALTER и DROP, операторов, управляющих разграничением доступа GRANT и REVOKE, а также неявное выполнение перечисленных операторов через вызовы процедур и функций. Строчный триггер срабатывает один раз для каждой строки. Внутри триггера можно обращаться к строке, обрабатываемой в данный момент. Для этого служат две псевдозаписи — :OLD и :NEW, синтаксически они рассматриваются как записи, хотя записями не являются, поэтому их называют псевдозаписями. Тип обеих псевдозаписей определяется как Ограничения использования предложений языка SQL в коде триггера Oracle Активирующая_таблица%ROWTYPE; Псевдозапись :OLD не определена для операторов INSERT, а псевдозапись :NEW — для оператора DELETE, при этом генерироваться ошибка не будет, но значения полей обеих записей будут NULL значениями. Двоеточие перед :NEW и :OLD обязательно, 134 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.3. Язык PL/SQL это двоеточие используется для ограничения переменных привязки. Операции, которые выполняются над записями, не могут быть выполнены псевдозаписями. :OLD и :NEW нельзя передавать процедурам и функциям, принимающим аргументы типа Активирующая_таблица%ROWTYPE. Упражнения 2.27. Создать триггер, который считает среднюю стипендию и выдает диагностическое сообщение при превышении заданного порога уклонения вводимого значения атрибута в зависимости от средней стипендии, при этом происходит заполнение некоторой таблицы. 2.28. Создать триггер, который считает средний балл в заданный день и выдает диагностическое сообщение при превышении заданного порога уклонения вводимого значения атрибута в зависимости от среднего балла, при этом происходит заполнение некоторой таблицы. 2.29. Создать триггер, который определяет границы изменения номеров предметов и выдает диагностическое сообщение при превышении заданного порога уклонения вводимого значения атрибута, при этом происходит заполнение таблицы. 2.30. Создать триггер, который определяет границы изменения номеров преподавателей и выдает диагностическое сообщение при превышении заданного порога уклонения вводимого значения атрибута, при этом происходит заполнение некоторой таблицы. 2.31. Создать триггер, который вычисляет средний рейтинг университетов и выдает диагностическое сообщение при превышении заданного порога уклонения вводимого значения атрибута в зависимости от величины среднего рейтинга, при этом происходит заполнение некоторой таблицы. 2.32. Создать триггер, который определяет границы изменения номеров лекторов в зависимости от номеров читаемых курсов и выдает диагностическое сообщение при превышении задан- 2.4. Связь с удаленной базой данных ♦ 135 Пример связи с удаленной базой данных ного порога уклонения вводимого значения атрибута, при этом происходит заполнение некоторой таблицы. 2.4. Связь с удаленной базой данных. Для создания связи пользователю в локальной базе данных необходимо иметь некоторую точку входа в удаленной базе данных. Данная точка входа может совпадать с именем пользователя, который создает связь, а может иметь и другое имя. Для создания общей (PUBLIC) связи необходимо пользователю обладать привилегией CREATE PUBLIC DATABASE LINK. Оператор создания связи с удаленной базой данных имеет следующий синтаксис: CREATE [PUBLIC] database link имя_связиБД [CONNECT to имя_пользователя IDENTIFIED BY пароль_пользователя] USING 'строка_связи' Если параметр PUBLIC отсутствует, то создается связь, доступная только создавшему ее пользователю. При наличии этого параметра создается связь, доступная всем пользователям. Параметр ИМЯ_СВЯЗИБД задает имя создаваемой связи. Параметры ИМЯ_ПОЛЬЗОВАТЕЛЯ, ПАРОЛЬ_ПОЛЬЗОВАТЕЛЯ задают имя пользователя и его пароль в удаленной базе данных. Строка 'СТРОКА_СВЯЗИ' определяет имя раздела параметров SQL*NET, задающего спецификации связи с удаленной базой данных. Если фраза, содержащая имя пользователя и пароль, отсутствует, будем пользоваться текущим именем пользователя и его паролем. Создав связь с удаленной базой данных, можно обращаться к таблицам в удаленной базе данных в запросах, при этом необходимо после имени таблицы в удаленной базе данных добавить @ИМЯ_СВЯЗИ во фразе FROM оператора SELECT. Пример 2.4.1 Пример связи с удаленной базой данных Пусть определяется связь с удаленной базой данных T1_ora_link, которая связывает пользователя Т1 с паролем Т1_ora в базе данных, 136 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.4. Связь с удаленной базой данных. определяемой строкой связи SUN. После создания связи можно выполнить любой запрос: SQL>CREATE database link T1_ora_link connect to t1 identified by t1_ora using ‘sun’; dtabase link created. SQL>Select * from tab1@T1_ora_link; Чтобы скрыть от пользователя факт, что таблица tab1 пользователя T1 находится на удаленной базе данных, можно использовать синоним. Синоним — это объект базы данных, используемый для альтернативного именования. Наличие синонимов позволяет приложениям обеспечить независимость от того, в какой схеме размещена таблица или представление, а также — в какой конкретно локальной базе данных распределенной системы хранятся требуемые приложению данные. Для создания синонима необходимо быть владельцем или иметь привилегию SELECT объекта, для которого создается синоним. Если надо создать синоним в схеме другого пользователя или синоним типа PUBLIC, то необходимо иметь привилегию CREATE PUBLIC SYNONYM или CREATE ANY SYNONYM. Оператор определения синонима имеет следующий синтаксис: CREATE [PUBLIC] synonym [имя_схемы.]имя_синонима FOR [имя_схемы.]имя объекта[@имя_связиБД]; Скроем факт, что таблица tab1 пользователя T1 находится на удаленной базе с помощью синонима: SQL>CREATE synonym suntab1 for t1.tab1@ T1_ora_link; Tеперь можно работать с таблицей suntab1. SQL>SELECT * FROM suntab1; 2.4.1. Снимки ♦ 137 Оператор определения снимков Для удаления определенной связи с удаленной базой данных используется команда DROP PUBLIC LINK. Для выполнения этой команды необходимо быть владельцем связи с удаленной базой данных либо иметь привилегию DROP ANY DATABASE LINK. Для отмены общей связи необходимо иметь привилегию DROP PUBLIC DATABASE LINK. Оператор уничтожения связи с удаленной базой данных имеет следующий синтаксис: DROP [public] database link имя_связи; Рассмотрим пример отмены связи с удаленной базой данных с именем T1_ORA_LINK: SQL>DROP database link T1_ora_link; 2.4.1. Снимки. Снимок — это поименованная, динамически поддерживаемая сервером выборка из одной или нескольких таблиц или представлений, обычно размещенных на удаленной базе данных. При помощи снимков администратор безопасности обеспечивает доступ пользователям к тем частям базы данных, которые необходимы им для работы. Чтобы механизм снимков работал на локальной и удаленной базе данных, должен быть установлен пакет DBMS_SNAPSHOT, в котором размещены процедуры обновления снимков. Оператор определения снимков имеет следующий вид: CREATE SNAPSHOT [имя_схемы.]имя_снимка [{PCTFREE целое | PCTUSED целое | INITRANS целое | MAXTRANS целое | TABLESPACE имя_табличной_области | STORAGE размер памяти}] | [CLUSTER имя_кластера (имя_столбца [,…])] [USING INDEX] [{PCTFREE целое | PCTUSED целое | INITRANS целое | MAXTRANS целое | TABLESPACE имя_табличной_области | STORAGE размер памяти}] | [REFRESH [{FAST | COMPLETE | FORCE }] 138 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.4. Связь с удаленной базой данных. [START WITH дата_1] [NEXT дата_2]] [FOR UPDATE] AS запрос; Ключевые слова PCTFREE, PCTUSED, INITRANS, MAXTRANS, TABLESPACE, STORAGE характеризуют пространство, распределяемое при работе со снимком. Ключевое слово PCTFREE определяет размер блоков, резервируемых для дальнейшей работы со снимком, допустимые значения от 0 до 99, значение по умолчанию 10, то есть если этот параметр не указан, то 10% пространства остается не использованным для записи в него данных для дальнейшей модификации строк снимка. Ключевое слово PCTUSED определяет минимальный процент использования пространства блока, при котором в него вводятся данные, допустимые значения от 1 до 99. Значение по умолчанию 40, то есть если этот параметр не указан, то в блоке занято менее 40% пространства, в него вводятся данные при выполнении операции вставки. Сумма значений параметров PCTFREE и PCTUSED не должна превышать 100. Ключевое слово INITRANS определяет начальное число параллельных транзакций, которые могут выполняться для модификации данных блока. Значение по умолчанию 1. Параметр MAXTRANS определяет максимальное число параллельных транзакций, которые могут выполняться для модификации данных блока. Ключевое слово TABLESPACE определяет имя табличной области, если оно не указано, то снимок располагается в табличной области пользователя, который является владельцем снимка. Ключевое слово STORAGE определяет объем внешней памяти, выделяемой под снимок. Ключевое слово CLUSTER указывает привязку столбцов снимка к кластеру. Ключевое слово USING INDEX определяет создание индекса для уменьшения времени доступа к данным снимка. Параметры 2.4.1. Снимки ♦ 139 Пример определения снимков PCTFREE, PCTUSED, INITRANS, MAXTRANS, TABLESPACE, STORAGE характеризуют пространство, отводимое для индекса снимка. Ключевое слово REFRESH определяет технологию обновления снимка. Параметр COMPLETE означает, что при обновлении данных снимка заново выполняется запрос, формирующий снимок. При задании параметра FAST при обновлении данных снимка используется информация об измененных данных в мастер-таблице, хранящаяся в журнальном файле снимка. При используемом по умолчанию параметре FORCE решение о технологии обновления снимка принимается системой (обычно это быстрое обновление). Ключевое слово START WITH определяет с помощью параметра дата_1 дату первого обновления снимка. Ключевое слово NEXT определяет с помощью параметра дата_2 интервал между автоматическими обновлениями снимка. Если параметр REFRESH отсутствует, то автоматического обновления данных снимка не происходит, так же не происходит автоматического обновления данных снимка при отсутствии обоих ключевых слов START WITH и NEXT. Ключевое слово FOR UPDATE указывает на возможность изменения данных снимка. Ключевое слово AS запрос включает в создаваемый снимок строки, являющиеся результатом выполнения запроса. Пример 2.4.2 Пример определения снимков Пусть таблица tab1 размещена на удаленном сервере, и доступ к ней осуществляется с помощью связи с именем T1_ora_link: SQL>CREATE SNAPSHOT snap_suntab1 AS SELECT * FROM tab1@ T1_ora_link WHERE AT1>0; SQL>SELECT * FROM snap_suntab1; Для модификации снимка с целью установки частоты автоматического изменения в 1 час можно воспользоваться командой ALTER SNAPSHOT. Ключевое слово REFRESH сделает его об- 140 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.4. Связь с удаленной базой данных. новляемым автоматически, изменения, введенные в мастер-таблице, автоматически будут появляться в снимке. SQL>ALTER SNAPSHOT snap_suntab1 REFRESH COMPLETE 2 START WITH SYSDATE NEXT SYSDATE + 1/24; SQL>SELECT FROM snap_suntab1; 2.4.2. Последовательности. Последовательность – это объект базы данных, генерирующий неповторяющиеся целые числа. Числа, создаваемые последовательностью, могут либо возрастать постоянно, либо до определенного предела, либо при достижении определенного предела, начинать возрастать заново с начального значения. Последовательность может создавать цепочки как увеличивающихся чисел, так и уменьшающихся, можно задавать и приращение значений последовательности. Для создания последовательности требуется привилегия CREATE SEQUENCE. Для создания последовательности в схеме другого пользователя необходимо иметь привилегию CREATE ANY SEQUENCE. Оператор определения последовательности имеет следующий синтаксис: CREATE SEQUENCE [имя_схемы.]имя_последовательности [INCREMENT BY приращение] [START WITH начальное_значение] [MAXVALUE наибольшее_значение | NOMAXVALUE] [MINVALUE наименьшее_значение | NOMINVALUE] [CYCLE | NOCYCLE] [CACHE число_элементов | NOCACHE] [ORDER | NOORDER] Ключевое слово INCREMENT BY определяет интервал между последовательными номерами. Если этот параметр имеет отрицательное значение, то последовательность убывающая, если положительное — то последовательность возрастающая. Значением по умолчанию является 1, параметр приращения может быть любым целым числом не равным нулю. 2.4.2. Последовательности ♦ 141 Оператор определения последовательности Ключевое слово START WITH параметром начальное_значение задает первый генерируемый номер. Если этот параметр отсутствует, то для возрастающих последовательностей первый генерируемый номер равен значению параметра MINVALUE, а для убывающей последовательности MAXVALUE. Ключевое слово MAXVALUE параметром наибольшее_значение задает максимальное значение, которое будет генерироваться последовательностью. Это число должно быть больше, чем начальное_значение и наименьшее_значение. Это число может быть любым числом с количеством знаков, не превышающим 28. Отсутствие верхней границы указывается ключевым словом NOMAXVALUE, которое определяет для убывающих последовательностей значение –1, а для возрастающих последовательностей 1027. Ключевое слово MINVALUE параметром наименьшее_значение задает минимальное число, которое будет генерироваться последовательностью. Это число должно быть меньше чем начальное_значение и наибольшее_значение. Это число может быть любым числом с количеством знаков, не превышающем 28. Отсутствие нижней границы указывается ключевым словом NOMINVALUE, которое определяет для убывающих последовательностей значение –1026, а для возрастающих последовательностей 1. Ключевое слово NOCYCLE является значением, используемым по умолчанию, и означает завершение генерирования последовательности по достижении конца последовательности. Если при определении последовательности указан параметр CYCLE, то после достижения очередным членом последовательности значения наибольшее_значение (для возрастающих последовательностей) выдается значение параметра наименьшее_значение. Если параметры наименьшее_значение и наибольшее_значение не указаны, то используются их значения по умолчанию. Ключевое слово CACHE указывает на использование техники кеширования, что обеспечивает более быструю генерацию элементов последовательности. Ключевое слово число_элементов определяет 142 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.4. Связь с удаленной базой данных. количество элементов области кеша, это число не должно превышать разницы между MAXVALUE и MINVALUE. Ключевое слово ORDER обеспечивает генерацию последовательных элементов точно в порядке поступления запросов. Одна последовательность может использоваться для генерации первичных ключей для нескольких таблиц. Если два пользователя обращаются к одной последовательности, то каждый из них не видит последовательные номера, сгенерированные для другого пользователя. Псевдостолбец NEXTVAL используется для генерирования очередного номера из указанной последовательности. Обращение имеет следующий вид: Имя_последовательности.NEXTVAL; Псевдостолбец CURVAL используется для ссылки на текущее значение последовательного номера, до ссылки на CURVAL в текущем сеансе NEXTVAL должен быть использован хотя бы один раз. Обращение к CURVAL имеет следующий синтаксис: Имя_последовательности.CURVAL; Рассмотрим пример создания последовательности с именем SEQ1. Начальный элемент последовательности определен 2, параметры наибольшее_значение и наименьшее_значение определены равными 3 и 1 соответственно, параметр цикла равен 2, параметр кеширования равен 2: Пример создания последовательности SQL>CREATE SEQUENCE SEQ1 MAXVALUE 3 MINVALUE 1 START SQL>SELECT SEQ1.NEXTVAL FROM NEXTVAL 2 SQL>SELECT SEQ1.NEXTVAL FROM NEXTVAL 3 SQL>SELECT SEQ1.NEXTVAL FROM NEXTVAL 1 WITH 2 CYCLE CACHE 2; DUAL; DUAL; DUAL; 2.4.2. Последовательности ♦ 143 Упражнения 2.33–2.38 Этот пример показывает циклическое образование элементов последовательности. Псевдостолбец NEXTVAL обычно используется для итерации значений первичных ключей. Для получения текущего значения используется псевдостолбец CURVAL. Пусть таблица сформирована предложением SQL>CREATE TABLE TAB1 (At1 NUMBER PRIMARY KEY); Рассмотрим пример, иллюстрирующий применение псевдостолбцов последовательности: SQL>INSERT INTO TAB1 VALUES (SEQ1.NEXTVAL); Этим действием мы добавили строку в таблицу. SQL>SELECT SEQ1.CURVAL FROM DUAL; CURVAL 1 Для удаления последовательности используется команда DROP SEQUENCE. Для выполнения данной операции необходимо быть владельцем последовательности либо иметь привилегию DROP ANY SEQUENCE. Оператор удаления последовательности имеет следующий синтаксис: DROP SEQUENCE [имя_схемы.]имя_последовательноси Пример уничтожения последовательности: DROP SEQUENCE SEQ1; Упражнения Упражнения 2.33—2.38 2.33. Создать таблицу Student и заполнить ее с использованием последовательностей. Создать связь с другим пользователем и прочитать у него первичный ключ таблицы SUBJECT. 2.34. Создать таблицу SUBJECT и заполнить ее с использованием последовательностей. Создать связь с другим пользователем и прочитать у него первичный ключ таблицы Student. 144 ♦ Глава 2. Распределенная система управления базами данных Oracle 2.4. Связь с удаленной базой данных. 2.35. Создать таблицу LECTURE и заполнить ее с использованием последовательностей. Создать связь с другим пользователем и прочитать у него первичный ключ таблицы Student. 2.36. Создать таблицу UNIVERCITY и заполнить ее с использованием последовательностей. Создать связь с другим пользователем и прочитать у него первичный ключ таблицы Student. 2.37. Создать таблицу EXAM_MARKS и заполнить ее с использованием последовательностей. Создать связь с другим пользователем и прочитать у него первичный ключ таблицы UNIVERSITY. 2.38. Создать таблицу SUBJ_LEC и заполнить ее с использованием последовательностей. Создать связь с другим пользователем и прочитать у него первичный ключ таблицы UNIVERCITY.