PL/SQL Anonymous Blocks
PL/SQL, the Oracle procedural extension of SQL, is a portable, high-performance transaction-processing language that is tightly integrated with SQL. The basic unit of a PL/SQL source program is the block, which groups related declarations and statements. A PL/SQL block is defined by the keywords DECLARE, BEGIN, EXCEPTION, and END. These keywords divide the block into a declarative part, an executable part, and an exception-handling part. Only the executable part is required.
begin dbms_output.put_line('hello world'); end; /
Because an anonymous block can have its own declaration and exception sections, developers can use anonymous blocks to provide scope for identifiers and exception handling within a larger program.
declare l_today date := sysdate; begin dbms_output.put_line( 'today is '||to_char(l_today,'Day')); exception when others then dbms_output.put_line(sqlerrm); end; /
Conditional Logic
Lets add some conditional logic using if . then . else syntax. The TO_CHAR function can be used to format dates and number data types. The D format mask is the day of the week, a number between 1 and 7.
declare l_today date := sysdate; begin if to_char(l_today,'D') < 4 then dbms_output.put_line( 'Have a wonderful week'); else dbms_output.put_line( 'Enjoy the rest of the week'); end if; dbms_output.put_line('today is '|| to_char(l_today,'Day')|| ' day '||to_char(l_today,'D')|| ' of the week.'); end; /
Static SQL
With PL/SQL it is easy to integrate SQL statements, the example below shows a an example of using SELECT INTO with an Oracle data dictionary table.
DECLARE howmany INTEGER; num_tables INTEGER; BEGIN -- Begin processing SELECT COUNT(*) INTO howmany FROM USER_OBJECTS WHERE OBJECT_TYPE = 'TABLE'; -- Check number of tables num_tables := howmany; -- Compute another value dbms_output.put_line (to_char(num_tables,'999G999G990')||' tables'); END;
Here is an example of using a cursor for loop
DECLARE l_table_count integer := 0; BEGIN for c1 in ( SELECT table_name FROM USER_TABLES order by 1) loop l_table_count := l_table_count + 1; dbms_output.put_line(c1.table_name); end loop; if l_table_count = 0 then dbms_output.put_line('You have no tables in your schema'); end if; END;
Dynamic SQL
Lets extend our static SQL example to include some dynamic content. To facilitate dynamic SQL passing a value back to the PL/SQL block we will create a package named "PKG".
CREATE OR REPLACE PACKAGE pkg AUTHID DEFINER AS table_row_count integer; END; / DECLARE l_table_count integer := 0; l_sql varchar2(32767); BEGIN for c1 in ( SELECT table_name FROM USER_TABLES order by 1) loop l_table_count := l_table_count + 1; l_sql := 'begin select count(*) into pkg.table_row_count from "'||c1.table_name||'"; end;'; execute immediate l_sql; dbms_output.put_line(c1.table_name||' - '||to_char(pkg.table_row_count,'999G999G990')||' rows'); end loop; if l_table_count = 0 then dbms_output.put_line('You have no tables in your schema'); end if; END; /
Additional Information
- Database on OTN SQL and PL/SQL Discussion forums
Oracle Database
Download Oracle Database
Oracle/PLSQL анонимные блоки
Структуры блоков PL/SQL могут быть включены в определения процедур, функций или триггеров PL/SQL или выполняться независимо в форме анонимного блока.
Структура блока
Структура блока PL/SQL:
DECLARE
--объявление переменных
BEGIN
--исполняемые операторы
EXCEPTION
--обработка исключений
END;
Описание структуры блока PL/SQL
DECLARE Необязательный. Раздел деклариорвания переменных, курсоров, типов, процедур и функций для использования в блоке. Область действия является локальной для блока. Каждое объявление должно заканчиваться точкой с запятой. BEGIN - END Обязательный. Раздел в котором исполняются один или несколько операторов PL/SQL. Должен быть как минимум один исполняемый оператор. Каждый оператор должен заканчиваться точкой с запятой. Блок BEGIN-END может содержать вложенные блоки BEGIN-END. EXCEPTION Необязательный. Раздел обработки исключительных ситуаций или "отлова" ошибок.
Примеры
В приведенном иже примере показан самый простейший допустимый блок, который ничего не делает.
Основы PL SQL: структура, функции, триггеры, переменные, записи
PL/SQL (Programming Language for SQL) — язык программирования от компании Oracle, предоставляющий средства для сложной обработки данных. В этой статье мы рассмотрим основы PL/SQL.
Начнём с программных единиц.
Программные единицы PL/SQL
К программным единицам в PL/SQL относят: 1. Процедуру — подпрограмму, выполняющую специфическое действие (CREATE PROCEDURE); 2. Функцию — подпрограмму, вычисляющую значение (CREATE FUNCTION). 3. PL/SQL-пакеты — объект БД, группирующий логически связанные типы, подпрограммы и программные объекты PL/SQL. Как правило, пакеты состоят из 2 частей — тела и спецификации. Спецификация представляет собой интерфейс с вашими приложениями (объявляет типы, константы, переменные, исключения, подпрограммы, курсоры — всё, что доступно для использования в пакете). Вторая часть — это тело пакета, полностью определяющая подпрограммы и курсоры, реализуя тем самым спецификацию пакета. 4. Динамический SQL: a. Native Dynamic SQL (NDS); b. DBMS_SQL. 5. Опции компилятора. 6. Триггеры — хранимые процедуры особого типа, которые юзер не вызывает непосредственно, т. к. их исполнение обусловлено действиями по модификации данных. Триггеры бывают разные: BEFORE INSERT, BEFORE UPDATE, AFTER INSERT и пр. 7. Управление зависимостями. 8. Хинты либо подсказки (Oracle Hints) — средства, которые позволяют оказывать явное влияние на план запроса. Подсказки определяют общие подходы и цели, оптимизирующие план исполнения запроса, в том числе методы и правила доступа к данным (например, указание метода и порядка соединения таблиц, индекса для доступа к таблице).
Блочная структура PL/SQL
В блоке PL/SQL может содержаться до 4-х разделов, но лишь один считается обязательным. 1. Заголовок. Применяется лишь в именованных блоках, служит для определения способа вызова программы либо именованного блока. 2. Раздел объявлений. Включает описания переменных, вложенных блоков и курсоров. 3. Раздел исключений. Служит для обработки исключений (предупреждений и ошибок). 4. Исполняемый раздел. Речь идёт о командах, которые выполняются ядром PL/SQL в процессе работы приложения. Обратите внимание, что это ОБЯЗАТЕЛЬНЫЙ раздел.
Давайте посмотрим на структуру PL/SQL-блока для процедуры:

Следующее изображение — это пример процедуры, содержащей все 4 раздела:

Хранимая процедура
Под хранимой процедурой понимают некоторый перечень инструкций, которые написаны на PL/SQL. Вызов такой процедуры обеспечивает выполнение содержащихся в этой процедуре инструкций. Сама она хранится в БД, поэтому и считается хранимой. Состоит из тела и спецификации.
Спецификация содержит имя процедуры, а также описание её выходных и входных данных, которые являются формальными параметрами либо формальными аргументами. Когда при вызове процедуры указывают параметры командной строки либо иные входные данные, указанные значения называют фактическими параметрами/фактическими аргументами.
Рассмотрим пример спецификации:
increase_salary_find_tax ( increase_percent IN NUMBER := 7, sal IN OUT NUMBER, tax OUT NUMBER )В примере выше перед нами процедура с 3-мя формальными параметрами. IN после имени параметра значит, что в процессе вызова процедура может из данного параметра считать входное значение. OUT значит, что процедура может применять этот параметр в целях возврата значения в ту программу, из которой она вызывалась. Комбинация IN OUT значит, что параметр может использоваться в качестве передачи значения процедуре, а также в целях возврата значения.
Что касается тела процедуры, то это блок кода PL/SQL.
Хранимые функции
Функция PL/SQL напоминает процедуру PL/SQL: у неё тоже есть тело и спецификация. Основное различие — функция нужна для возврата значения, которое можно применять в более крупном операторе SQL.
Триггеры
Триггером называют процедуру PL/SQL, выполняемую автоматически, когда происходит некоторое событие, которое называется триггерным событием.
К примеру, мы можем писать триггеры, которые срабатывают в процессе выполнения над таблицей операций UPDATE, INSERT либо DELETE; во время выдачи команд DDL; во время входа пользователя в систему либо его выхода; во время запуска либо остановки БД; во время возникновения ошибок.
Существуют 3 различия между процедурами PL/SQL и триггерами: 1. Триггеры невозможно вызвать из кода программы. Они вызываются автоматически как ответ на некоторое событие. 2. У триггеров нет списка параметров. 3. Спецификации триггера и процедуры немного отличаются.
Переменные в PL/SQL
Переменными называют именованные контейнеры. Они способны содержать информацию разных видов. С учётом помещаемой информации данных они имеют разные типы данных, а чтобы отличать эти данные друг от друга, присваиваются имена. К примеру, числа в PL/SQL хранятся в переменных типа NUMBER, текст — в переменных CHAR либо VARCHAR2. Что касается синтаксиса объявления переменной, то в PL/SQL он имеет любую из нижеперечисленных форм записи:
имя_переменной тип_данных [[NOTNULL] := выражение_по_умолчанию]; имя_переменной тип_данных [[NOT NULL] DEFAULT выражение_по_умолчанию];Здесь имя_переменной — любой правильный PL/SQL идентификатор. Такой идентификатор должен: 1. Иметь в длину не больше 30 символов, причём не иметь в записи пробелов и знаков табуляции. 2. Начинаться с буквы. 3. Состоять лишь из букв, цифр 0-9, символа подчеркивания, знака доллара и знака фунта. 4. Не совпадать с зарезервированными словами SQL и PL/SQL, имеющими спецзначение. Пример неправильной записи для переменной — слово BEGIN, обозначающее начало выполняемой секции основного PL/SQL-блока.
Следующее, это тип_данных — любой допустимый тип данных в SQL либо PL/SQL. Здесь обратите внимание, что модификатору NOT NULL требуется, чтобы переменная имела значение. И если модификатор указан, то переменной должно присвоиться значение по умолчанию.
Объявляем константы PL/SQL
Запись объявления константы выглядит следующим образом:
имя_переменной тип_данных CONSTANT := выражение;В отличие, скажем, от тех же переменных, константам обязательно присваивается значение, причём это значение нельзя будет поменять в течение всего срока жизни константы. При этом константы весьма полезны при поддержании безопасности и дисциплины во время разработки приложений повышенной сложности. К примеру, если вы желаете гарантировать, что PL/SQL-процедура не будет модифицировать данные, передаваемые ей, то вы можете объявить их константами. А если процедура всё-таки попытается модифицировать эти данные, PL/SQL возбудит исключение.
Записи в PL/SQL
Говоря о записи в PL/SQL, мы говорим о наборе данных базовых типов. К записи мы можем обращаться, как к единому целому. При этом для доступа к отдельным полям записи используют нотацию имя_записи_имя_поля . Записи бывают одного из 3-х нижеперечисленных типов: 1. Table-based (основанные на таблице). Такие записи имеют поля, которые совпадают по типу и имени со столбцами таблицы. Когда курсор выбирает всю строку — к примеру, оператором SELECT * FROM примерная_таблица, то возвращаемые записи можно копировать в переменную, имеющую тип записи, которая основана на таблице примерная_таблица. 2. Cursor-based (основанные на курсоре). Что касается полей этих записей, то они совпадают по имени, порядку и типу с заключительным списком столбцов в курсорном операторе SELECT. 3. Programmer-defined (определённые программистом). Тут речь идёт про записи, тип которых определяет программист, то есть вы сами.
Record PL/SQL
Давайте посмотрим, как применять спецификатор записи Record в PL/SQL с синтаксисом.
Record (запись) — это группа связанных элементов данных, которые хранятся в полях, причём каждая имеет своё имя и тип данных. При этом мы можем применять Record как переменную, способную содержать строку таблицы либо некоторые столбцы из строки таблицы.
Определяем и объявляем Record в PL/SQL
Объявить запись поможет атрибут %ROWTYPE, представляющий строку в таблице БД без непосредственного перечисления всех столбцов. При этом ваш код будет продолжать функционировать даже после добавления в таблицу столбцов. Но если вы желаете представить подмножество столбцов в таблице либо столбцы из различных таблиц, можно определить VIEW либо объявить CURSOR в целях выбора правильных столбцов и любых нужных объединений, а потом задействовать атрибут %ROWTYPE к CURSOR либо VIEW.
Посмотрим на синтаксис объявления переменной в PL/SQL и определения типа Record:
TYPE type_rec_name IS Record (field_1 datatype, field_2 datatype, … field_n datatype); var_rec type_rec_name;Мы видим следующие параметры: 1) type_rec_name – имя конкретного типа Record; 2) var_rec – имя переменной Record-типа; 3) field_1, field_2,… field_n – поля Record-типа; 4) datatype – тип данных для полей Record-типа. Может быть любой из списка:
Основы PL/SQL
Programming Language for SQL (PL/SQL) – решение Oracle, предоставляющее средства, которые позволяют выполнять сложную обработку информации (plsql).
Программные единицы PL/SQL
- Процедура — это подпрограмма, которая выполняет специфическое действие (CREATE PROCEDURE).
- Функция — это подпрограмма, которая вычисляет значение (CREATE FUNCTION).
- PL/SQL пакеты — это объект базы данных, который группирует логически связанные типы, программные объекты и подпрограммы PL/SQL. Пакеты обычно состоят из двух частей — спецификации и тела. Спецификация пакета — это интерфейс с вашими приложениями, она объявляет типы, переменные, константы, исключения, курсоры и подпрограммы, доступные для использования в пакете. Тело пакета полностью определяет курсоры и подпрограммы, тем самым реализуя спецификацию пакета (CREATE PACKAGE и CREATE PACKAGE BODY).
- Динамический SQL
- Native Dynamic SQL (NDS)
- DBMS_SQL
Структура блока PL/SQL
Блок PL/SQL может содержать до четырех разделов, однако только один из них является обязательным.
- Заголовок. Используется только в именованных блоках, определяет способ вызова именованного блока или программы. Не обязателен.
- Раздел объявлений. Содержит описания переменных, курсоров и вложенных блоков, на которые имеются ссылки в исполняемом разделе и разделе исключений. Не обязателен.
- Исполняемый раздел. Команды, выполняемые ядром PL/SQL во время работы приложения. Обязателен.
- Раздел исключений. Обрабатывает исключения (предупреждения и ошибки). Не обязателен.
Структура блока PL/SQL для процедуры показана на рисунке:
Рисунок «Процедура, содержащая все четыре раздела»:
Хранимая процедура
Хранимая процедура — это определенный набор инструкций, написанных на языке PL/SQL. Вызов процедуры приводит к выполнению содержащихся в ней инструкций. Процедура хранится в базе данных, поэтому и называется хранимой. Процедура состоит из двух основных частей:спецификации и тела.
Спецификация процедуры (procedure specification) включает в себя имя процедуры и описание ее входных и выходных данных. Эти входные и выходные данные называются формальными параметрами (formal parameters) или формальными аргументами (formal arguments). Если при вызове процедуры указываются параметры командной строки или другие входные данные, эти значения называются фактическими (actual) параметрами или фактическими аргументами.
Пример спецификацииincrease_salary_find_tax ( increase_percent IN NUMBER : = 7 , sal IN OUT NUMBER , tax OUT NUMBER )
Здесь мы видим процедуру с тремя формальными параметрами. Слово IN после имени параметра означает, что при вызове процедура может считать из этого параметра входное значение. Слово OUT означает, что процедура может использовать данный параметр для возврата значения в ту программу, из которой она была вызвана. Комбинация IN OUT после имени параметра говорит о том, что параметр может использоваться как для передачи значения процедуре, так и для возврата значения.
Тело процедуры (procedure body) — это блок PL/SQL-кода.Хранимые функции
Функция PL/SQL похожа на процедуру PL/SQL: она также имеет спецификацию и тело. Главное различие между процедурой и функцией в том, что функция предназначена для возврата значения, которое может использоваться в более крупном SQL-Операторе.
Триггеры
Триггер — это процедура PL/SQL, которая выполняется автоматически, когда происходит некоторое заданное событие, называемое триггерным событием (triggering event).
Например, можно писать триггеры, срабатывающие при выполнении над таблицей операций INSERT, UPDATE или DELETE; при выдаче команд DDL; при входе пользователя в систему или его выходе из системы; при запуске или останове базы данных; при возникновении ошибок.
Между триггерами и процедурами PL/SQL есть три различия:- Триггеры нельзя вызывать из кода программы. Oracle вызывает их автоматически в ответ на определенное событие.
- Триггеры не имеют списка параметров.
- Спецификация триггера немного отличается от спецификации процедуры.
Структура блока PL/SQL
Базовый блок PL/SQL состоит из четырех секций:
- секции заголовка (header section);
- необязательной секции объявлений (declaration section);
- выполняемой секции (execution section);
- необязательной секции исключений (exception section).
DECLARE — необязательно — переменные, константы, курсоры
BEGIN — обязательно — команды SQL, управляющие команды PL/SQL
EXCEPTION — необязательно — действия в случае возникновения ошибок
END; — обязательноАнонимный блок (anonumous block) — это блок PL/SQL без секции заголовка, иначе говоря, секции имени, поэтому он и называется анонимным. Анонимные блоки могут выполняться из SQL*Plus и использоваться в функциях, процедурах и триггерах PL/SQL. Вспомните, что сами процедуры, функции и триггеры также состоят из базовых блоков. Это означает, что базовый блок можно помещать в другой базовый блок.
Секция объявлений
Секция объявлений не является обязательной. В случае использования она начинается после секции заголовка и оканчивается перед ключевым, словом BEGIN. Эта секция содержит объявления переменных, констант, курсоров, исключений, функций и процедур PL/SQL, которые будут использоваться в выполняемой секции и секции исключений. Все объявления переменных и констант должны размещаться до объявлений функций или процедур. О переменных и константах PL/SQL будет подробно рассказано в следующем разделе. Объявление сообщает PL/SQL о том, что нужно создать переменную, константу, курсор, функцию или процедуру согласно приведенной спецификации. Когда выполнение базового блока завершается, все элементы, объявленные в секции объявлений, перестают существовать. Элементы, объявленные в секции объявлений базового блока, могут использоваться только в пределах этого блока. Одним словом, все, что находится в секции объявлений, при надлежит блоку и может использоваться только внутри него, а следовательно, существует только на протяжении его времени жизни. Часть кода, в которой может использоваться переменная, называется областью видимости (scope).
Выполняемая секция
Выполняемая секция начинается с ключевого слова BEGIN и заканчивается либо ключевым словом EXCEPTION, если присутствует секция исключений, либо ключевым словом END, за которым следуют необязательное имя функции или процедуры и точка с запятой. Выполняемая секция содержит один и более PL/SQL-операторов, выполняемых при передаче управления данному блоку. Структура выполняемой секции показана ниже.
один и более PL / SQL - операторов
[ секция исключений ]
END [ имя функции или процедуры ] ;В выполняемом коде PL/SQL чаще всего встречается оператор присваивания (:=). Он указывает, что нужно вычислить выражение справа и поместить результат в переменную слева.
Секция исключений
В ходе выполнения PL/SQL-оператора может возникнуть ошибка, которая сделает невозможным дальнейшее выполнение программы. Такие исключительные ситуации называются исключениями (exceptions). Пользователь, вызвавший процедуру, должен быть проинформирован о возникновении исключения, а также о причинах, его вызвавших. Вы можете выдать пользователю содержательное сообщение об ошибке, или предпринять некоторые корректирующие действия и повторить операцию, выполнявшуюся до возникновения ошибки. Вы также можете откатить изменения, которые были произведены в базе данных к этому моменту. PL/SQL помогает вам во всех этих случаях, предоставляя средства обработки исключений (exception handling).
WHEN имя _ исключения THEN
действия , предпринимаемые при возникновении исключения
WHEN имя _ исключения THEN
действия , предпринимаемые при возникновении исключенияСекция исключений начинается с ключевого слова EXCEPTION и продолжается до конца блока. Каждому исключению соответствует оператор WHEN имя_исключения, указывающий, что должно быть сделано при возникновении данного исключения. Все операторы, находящиеся между оператором, вызвавшим ошибку, и секцией исключений, игнорируются. Выполнение оператора, указанного в секции исключений, называется обработкой исключения (exception handling). Процесс, включающий в себя обнаружение ошибки, определение, какое исключение описывает ее наилучшим образом, и передачу PL/SQL информации, позволяющей найти соответствующий код в секции исключений, называется возбуждением исключения (raising exception).
Переменные
Переменные — это именованные контейнеры. Они могут содержать информацию (данные) различных видов. В зависимости от того, какую информацию в них можно помещать, они имеют различные типы данных, а чтобы отличать их друг от друга, им присваиваются имена. PL/SQL хранит числа в переменных типа NUMBER, а текст — в переменных типа CHAR или VARCHAR2. Синтаксис объявления переменной в PL/SQL может иметь любую из следующих форм:
имя _ переменной тип _ данных [ [ NOTNULL ] : = выражение _ по _ умолчанию ] ;
имя _ переменной тип _ данных [ [ NOT NULL ] DEFAULT выражение _ по _ умолчанию ] ;Имя_переменной — это любой правильный идентификатор PL/SQL. Правильный идентификатор PL/SQL должен:
- Иметь не более 30 символов в длину и не содержать пробельных символов (собственно пробелов и знаков табуляции).
- Состоять только из букв, цифр от 0 до 9, символа подчеркивания (_), знака доллара ($) и знака фунта (#).
- Начинаться с буквы.
- Не совпадать с зарезервированными словами PL/SQL или SQL, которые имеют специальное значение. Например, именем переменной не может быть слово BEGIN, которое обозначает начало выполняемой секции базового блока PL/SQL.
Тип_данных — это любой допустимый тип данных SQL или PL/SQL. Модификатор NOT NULL требует, чтобы переменная имелазначение. Если он указан, переменной должно быть присвоено значение по умолчанию.
Объявление констант PL/SQL
Синтаксис объявления константы имеет следующий вид:
имя _ переменной тип _ данных CONSTANT : = выражение ;
В отличие от переменных константам обязательно присваивается значение, которое нельзя изменять на протяжении времени жизни константы. Константы очень полезны для поддержания безопасности и дисциплины при разработке больших и сложных приложений. Например, если вы хотите гарантировать, что процедура PL/SQL не будет модифицировать передаваемые ей данные, можете объявить их константами. Если процедура все же попытается их модифицировать, PL/SQL возбудит исключение.
Оператор IF
Оператор IF имеет следующий синтаксис:
IF условие _1 THEN
действие _1 ;
[ ELSIF условие _2 ТНЕ N действие _2 ; ]
[ ELSE альтернативное _ действие ; ]Действие_1 … альтернативное Действие представляют один или несколько PL/SQL-операторов. Каждая группа операторов выполняется только в том случае, если выполнено соответствующее условие. После того как обнаружено выполнение одного из условий, остальные условия не проверяются.
Циклы
PL/SQL предоставляет три различные конструкции для итеративной обработки. Каждая из них позволяет циклически выполнять набор операторов PL/SQL. Выход из цикла осуществляется в зависимости от некоторого условия.
LOOP
Конструкция LOOP имеет следующий синтаксис:
имя _ цикла LOOP
EXIT имя _ цикла [ WHEN условие _ выхода ] ;При наличии конструкции WHEN все операторы в теле цикла повторяются до тех пор, пока выражение условие_выхода не примет положительное значение (т.е. не станет истинным). Условие выхода проверяется на каждом проходе, иначе называемом итерацией. Как только выражение принимает значение «истина», все операторы после EXIT пропускаются, итерации прекращаются и выполнение продолжается с первого оператора, следующего за END LOOP. Если условие WHEN отсутствует, операторы между LOOP и EXIT выполняются только один раз. Очевидно, что опустив условие WHEN, вы поступите нелогично. В конце концов идея цикла состоит в том, чтобы обеспечить потенциально многократное выполнение кода.
Цикл WHILE
Еще одной разновидностью цикла является цикл WHILE. Он хорошо подходит в ситуациях, когда количество итераций заранее неизвестно, и определяется некоторым внешним фактором. Цикл WHILE имеет следующий синтаксис:
WHILE условие _ выхода LOOP
Условие WHILE проверяется перед каждым входом в цикл. Если оно имеет значение «истина», то выполняется очередная итерация.
Цикл FOR
В цикле FOR для подсчета итераций используется переменная-счетчик, называемая также индексом цикла (loop index). По завершении каждой итерации счетчик увеличивается, начиная с нижнего предела, или уменьшается, начиная с верхнего предела. Как только его значение выйдет за указанный диапазон, цикл завершается. Синтаксис цикла FOR выглядит следующим бразом:
FOR счетчик IN [ REVERSE ] нижняя _ граница . . верхняя _ граница LOOP
Курсоры
Курсор — это исключительно важная конструкция PL/SQL, лежащая в основе взаимодействия PL/SQL и SQL. Название «курсор» означает «текущий набор записей». Курсор представляет собой специальный элемент PL/SQL, с которым связан SQL-оператор SELECT. Используя курсор, можно отдельно обрабатывать каждую строку связанного с ним SQL-оператора. Курсор объявляется в секции объявлений базового блока. Он открывается командой OPEN, а выборка строк осуществляется с помощью команды FETCH. После завершения всей обработки курсор закрывается командой CLOSE. Закрытие курсора освобождает те системные ресурсы, которые использовались, пока он был открыт. Строки, выбранные курсором, можно заблокировать, чтобы предотвратить их модификацию другими пользователями. Закрытие курсора или выполнение явной операции COMMIT или ROLLBACK приведет к разблокированию строк. Для SQL-операторов, используемых в коде PL/SQL, применяются скрытые, или неявные (implicit), курсоры, а также явные (explicit) курсоры, т.е. те, которым присвоено имя.
Объявление курсора и атрибуты курсора
Курсор объявляется в процедуре PL/SQL следующим образом:
CURSOR имя _ курсора [ ( [ параметр _1 [ , параметр _2 . . . ] ) ]
[ RETURN спецификация возврата ] ISоператор _select [ FOR UPDATE [ OF таблица _ или _ столбец _1 [ , таблица _ или _ столбец _2 . . . ] ] ]
Параметры курсора похожи на параметры процедуры, за тем исключением, что они всегда являются входными (IN). Использование параметров OUT или IN OUT невозможно, поскольку курсор не может их модифицировать. Параметры используются в конструкции WHERE курсорного оператора SELECT. Спецификация возврата показывает, записи какого типа будут выбираться оператором SELECT. Таблица_или_столбец — это имя столбца, который предстоит обновлять, или имя таблицы, в которой предстоит удалять или обновлять строки. Оно должно входить в число имен таблиц и столбцов, указанных в операторе SELECT курсора, и предназначено для документирования, показывая, какие элементы могут быть потенциально модифицированы кодом, использующим данный курсор. Команда FOR UPDATE блокирует строки, выбранные оператором SELECT при открытии курсора. Строки остаются заблокированными до тех пор, пока вы не закроете курсор рассмотренными выше способами. Атрибуты курсора:
- имя_курсора%ISOPEN — Позволяет проверить, открыт ли курсор. Если курсор имя_курсора уже открыт, возвращается значение TRUE
- имя_курсора%ROWCOUNT — Количество строк таблицы, возвращенных оператором SELECT курсора
- имя_курсора%FOUND — Позволяет проверить, была ли успешной последняя попытка получения записи из курсора. Если запись была выбрана, то возвращается значение TRUE
- имя_курсора%NOTFOUND — Противоположен атрибуту FOUND. Если записей больше не найдено, возвращается значение TRUE
Записи PL/SQL
Запись PL/SQL— это набор данных базовых типов. К ней можно обращаться, как к единому целому. Для доступа к отдельным полям записи применяется нотация имя_записи_имя_поля, которую вы уже использовали для столбцов таблицы. Записи могут иметь один из трех типов, перечисленных ниже; вы можете объявлять переменные, имеющие тип записи.
- Основанные на таблице (table-based) Эти записи имеют поля, совпадающие по имени и типу со столбцами таблицы. Если курсор выбирает всю строку — например, оператором SELECT * FROM некоторая_таблица — то возвращаемые им записи можно непосредственно копировать в переменную, имеющую тип записи, основанной на таблице некоторая_таблица.
- Основанные на курсоре (cursor-based) Поля этих записей совпадают по имени, типу и порядку с заключительным списком столбцов в курсорном операторе SELECT.
- Определенные программистом (programmer-defined) Это записи, тип которых определяете вы сами.
Использование команд OPEN, FETCH и CLOSE
Команды открытия курсора, выборки из курсора и закрытия курсора имеют следующий синтаксис:
OPEN имя курсора ;
FETCH имя _ курсора INTO переменная _ или _ список _ переменных ;
CLOSE имя _ курсора ;После открытия курсор содержит набор записей, если в результате успешного выполнения оператора SELECT из базы данных были выбраны заданные строки. Каждая команда FETCH удаляет запись из открытого курсора и перемещает ее содержимое либо в переменную PL/SQL, тип записи которой совпадает с типом записи курсора, либо в группу переменных PL/SQL, где каждая переменная в списке совпадает по типу с соответствующим полем в записи курсора. Перед тем как пытаться выбрать из курсора очередную запись, следует проверить с помощью атрибутов FOUND и NOTFOUND, есть ли в нем еще записи. Выборки из пустого курсора будут все время давать последнюю запись, не приводя к ошибке. Не забывайте проверять атрибуты FOUND и NOTFOUND при использовании FETCH. Фактическая обработка записей из курсора обычно выполняется внутри цикла. При написании такого цикла неплохо начать с проверки, была ли найдена запись в курсоре. Если да, можно продолжать необходимую обработку; в противном случае следует выйти из цикла. То же самое можно сделать более коротким путем, использовав курсорный цикл FOR. При этом PL/SQL будет осуществлять открытие, выборку и закрытие без вашего участия.
Курсорный цикл FOR
Синтаксис курсорного цикла FOR имеет следующий вид:
FOR запись _ курсора IN имя _ курсора LOOP
Этот цикл выбирает записи из курсора в переменную типа запись_курсора. Поля записи_курсора можно использовать для доступа к данным из операторов PL/SQL, выполняемых в цикле. Когда все записи выбраны, цикл завершается. Для удобства открытие и закрытие курсора производится автоматически. Попытавшись выбрать запись из неоткрытого курсора, вы получите сообщение in valid cursor (недействительный курсор). Если не закрывать курсоры, то в конце концов количество открытых курсоров достигнет максимальной величины, допускаемой системой.
Конструкция WHERE CURRENT OF
Когда курсор открывается для обновления или удаления выбранных записей, можно использовать конструкцию WHERE CURRENT OF имя_курсора для доступа к таблице и строке, которые соответствуют последней записи, выбранной в конструкции WHERE оператора UPDATE или DELETE.
Обработка ошибок
В языке PL/SQL ошибки всех видов интерпретируются как исключения — ситуации, которые не должны возникать при нормальном выполнении программы.
К числу исключений относятся:- ошибки, генерируемые системой (например, нехватка памяти или повторяющееся значение индекса);
- ошибки, вызванные действиями пользователя;
- предупреждения, выдаваемые приложением пользователю.

PL/SQL перехватывает ошибки и реагирует на них при помощи так называемых обработчиков исключений. Механизм обработчиков исключений позволяет четко отделить код обработки ошибок от основной логики программы, а также дает возможность реализовать обработку ошибок, управляемую событиями. Независимо от того, как и по какой причине возникло конкретное исключение, оно всегда обрабатывается одним и тем же обработчиком в разделе исключений.
При возникновении ошибки — как системной, так и ошибки в приложении — в PL/SQL инициируется исключение. В результате выполнение блока прерывается, и управление передается для обработки в раздел исключений текущего блока, если он имеется. После обработки исключения возврат в тот блок, где исключение было инициировано, невозможен, поэтому управление передается во внешний блок.
Схема передачи управления при возникновении исключения:Существует два типа исключений:
- Системное исключение определяется в Oracle и обычно инициируется исполняемым ядром PL/SQL, обнаружившим ошибку. Одним системным исключениям присваиваются имена (например, NO_DATA_FOUND), другие ограничиваются номерами и описаниями.
- Исключение, определяемое программистом, актуально только для конкретного приложения. Имя исключения можно связать с конкретной ошибкой Oracle с помощью директивы компилятора EXCEPTION_INIT или же назначить ошибке номер и описание процедурой RAISE_APPLICATION_ERROR.
Исключения
Исключение — это состояние ошибки, которое активизируется — или возбуждается — при возникновении некоторой проблемы. Существует много разных исключений, каждое из которых связано с определенным типом проблем. При возникновении исключительной ситуации выполнение кода останавливается на операторе, который возбудил исключение, и управление передается той части блока, которая обрабатывает это исключение. Если блок не содержит выполняемой секции, PL/SQL пытается найти выполняемую секцию во включающем базовом блоке (enclosing basic block), т.е. в блоке, который является внешним по отношению к коду, возбудившему исключение. Если в непосредственном включающем блоке отсутствует обработчикданного исключения, то поиск продолжается в блоках следующих уровней, пока не будет найден подходящий обработчик, а если его найти не удается, то выполнение программы прекращается с выдачей сообщения о необрабатываемой ошибке. Часть блока, предназначенная для обработки исключений, — это идеальное место для выдачи информативных сообщений об ошибках и выполнения очистки (cleanup), позволяющей избавиться от всего, что могло бы в дальнейшем вызвать путаницу или проблемы. Если исключение было возбуждено в ходе выполнения процедуры, вставляющей строки в таблицу, то типичная процедура очистки может включать в себя оператор ROLLBACK. После того как управление было передано обработчику исключения, оно уже не возвращается оператору, ставшему причиной этого исключения. Вместо этого управление передается оператору включающего базового блока, который следует сразу за вызовом вложенного блока или процедуры/функции.
Системные исключения
В PL/SQL можно выдавать пользователям информацию об ошибке двумя способами. Первый способ — использовать команду SQLCODE, которая возвращает код ошибки. Этот код представляет собой отрицательное число, обычно равное номеру ошибки ORA, которая выводится при завершении приложения, если исключение осталось необработанным. Второй способ — возвращать текстовое сообщение, описывающее ошибку. Неудивительно, что соответствующая команда называется SQLERRM. В обработчике исключения можно использовать как SQLCODE, так и SQLERRM. Замечание: не у всех системных исключений есть имена. Системные исключения:
- CURSOR_ALREADY_OPEN — Попытка открыть уже открытый курсор;
- DUP_VAL_ON_INDEX — Попытка вставить повторяющееся значение в столбец, имеющий уникальный индекс, а следовательно, ограничение уникальности;
- INVALID_CURSOR — Попытка применить команду FETCH к неоткрытому курсору или попытка закрыть курсор, который не открывался;
- NO_DATA_FOUND — Попытка выполнить SELECT INTO, когда SELECT возвращает нулевое количество строк, а также другие причины;
- PROGRAM_ERROR — Внутренняя ошибка. Обычно означает, что вам нужно обратиться в службу поддержки Oracle;
- STORAGE_ERROR — Программе не хватает системной памяти;
- TIME_OUT_ON_RESOURCE — Программа слишком долго ожидала доступности некоторого ресурса;
- TOO_MANY_ROWS — SELECT INTO в PL/SQL вернул более одной строки;
- VALUE_ERROR — PL/SQL встретил неправильное преобразование или усечение данных, или неправильное ограничение на данные;
- ZERO_DMDE — Попытка деления на нуль;
- OTHERS — Все прочие исключения и внутренние ошибки, которые не охватываются исключениями, определенными в базовом блоке. Используется в тех случаях, когда вы точно не знаете, какое именованное исключение предстоит обрабатывать, и хотите обрабатывать любые возбуждаемые исключения.
Исключения, определяемые программистом
Одной из удобных возможностей PL/SQL является то, что он позволяет вам определять свои собственные исключения. При возбуждении и обработке они должны именоваться и объявляться аналогично любым другим элементам PL/SQL. Исключение объявляется в секции объявлений. Аналогично любой другой объявленной там переменной, исключение действительно только для данного блока. Вы можете использовать свои собственные исключения для обработки ошибок, которые система не обнаруживает или не считает за ошибки.
Схема сложного запроса PL/SQL с использованием временных таблиц
Ниже рассмотрена схема получения результирующей таблицы в Oracle Database, используя временные таблицы.

