Книги: [Классика] [Базы данных] [Internet/WWW] [Сети] [Программирование] [UNIX] [Windows] [Безопасность] [Графика] [Software Engineering] [ERP-системы] [Hardware]
Отрывок
Глава 3
Основы языка
Структура блока PL/SQL
Набор символов PL/SQL
Идентификаторы
Литералы
Разделитель в виде точки с запятой
Комментарии
Ключевое слово PRAGMA
Метки
Каждый язык, будь то человеческий или компьютерный, имеет синтаксис, словарь и набор символов, и для того чтобы общаться с помощью этого языка, нужно выучить правила его использования. Многие с опаской приступают к изучению новых компьютерных языков, но вообще-то они очень просты, а PL/SQL еще и один из самых простых. Трудность общения на языке, основанном на байтах, связана не с самим языком, а с компилятором или компьютером, с которым мы "говорим". Большинство компиляторов - это "недалекие" создания, их трудно назвать творческими и гибкими, они не способны нестандартно мыслить, а их словарь крайне ограничен. Разве что соображают они очень-очень быстро.
Если вы слышите что-нибудь вроде: "Давай выпьем чаю", то понимаете, о чем вам говорят, и знаете, что ответить. Однако если вы скажете PL/SQL: "подкинь-ка еще с полдюжины записей", то едва ли получите требуемое. Говоря на языке синтаксиса, для использования PL/SQL нужно расставлять все точки над "i". Поэтому в данной главе описываются основные правила языка, помогающие общаться с компилятором PL/SQL, а также структура блока PL/SQL. Кроме того, вы узнаете, что такое лексические единицы и для чего предназначено ключевое слово PRAGMA.
Структура блока PL/SQL
БлокВсе языки программирования позволяют организовать логически связанные элементы в программные единицы. В PL/SQL фундаментальной организационной программной единицей является блок. Он лежат в основе двух ключевых языковых концепций.
Модульность. Блок PL/SQL является базовой единицей кода. Из данных единиц Модульностьсоздаются модули (например, процедуры и функции), которые, в свою очередь, составляют приложение. Именно блоки как организационные единицы низшего уровня определяют читабельность и простоту сопровождения программного кода.
Область действия. Область;действияБлок определяет область действия или контекст логически связанных объектов. В блоке группируются связанные между собой объявления и выполняемые операторы.
Блок может быть анонимным (то есть не имеющим имени) или именованным (представляющим собой процедуру и функцию). С блоком связано понятие пакета PL/SQL, который представляет собой набор из нескольких процедур и функций.
Разделы блока PL/SQL
Блок;разделыБлок PL/SQL может содержать до четырех разделов, однако только один из них является обязательным.
Заголовок. Заголовок;блокаИспользуется только в именованных блоках, определяет способ вызова именованного блока или программы. Не обязателен.
Раздел объявлений. Идентифицирует переменные, курсоры и вложенные блоки, на которые имеются ссылки в исполняемом блоке и блоке исключений. Не обязателен.
Исполняемый раздел. Операторы, которые выполняются ядром PL/SQL во время работы приложения. Обязателен.
Раздел исключений. Обрабатывает исключения (предупреждения и ошибки). Не обязателен.
Структура блока PL/SQL для процедуры показана на рис. 3.1.
Рис. 3.1. Структура блока PL/SQL
Порядок размещения разделов блока соответствует последовательности написания и выполнения программы.
1.
Определяются тип блока (процедура, функция, анонимный) и способ его вызова (заголовок).
2.
Объявляются все переменные и другие объекты PL/SQL, используемые в этом блоке (раздел объявлений).
3.
Локальные переменные и другие объекты PL/SQL, объявленные выше, применяются для выполнения необходимых действий.
4.
Обрабатываются все проблемные ситуации, которые могут возникнуть во время выполнения блока (раздел исключений).
Процедура, содержащая все четыре раздела, показана на рис. 3.2. В действительности все перечисленные разделы блока создаются не сразу, а в несколько этапов. Не ожидайте, что вы достигнете совершенства с первой попытки!
Рис. 3.2. Процедура, которая содержит все четыре раздела
Анонимные блоки
Блок;анонимныйКогда кто-то хочет остаться неизвестным, он не называет своего имени. То же можно сказать и об анонимном блоке PL/SQL, показанном на рис. 3.3: в нем вообще нет раздела заголовка, блок начинается ключевым словом DECLAREКлючевое слово;DECLARE (или BEGIN).
Рис. 3.3. Анонимный блок без разделов объявлений и исключений
Анонимный блок не может быть вызван другим блоком, поскольку не имеет составляющей, с помощью которой к нему можно обратиться. Таким образом, он является чем-то вроде сценария, который предназначен для выполнения операторов PL/SQL, в большинстве случаев включающих вызовы процедур и функций. Поскольку анонимные блоки могут содержать собственные разделы объявлений и исключений, разработчики часто используют их для определения области видимости идентификаторов и области действия обработки исключений в программе большего размера. Эти свойства блока мы подробно рассмотрим в следующих разделах.
Структура анонимного блока
Общий формат анонимного блока PL/SQL таков:
[ DECLARE
... необязательные операторы объявлений ... ]
BEGIN
... исполняемые операторы ...
[ EXCEPTION
... необязательные операторы обработки исключений ... ]
END;
Ключевое слово;BEGINBEGIN, ключевое словоКвадратные скобки указывают на необязательную часть синтаксиса. Ключевые слова BEGIN и END являются обязательными, и между ними должен быть как минимум один исполняемый оператор. Ключевое слово;ENDEND, ключевое слово
Примеры анонимных блоков
Ниже приведены различные сочетания разделов, которые допустимы для блока PL/SQL.
Анонимный блок BEGIN...END без разделов объявлений и исключений:
BEGIN
-- Вывод текущей даты в стандартном формате
DBMS_OUTPUT.PUT_LINE(SYSDATE);
END;
Анонимный блок с разделом объявлений, но без раздела исключений:
DECLARE
l_right_now DATE := SYSDATE;
BEGIN
DBMS_OUTPUT.PUT_LINE(l_right_now );
END;
Анонимный блок с разделом объявлений, исполняемым разделом и разделом исключений:
DECLARE
-- Вызов определенной ранее функции для получения даты
-- найма сотрудника по фамилии "FEUERSTEIN".
l_hiredate DATE := employee_pkg.date_of_hire ('FEUERSTEIN');
l_right_now DATE := SYSDATE;
l_old_timer EXCEPTION;
BEGIN
IF l_hiredate < ADD_MONTHS (l_right_now, 6)
THEN
RAISE l_old_timer;
ELSE
l_hiredate := right_now;
END IF;
EXCEPTION
WHEN l_old_timer
THEN
DBMS_OUTPUT.PUT_LINE('У вас нет доступа к информации.');
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE('ОШИБКА: ' || SQLCODE);
END;
Анонимные блоки выполняют последовательности операторов и затем завершают свою работу, действуя как процедуры. Фактически все анонимные блоки являются анонимными процедурами.
Анонимные блоки в различных средах
Анонимные блоки используются в средах, где код PL/SQL выполняется либо непосредственно, либо как часть некоторой программы этой среды (табл. 3.1). Объект, включающий конкретный блок, обеспечивает его контекст и в ряде случаев - имя программы.
Таблица 3.1. Анонимные блоки в различных средах
Объект, содержащий блок | Среда | Описание |
Клиентский триггер | Средства разработки Oracle | "Чистые" исполняемые операторы в триггерах Forms Builder или Reports Builder, оформленные соответствующим инструментальным средством как анонимные блоки и отправляемые исполнительному ядру PL/SQL (подробнее о триггерах см. в главе 18) |
Триггер базы данных | Манипуляции данными на уровне таблицы или события базы данных | Тело триггера. Хотя у триггера имеется имя, код PL/SQL анонимен (не имеет имени) |
Сценарий | SQL*Plus или его эквивалент | Программы и пакетно выполняемые сценарии, вызывающие процедуры и/или функции. Кроме того, команда SQL*Plus EXECUTE транслирует свой аргумент в анонимный блок, заключая его в операторы BEGIN и END |
Откомпилированная программа Встроенные языки (Pro*C и т. п.); OCI (Oracle Call Interface) Анонимные блоки, встроенные в код программы и выполняемые сервером базы данных
Когда вы связываете код PL/SQL с триггером или полем, пользуясь таким инструментальным средством, как Forms Builder, этот код составляет анонимный блок PL/SQL. При этом можно создать полный блок с объявлениями, исполняемыми операторами и разделом обработки исключений или же ограничиться только исполняемыми операторами.
Именованные блоки
Блок;именованныйХотя анонимные блоки PL/SQL применяются во многих приложениях Oracle, вероятно, большая часть написанного вами кода будет оформлена в виде именованных блоков. Ранее вы уже видели несколько примеров хранимых процедур (см. рис. 3.1) и знаете, что их главной особенностью является наличие заголовка. Заголовок процедуры выглядит так: Заголовок;процедуры
PROCEDURE [схема.]имя [(параметр [, параметр ...])]
[AUID {DEFINER | CURRENT_USER}]
Ключевое слово;RETURNRETURN, ключевое словоФункция;заголовокЗаголовок функции в целом очень похож на него, но дополнительно содержит ключевое слово RETURN:
FUNCTION [схема.]имя [(параметр [, параметр ...])]
RETURN тип_возвращаемых_данных
[AUID {DEFINER | CURRENT_USER}]
[DETERMINISTIC]
[PARALLEL ENABLE ...]
[PIPELINED]
Заголовок;функцииПоскольку Oracle позволяет вызывать некоторые функции из SQL-инструкций, заголовок функции включает больше необязательных элементов, чем заголовок процедуры. Таким образом, вам предоставляется гораздо больше возможностей управлять поведением функции во время ее выполнения. Более подробно процедуры и функции рассмотрены в главе 16.
Вложенные блоки
Блок;вложенныйВложенным является блок, который располагается внутри другого блока. Пример процедуры, содержащей анонимный вложенный блок, приведен ниже:
PROCEDURE calc_totals
IS
year_total NUMBER;
BEGIN
year_total := 0;
/* Начало вложенного блока */
DECLARE
month_total NUMBER;
BEGIN
month_total := year_total / 12;
END set_month_total;
/* Конец вложенного блока */
END;
Между операторами /* и */ помещается комментарий (см. раздел "Комментарии" далее в этой главе). Вложенный блок, в свою очередь, также может содержать блок. Таким образом, допустимой является структура вложенных блоков, представленная на рис. 3.4.
Рис. 3.4. Вложенные анонимные блоки
Вложенный блок PL/SQL называют также дочерним или подблоком, а внешний блок - родительским.
Область действия
Область;действияБлок; область действияГлавное преимущество вложения блоков - возможность ограничить область действия всех объявленных во вложенном блоке объектов и исполняемых операторов. Она, в свою очередь, позволяет не только лучше управлять поведением программы, но и уменьшить вероятность того, что по ошибке программист изменит значение не той переменной.
Переменные, исключения, модули и некоторые другие структуры являются локальными для блока, в котором они объявлены. Когда выполнение блока прекратится, ни на одну из этих структур сослаться будет нельзя. Так, в приведенной выше процедуре calc_totals к элементам внешнего блока, в частности к переменной year_total, можно обращаться из любого места процедуры, тогда как элементы, объявленные во внутреннем блоке, из внешнего недоступны.
Чаще всего вложенный блок создается с целью размещения в нем раздела обработки исключений. Когда исключение обрабатывается в программе, она продолжает свое выполнение, вместо того чтобы завершиться с ошибкой. Например, если вы не уверены в том, имеется ли в базе данных конкретная запись, можно поступить так:
BEGIN
BEGIN /* вложенный блок */
INSERT INTO book_copies (isbn, qty)
VALUES (:newisbn, :copies);
EXCEPTION
WHEN DUP_VAL_ON_INDEX
THEN
UPDATE book_copies SET qty = :copies WHERE isbn = :newisbn;
END; /* вложенный блок */
books.distribute_inventory_report;
END;
Исключение;DUP_VAL_ON_INDEXDUP_VAL_ON_INDEX, исключениеВ данном случае вложенный блок помогает обеспечить наличие в таблице нужной записи перед вызовом процедуры books.distribute_inventory_report. Кроме того, он предотвращает прекращение работы программы из-за исключения DUP_VAL_ON_INDEX. Однако в случае появления таких ошибок, как ORA-00942: Table or view does not exist, может оказаться, что работу программы необходимо прервать. Важно понимать, что именно вы должны контролировать происходящее и решать, как будет действовать приложение в том или ином случае. Более подробно об обработке ошибок в программах PL/SQL рассказывается в главе 6.
Видимость переменной
Видимость переменойПеременая;видимостьВажным свойством переменной, связанным с областью ее действия, является видимость. Данное свойство определяет, можно ли обращаться к переменной только по ее имени или же к имени необходимо добавлять префикс.
"Видимые" идентификаторы
Идентификатор;видимыйРассмотрим следующий фрагмент кода:
DECLARE
first_day DATE;
last_day DATE;
BEGIN
first_day := SYSDATE;
last_day := ADD_MONTHS (first_day, 6);
END;
Переменные first_day и last_day объявлены в том же блоке, где они используются, поэтому при обращении к ним указаны только их имена. Мы говорим, что идентификаторы этих переменных видимы. В общем случае видимыми идентификаторами являются:
индексная переменная цикла (видима и доступна только внутри цикла);
идентификатор, объявленный в текущем блоке;
идентификатор, объявленный в блоке, который включает текущий блок;
отдельный объект базы данных (таблица, представление и т. д.) или объект PL/SQL (процедура, функция), владельцем которого вы являетесь;
отдельный объект базы данных или объект PL/SQL, на который у вас есть соответствующие права и который определяется соответствующим синонимом.
Следовательно, ссылаться на эти объекты можно, просто указывая их имена. PL/SQL позволяет также обращаться к существующим объектам, которые не находятся в пределах непосредственной видимости блока. Как это делается, рассказано в следующем разделе.
Уточненные идентификаторы
Идентификатор;уточненныйХарактерными примерами идентификаторов, которые невидимы в области кода, где они используются, являются идентификаторы, объявленные в спецификации пакета (имена переменных, типы данных, а также имена процедур и функций). Делая ссылку на такой объект, необходимо перед его именем указывать префикс и символ точки (аналогичным образом вы уточняете имя столбца посредством имени таблицы, в которой он содержится). Например:
price_util.compute_means - программа с именем compute_means из пакета price_util;
math.pi - константа с именем pi, объявленная и инициализированная в пакете math;
:GLOBAL.company.id - глобальная переменная в Oracle Forms.
(В описании такой переменной указано, что она собой представляет, но по ее имени невозможно определить тип - это еще один аргумент в пользу соглашения об информативных именах.)
Можно также использовать дополнительное уточнение, определяющее владельца объекта. Например, выражение
scott.price_util.compute_means
указывает на процедуру compute_means пакета price_util, принадлежащего пользователю Oracle c учетной записью scott.
Уточнение идентификаторов с помощью имен модулей
Обеспечить правильное применение идентификаторов в PL/SQL можно несколькими методами. В частности, при работе с пакетами удобно создавать переменные, имеющие глобальную область действия. Предположим, у нас есть пакет company_pkg и в спецификации пакета объявлена переменная с именем last_company_id:
PACKAGE company_pkg
IS
last_company_id NUMBER;
...
END company_pkg;
Далее, ссылаясь на переменную last_company_id извне, необходимо предварять ее имя именем этого пакета:
IF new_company_id = company_pkg.last_company_id THEN
Поскольку переменная, объявленная в спецификации пакета, глобальна для сеанса, на нее можно ссылаться в любой программе, но доступна она только при указании имени пакета.
Идентификатор можно уточнить также с помощью имени модуля, в котором он определен:
PROCEDURE calc_totals
IS
salary NUMBER;
BEGIN
...
DECLARE
salary NUMBER;
BEGIN
salary := calc_totals.salary;
END;
...
END;
В первом объявлении создается переменная salary, областью действия которой является вся процедура. Однако во вложенном блоке объявляется другая переменная с тем же именем. Поэтому ссылка на переменную salary во внутреннем блоке всегда сначала разрешается относительно объявления в этом блоке, где переменная видима безо всяких уточнений. Чтобы во внутреннем блоке сделать ссылку на переменную salary, объявленную на уровне процедуры, необходимо уточнить ее имя посредством имени процедуры (cal_totals.salary).
В PL/SQL имеется много правил, с помощью которых можно найти выход из подобных ситуаций. И хотя знать их полезно, лучше использовать уникальные идентификаторы, чтобы избежать конфликтов имен вообще.
Набор символов PL/SQL
PL/SQL;набор символовПрограмма PL/SQL представляет собой последовательность операторов, состоящих из одной или нескольких строк текста. Набор символов, из которых можно составлять эти строки текста, зависит от используемого в базе данных набора символов. Для примера в табл. 3.2 приведены символы, входящие в набор US7ASCII.
Таблица 3.2. Символы из набора US7ASCII, которые можно использовать в PL/SQL
Тип | Символы |
Буквы | A-Z, a-z |
Цифры | 0-9 |
Знаки | ~!@#$%*()_-+=|[]{}:;" ' <>,.?/^ |
Пробельные символы | Табуляция, пробел, новая строка, возврат каретки |
Каждое ключевое слово в PL/SQL состоит из разных комбинаций символов данного набора. По умолчанию язык SQL не чувствителен к регистру символов. Это означает, что символы верхнего регистра в нем интерпретируются так же, как символы нижнего, за исключением ситуаций, когда символы заключены в одинарные кавычки, что превращает их в литеральные строки.
Многие из указанных символов, в отдельности или в сочетании с другими символами, имеют в PL/SQL специальное назначение. Простые и составные специальные символы описаны в табл. 3.3.
Таблица 3.3. Простые и составные специальные символы в PL/SQL
Символы | Описание |
; | Завершает объявления и операторы |
% | Индикатор атрибута (атрибут курсора, подобный %ISOPEN, или атрибут неявных объявлений, например %ROWTYPE); кроме этого, используется в качестве символа подстановки в условии LIKE |
_ | Символ подстановки одного символа в условии LIKE |
@ | Индикатор удаленного местоположения (произносится "эта") |
: | Индикатор хост-переменной, например :block.item в Oracle Forms |
** | Оператор возведения в степень |
<> или != или ^= или ~= | Оператор сравнения "не равно" |
|| | Оператор конкатенации |
<< и >> | Ограничители метки |
<= и >= | Операторы сравнения "меньше или равно" и "больше или равно" |
:= | Оператор присваивания |
=> | Оператор ассоциации |
.. | Оператор диапазона |
-- | Индикатор однострочного комментария |
/* и */ | Начальный и конечный ограничители многострочного комментария |
Символы группируются в лексические единицы, которые называют атомарными, поскольку они представляют собой наименьшие самостоятельные элементы языка. В PL/SQL лексическими единицами являются идентификатор, литерал, разделитель и комментарий. Мы рассмотрим их в следующих разделах.
Идентификаторы
ИдентификаторИдентификатор - это имя объекта PL/SQL, которым может быть:
константа;
скалярная переменная;
составная переменная (запись или коллекция);
исключение;
процедура;
функция;
пакет;
тип;
курсор;
зарезервированное слово;
метка.
К идентификаторам PL/SQL предъявляются следующие требования:
длина - до 30 символов;
должны начинаться с буквы;
не должны содержать пробелов (но могут включать символы "$", "_" и "#").
Если единственным отличием двух идентификаторов является регистр одного или более символов, компилятор PL/SQL воспринимает их как один и тот же идентификатор. В частности, одинаковыми считаются следующие идентификаторы:
lots_of_$MONEY$
LOTS_of_$MONEY$
Lots_of_$Money$
Примеры допустимых имен идентификаторов вы найдете далее:
company_id#
primary_acct_responsibility
First_Name
FirstName
address_line1
S123456
Идентификаторы, которые приведены ниже, в PL/SQL недопустимы:
1st_year -- Начинается с цифры
procedure-name -- Содержит недопустимый символ "-"
minimum_%_due -- Содержит недопустимый символ "%"
maximum_value_exploded_for_detail -- Имя слишком длинное
company ID -- Имя не должно содержать пробелов
Идентификаторы - это имена, с помощью которых можно обращаться к элементам программы, и лучше, когда они отражают назначение элементов. Не стоит пользоваться именами, подобными X1 и temp, поскольку они ни о чем не говорят ни вам, ни программисту, которому придется работать с вашим кодом.
Некоторые из перечисленных правил именования объектов можно нарушать, если заключить идентификатор в двойные кавычки. Однако мы не рекомендуем пользоваться этим методом. Хотя когда-нибудь вы наверняка встретите "крутой" код вроде следующего:
SOL> DECLARE
2 "pi" CONSTANT NUMBER := 3.141592654;
3 "PI" CONSTANT NUMBER := 3.14159265358979323846;
4 "2 pi" CONSTANT NUMBER := 2 * "pi";
5 BEGIN
6 DBMS_OUTPUT.PUT_LINE('pi: ' || "pi");
7 DBMS_OUTPUT.PUT_LINE('PI: ' || pi);
8 DBMS_OUTPUT.PUT_LINE('2 pi: ' || "2 pi");
9* END;
10 /
pi: 3.141592654
PI: 3.14159265358979323846
2 pi: 6.283185308
Обратите внимание, что в строке 7 идентификатор pi используется без кавычек. Поскольку компилятор обеспечивает независимость от регистра, преобразуя все идентификаторы и ключевые слова в верхний регистр, данный идентификатор указывает на переменную, объявленную в строке 3 как "PI".
Иногда двойные кавычки применяются в SQL-инструкциях для ссылки на таблицы базы данных, имена столбцов которых содержат несколько слов, разделенных пробелами.
Зарезервированные слова
Слово;зарезервированноеНекоторые идентификаторы (такие как BEGIN, IF и THEN) имеют в языке PL/SQL специальное назначение. К ним относятся:
ключевые слова;
идентификаторы пакета STANDARD.
Вы не должны, и в большинстве случаев не сможете, использовать их в качестве имен объектов, объявляемых в своих программах.
Ключевые слова
Существуют слова, которые, с точки зрения Ключевое словоСлово;ключевоекомпилятора PL/SQL, имеют строго определенную семантику - являются ключевыми. К таковым относится, например, слово END, завершающее программу, условный оператор IF и оператор цикла. Предположим, вы попытаетесь объявить переменную с именем end, как в следующем примере:
DECLARE
end VARCHAR2(10) := 'blip'; /* Не будет работать! END нельзя использовать
в качестве имени переменной.*/
BEGIN
DBMS_OUTPUT.PUT_LINE(end);
END;
/
В ответ получите сообщение об ошибке компиляции:
PLS-00103: Encountered the symbol "END" when expecting one of the following:
Слово end в разделе объявлений сообщает компилятору PL/SQL о преждевременном завершении анонимного блока.
Идентификаторы пакета STANDARD
Пакет;STANDARDSTANDARD, пакетНе следует использовать в качестве идентификаторов имена объектов, которые определены в специальном пакете STANDARD. В нем объявлено большое число идентификаторов - это имена встроенных исключений (подобные DUP_VAL_ON_INDEX), функций (например, UPPER, REPLACE и TO_DATE) и подтипов (таких как STRING). Список функций и процедур модуля STANDARD можно просмотреть с помощью команды
SQL> DESC SYS.STANDARD
Если все же вам потребуется назначить своей переменной имя встроенного объекта модуля STANDARD, то вы можете сделать это. На соответствующий модулю объект можно будет ссылаться, указав префикс STANDARD, как показано в следующем примере:
DECLARE
dup_val_on_index EXCEPTION; -- локальное переопределение
BEGIN
...
INSERT INTO ... /* может вызвать встроенное исключение */
...
RAISE dup_val_on_index; -- разрешается как
ссылка на локально объявленное исключение
EXCEPTION
WHEN dup_val_on_index
THEN
/* обработка локально объявленного исключения */
...
WHEN STANDARD.DUP_VAL_ON_INDEX
THEN
/* обработка обычного исключения */
...
END;
Как избежать использования зарезервированных слов в качестве идентификаторов
Придумать для идентификатора отвечающее требованиям имя совершенно несложно, поскольку существуют тысячи и тысячи сочетаний допустимых символов. Проблема в том, как при этом избежать использования одного из зарезервированных слов - ведь в PL/SQL их сотни!
Можно, конечно, проигнорировать данный момент и исправлять ошибки компиляции по мере их возникновения. Именно так большинство и поступает, но на поиск ошибок иногда тратится целый рабочий день, поскольку сообщения об ошибках компиляции часто не отражают причину ошибки. Некоторые программисты используют дорогостоящие средства разработки с мощным редактором, который имеет встроенные функции синтаксического анализа и сообщает о возможных проблемах по мере ввода программного кода. Мы же предпочитаем пользоваться дешевым редактором, который знает ключевые слова PL/SQL и автоматически их выделяет.
Представление;V$RESERVED_WORDSV$RESERVED_WORDS, представлениеНиже приведен минимальный список слов, которые нельзя использовать в качестве идентификаторов в программах PL/SQL (табл. 3.4). При составлении этой таблицы применялся следующий метод. Для каждого зарезервированного слова (их полный список хранится в представлении V$RESERVED_WORDS) мы пытались объявить сначала переменную, а затем процедуру с таким же именем. Если компилятор не позволял выполнить одну или обе эти операции, соответствующее ключевое слово помещалось в список.
Если вы работаете с Oracle 8.1.5 или более поздней версией и имеете соответствующие права, то для получения полного списка зарезервированных слов можете выполнить следующую инструкцию SQL:
SQL> SELECT * FROM V$RESERVED_WORDS;
Хотя данный список очень длинный, он не включает идентификаторы модуля STANDARD. Это еще один аргумент в пользу "интеллектуальных" редакторов.
Таблица 3.4. Минимальный список слов, которые нельзя использовать в качестве
идентификаторов в программах PL/SQL
ACCESS | DATE | INITIAL | OR | SUCCESSFUL |
ADD | DECIMAL | INSERT | ORDER | SYNONYM |
ALL | DECLARE | INTEGER | OVERLAPS | SYSDATE |
ALTER | DEFAULT | INTERSECT | PACKAGE | TABLE |
AND | DELETE | INTO | PCTFREE | THEN |
ANY | DESC | IS | PRIOR | TO |
AS | DISTINCT | LEVEL | PRIVILEGES | TRIGGER |
ASC | DROP | LIKE | PROCEDURE | TYPE |
AT | ELSE | LOCK | PUBLIC | UID |
AUDIT | END | LONG | RAW | UNION |
BEGIN | EXCLUSIVE | MAXEXTENTS | RENAME | UNIQUE |
BETWEEN | EXISTS | MINUS | RESOURCE | UPDATE |
BY | FILE | MLSLABEL | RETURN | USE |
CASE | FLOAT | MODE | REVOKE | USER |
CHAR | FOR | MODIFY | ROLLBACK | VALIDATE |
CHECK | FROM | NOAUDIT | ROW | VALUES |
CLOSE | FUNCTION | NOCOMPRESS | ROWID | VARCHAR |
CLUSTER | GRANT | NOT | ROWNUM | VARCHAR2 |
COLUMN | GROUP | NOWAIT | ROWS | VIEW |
COLUMNS | HAVING | NULL | SAVEPOINT | WHEN |
COMMENT | IDENTIFIED | NUMBER | SELECT | WHENEVER |
COMMIT | IF | OF | SESSION | WHERE |
COMPRESS | IMMEDIATE | OFFLINE | SET | WITH |
CONNECT | IN | ON | SHARE | |
CREATE | INCREMENT | ONLINE | SIZE | |
CURRENT | INDEX | OPEN | SMALLINT | |
CURSOR | INDEXES | OPTION | START | |
Отступы и ключевые слова
Идентификаторы необходимо отделять друг от друга хотя бы одним пробелом или разделителем. Кроме этого, вы можете форматировать текст программы, вставляя дополнительные пробелы, символы разрыва строки (перевод строки и/или возврат каретки) и табуляции в местах, где полагаются пробелы, и это не вызовет сообщения об ошибке. Например, два приведенных ниже оператора эквивалентны:
IF too_many_orders
THEN
warn_user;
ELSIF no_orders_entered
THEN
prompt_for_orders;
END IF;
IF too_many_orders THEN warn_user;
ELSIF no_orders_entered THEN prompt_for_orders;
END IF;
Однако внутри лексических единиц, таких как оператор "не равно", представленный символами "!=", наличие пробелов, символов разрыва строки или табуляции не допускается. В частности, при компиляции строки
IF max_salary ! = min_salary THEN
вы получите сообщение об ошибке, поскольку между символами "! =" имеется пробел.
Литералы
ЛитералЛитерал - это значение, с которым не связан идентификатор, оно существует "само по себе". Литерал может быть представлен одним из следующих типов данных: NUMBER (например, 415, 21,6 или NULL), STRING (например, 'Предложение', '01-FEB-2003', NULL) либо BOOLEAN (а именно TRUE, FALSE или NULL).
Заметьте, что в PL/SQL нет возможности непосредственно задать литеральное значение даты. Значение '01-FEB-2003' - это строковый литерал, то есть последовательность символов, заключенная в одинарные кавычки. Такую строку можно конвертировать в дату с помощью PL/SQL или SQL, но внутри базы данных Oracle для значений дат используется только двоичное представление.
Строковый литерал может состоять из одного или более символов, входящих в набор символов PL/SQL. Литерал длиной нуль символов представляется как '' (две последовательные одинарные кавычки без символов между ними). В Oracle9i строковый литерал нулевой длины имеет значение NULL и тип данных CHAR (строка нулевой длины).
В отличие от идентификаторов, строковые литералы в PL/SQL чувствительны к регистру символов. Например, значения следующих двух литералов различны:
'Steven'
'steven'
При проверке приведенного ниже условия возвращается значение FALSE:
IF 'Steven' = 'steven'
Одинарные кавычки внутри строки
Литерал;одинарные кавычки Иногда возникает необходимость включить одинарную кавычку в литерал как часть литерала. Для этого в месте, где должна стоять кавычка, ставятся два таких символа. Как это делается, показано ниже. Слева приведены различные строковые литералы, а справа - их "внутренние" строковые представления.
Литерал | Значение |
'There''s no business like show business.' | There's no business like show business. |
'"Hound of the baskervilles"' | "Hound of the baskervilles" |
'NLS_LANGUAGE=''ENGLISH''' | NLS_LANGUAGE='ENGLISH' |
'''' | ' |
'''hello''' | 'hello' |
'''''' | '' |
Перечень правил, которыми следует руководствоваться при включении одинарной кавычки в литерал, приведен ниже.
Чтобы включить одинарную кавычку в литерал, поместите на ее место две подряд идущие одинарные кавычки.
Если нужно включить одинарную кавычку в начало или конец литерала, используйте три подряд идущие одинарные кавычки.
Для создания строкового литерала, состоящего из одной одинарной кавычки, поместите подряд четыре одинарные кавычки.
Чтобы создать литерал, состоящий из двух одинарных кавычек, поставьте подряд шесть одинарных кавычек.
Две одинарные кавычки подряд - это не то же самое, что символ двойной кавычки, который в строковом литерале не имеет специального значения, а интерпретируется так же, как буква или цифра.
Числовые литералы
Литерал;числовой Числовые литералы могут быть целыми или действительными (то есть содержащими дробную часть) числами. Заметьте, что PL/SQL рассматривает число 154,00 как действительное, хотя его дробная часть равняется нулю и с точки зрения математики оно является целым. Целые и действительные числа имеют разное внутреннее представление, и преобразование числа из одной формы в другую требует определенных ресурсов.
Задавая числовые литералы, можно использовать также экспоненциальное представление числа. При этом символ "E" (в верхнем или нижнем регистре) обозначает умножение числа на 10 в степени n, например, 3,05E19, 12e-5.
Логические (булевы) литералы
Литерал;логический Литерал;TRUEЛитерал;FALSEДля представления логических значений в Oracle определено два литерала: TRUE и FALSE. Это не строки, и их не нужно заключать в кавычки. Они используются для присвоения значений логическим переменным, как в следующем примере:
DECLARE
enough_money BOOLEAN; -- Объявляем логическую переменную
BEGIN
enough_money := FALSE; -- Присваиваем ей значение
END;
При проверке логического значения литерал можно не указывать -
тип переменной говорит сам за себя:
DECLARE
enough_money BOOLEAN;
BEGIN
IF enough_money
THEN
...
Разделитель в виде точки с запятой
Программа на PL/SQL представляет собой последовательность объявлений переменных и операторов, границы которых определяются не кодом конца строки, а символом точки с запятой (;). Один оператор часто состоит из нескольких строк. Например, следующий оператор IF занимает четыре строки:
IF salary < min_salary (2003)
THEN
salary := salary + salary *0.25;
END IF;
В нем вы видите два символа точки с запятой. Первый отмечает конец единственного оператора присваивания в конструкции IF...END IF, а второй - конец оператора IF. Данный оператор можно разместить и в одной строке, причем результат будет одинаковым:
IF salary < min_salary (2003) THEN salary := salary + salary*0.25; END IF;
Каждый оператор также должен завершаться точкой с запятой, даже если они вложены друг в друга. Но если вашей целью не является создание нечитабельного кода, советуем каждый оператор или объявление размещать на отдельной строке.
Комментарии
Наличие поясняющего и сопроводительного Комментарийтекста в коде (комментариев) является основным признаком хорошей программы. В данной книге приводится множество советов, касающихся того, как сделать программы самодокументируемыми за счет использования продуманных соглашений об именах и модульного подхода. Однако для понимания сложного программного кода этого еще не достаточно. PL/SQL предлагает разработчикам две разновидности комментариев: однострочные и многострочные.
Однострочные комментарии
Комментарий;однострочный (--)Однострочные комментарии начинаются двумя дефисами (--), между которыми не должно быть пробелов или каких-либо других символов. Весь текст после двух дефисов и до конца строки рассматривается как комментарий и игнорируется компилятором. Если два дефиса стоят в начале строки, комментарием считается вся строка.
Запомните: два дефиса отмечают как комментарий остаток строки в редакторе кода, а не всю инструкцию PL/SQL, после которой они стоят. Например, в следующем операторе IF с помощью однострочного комментария поясняется содержимое условного выражения:
IF salary < min_salary (2003) -- Функция min_salary
возвращает минимальную годовую зарплату
THEN
salary := salary + salary *0.25;
END IF;
Многострочные комментарии
Комментарий;многострочный (/* */)Если однострочные комментарии удобны для создания кратких замечаний к фрагменту кода или для временного исключения строки программы из обработки, то многострочные позволяют включать в программу длинный сопроводительный текст или пояснения.
Многострочный комментарий помещается между начальным (/*) и конечным (*/) ограничителями. Весь текст между этими двумя парами символов рассматривается как часть комментария и игнорируется компилятором.
В следующем примере многострочный комментарий располагается в разделе заголовка процедуры. Слева, для того чтобы зрительно выделить комментарий в программе, создан столбик вертикальных черточек:
PROCEDURE calc_revenue (company_id IN NUMBER) IS
/*
| Имя программы: calc_revenue
| Автор: Стивен Ферстайн
| Программа предназначена для ...
| Для работы программы требуется следующее аппаратное обеспечение: ...
*/
BEGIN
...
END;
С помощью многострочных комментариев можно также отменить выполнение блока кода программы на время тестирования, как это сделано в следующем фрагменте:
EXIT WHEN a_delimiter (next_char)
/*
OR
(was_a_delimiter AND NOT a_delimiter (next_char))
*/
;
Ключевое слово PRAGMA
Директива;компилятора Ключевое слово;PRAGMAPRAGMA, ключевое словоКлючевое слово PRAGMA указывает, что остальная часть оператора PL/SQL является директивой компилятора (псевдоинструкцией), которая передает некоторую информацию компилятору и при трансляции не включается в исполняемый код.
Директивы компилятора задаются следующим образом:
PRAGMA директива;
Они могут располагаться в любом месте раздела объявлений. PL/SQL поддерживает четыре директивы компилятора, краткое описание которых приведено в следующей таблице.
Директивы компилятора | Описание |
AUTONOMOUS_TRANSACTION | Предписывает Директива;компилятора;AUTONOMOUS_TRANSACTIONAUTONOMOUS_TRANSACTION, директива компилятораисполнительному ядру PL/SQL выполнить сохранение или откат любых изменений, внесенных в базу данных в текущем блоке, без воздействия на главную транзакцию. Данная директива введена в Oracle8i. Дополнительную информацию см. в главе 13 |
EXCEPTION_INIT | Директива;компилятора;EXCEPTION_INITEXCEPTION_INIT, директива компилятораУказывает компилятору связать конкретный номер ошибки с идентификатором, который объявлен в программе как исключение. Дополнительную информацию см. в главе 6 |
RESTRICT_REFERENCES | Задает для компилятора уровень чистоты программы пакета (отсутствия в ней действий, вызывающих побочные эффекты). Дополнительную информацию см. в главе 16 |
SERIALLY_REUSABLE | Указывает исполнительному ядру PL/SQL, что данные уровня пакета не должны сохраняться между обращениями к ним. Эта директива введена в Oracle8i. Дополнительную информацию см. в главе 17 |
В следующем блоке демонстрируется, как использовать директиву EXCEPTION_ INIT для указания имени встроенного исключения. Если этого не сделать, исключение будет иметь только номер.
DECLARE
no_such_sequence EXCEPTION;
PRAGMA EXCEPTION_INIT (no_such_sequence, -2289);
BEGIN
...
EXCEPTION
WHEN no_such_sequence
THEN
...
END;
Метки
МеткаМетка PL/SQL - это способ наименования некоторого фрагмента программы. Она имеет такой формат:
<<идентификатор>>
Здесь идентификатор - это допустимый идентификатор PL/SQL (длиной до 30 символов и начинающийся с буквы), который не сопровождается символом точки с запятой. Метка располагается непосредственно перед фрагментом кода, имя которого она определяет. Фрагмент кода должен включать исполняемый оператор, им может быть даже оператор NULL:
BEGIN
...
<<the_spot>>
NULL;
Поскольку анонимный блок представляет собой группу исполняемых операторов, с помощью метки можно задавать имя анонимного блока (на время его выполнения). Это показано в следующем фрагменте кода:
<<insert_but_ignore_dups>>
BEGIN
INSERT INTO catalog
VALUES (...);
EXCEPTION
WHEN DUP_VAL_ON_INDEX
THEN
NULL;
END insert_but_ignore_dups;
Блоки часто именуют для улучшения читабельности кода. Давая блоку имя, вы делаете код самодокументированным и наверняка еще раз задумаетесь над тем, что он делает. Это иногда помогает находить ошибки.
Метки используют также, чтобы иметь возможность уточнить имя объекта внешнего анонимного блока в случае обращения к нему из внутреннего блока. Пример того, как это делается, приведен ниже:
<<outerblock>>
DECLARE
counter INTEGER := 0;
BEGIN
...
DECLARE
counter INTEGER := 1;
BEGIN
IF counter = outerblock.counter
THEN
...
END IF;
END;
END outerblock;
Без метки блока невозможно различить две переменные с одинаковым именем counter (лучше присвоить этим переменным разные имена).
Оператор;GOTOGOTO, операторТретья функция меток заключается в том, что они могут служить целевыми точками перехода для операторов GOTO. Однако в современных программах операторы GOTO использовать не принято, поскольку схема обработки исключений действует гораздо эффективнее. Во всем коде PL/SQL, который мне когда-либо доводилось видеть, я помню только один оператор GOTO.
Наиболее значимым является Оператор;EXITEXIT, операторприменение меток в качестве целевых точек выхода для операторов EXIT во вложенных циклах:
BEGIN
<<outer_loop>>
LOOP
LOOP
EXIT outer_loop;
END LOOP;
некоторый_оператор;
END LOOP;
END;
Без метки outer_loop осуществляется выход из внутреннего цикла, после чего выполняется некоторый_оператор. Однако с точки зрения алгоритма это не нужно. Последовательность выполнения операторов, которую задает метка в данном случае, нельзя организовать никаким другим способом.
Начало
Cодержание
Глава 3. Основы языка
Рецензия (В.Абрамов, А.Бачин, журнал Oracle Magazine RE)
[Заказать книгу в магазине "Мистраль"]