- •ВВЕДЕНИЕ
- •1. ВВЕДЕНИЕ В PL/SQL
- •1.1. ОПИСАНИЕ PL/SQL
- •1.2. ПРЕИМУЩЕСТВА PL/SQL
- •2. КОМАНДЫ DATA DEFINITION LANGUAGE (DDL)
- •2.1. ОСНОВНЫЕ ОБЪЕКТЫ ORACLE
- •2.2. ТАБЛИЦЫ
- •2.5. ИЗМЕНЕНИЯ ОБЬЕКТОВ
- •2.3. ПРЕДСТАВЛЕНИЕ (VIEW)
- •2.4. ИНДЕКС
- •КОНТРОЛЬНЫЕ ВОПРОСЫ К ГЛАВЕ 2
- •3. ЯЗЫК ORACLE SQL
- •3.3. ВЫБОРКА
- •3.4. ОБРАБОТКА ОШИБОК
- •3.5. ВЫРАЖЕНИЯ
- •КОНТРОЛЬНЫЕ ВОПРОСЫ К ГЛАВЕ 3
- •4. ЯЗЫК PL/SQL
- •4.1. ТИПЫ ДАННЫХ PL/SQL
- •4.2. СТРУКТУРА ПРОГРАММЫ НА PL/SQL
- •4.3. УПРАВЛЕНИЕ ВЫПОЛНЕНИЕМ ПРОГРАММЫ
- •4.4. УЧЕБНАЯ БАЗА ДАННЫХ
- •4.5. КУРСОРЫ
- •4.6. ОБРАБОТКА ИСКЛЮЧИТЕЛЬНЫХ СИТУАЦИЙ
- •4.7. СОЗДАНИЕ ПОЛЬЗОВАТЕЛЬСКИХ ПРОЦЕДУР И ФУНКЦИЙ
- •4.8. ПАКЕТЫ PL/SQL
- •4.9. ТРИГГЕРЫ БАЗЫ ДАННЫХ
- •ЗАКЛЮЧЕНИЕ
- •СПИСОК ЛИТЕРАТУРЫ
106). Для преобразования числа в строку использовать встроенную функцию
TO_CHAR(число).
4.4.УЧЕБНАЯ БАЗА ДАННЫХ
Вследующих разделах будем рассматривать PL/SQL на примере следующей базы данных (табл. 4.1 – 4.6).
|
Таблица 4.1. Отношение STUDENT (Студент) |
|
ST_ID |
– идентификатор студента |
|
SURNAME |
– фамилия студента |
|
NAME |
– имя студента |
|
STIPEND |
– стипендия, которую получает студент |
|
KURS |
– курс, на котором учится студент |
|
CITY |
– город, в котором живет студент |
|
BIRTHDAY |
– дата рождения студента |
|
FAC_ID |
– идентификатор факультета, на котором учится студент |
|
Таблица 4.2. Отношение LECTURE (Преподаватель) |
||
LECT_ID |
– идентификатор преподавателя |
|
SURNAME |
– фамилия преподавателя |
|
NAME |
– имя преподавателя |
|
FAC_ID |
– идентификатор факультета, на котором работает |
|
|
|
преподаватель |
Таблица 4.3. Отношение SUBJECT (Предмет обучения) |
||
SUBJ_ID |
– |
идентификатор предмета обучения, SUBJ_NAME – на- |
|
|
именование предмета обучения |
HOUR |
– |
количество часов, отводимых на изучение предмета |
SEMESTR |
– семестр, в котором изучается данный предмет |
|
Таблица 4.4. Отношение UNIVERCITY (Факультеты) |
||
FAC_ID |
– идентификатор факультета |
|
FAC_NAME |
– название факультета |
|
RATING |
– рейтинг факультета |
|
52
Таблица 4.5. Отношение EXAM_MARKS (Экзаменационные оценки)
EXAM_ID |
– идентификатор экзамена |
ST_ID |
– идентификатор студента |
SUBJ_ID |
– идентификатор предмета обучения |
MARK |
– экзаменационная оценка |
EXAM_DATE |
– дата экзамена |
|
Таблица 4.6. Отношение SUBJLECT |
|
(Учебные дисциплины преподавателей) |
LECT_ID |
– идентификатор преподавателя, |
SUBJ_ID |
– идентификатор предмета обучения |
4.5. КУРСОРЫ
Ключевым понятием языка PL/SQL является курсор.
Для выполнения предложений SQL и хранения их результатов ORACLE использует рабочие области, называемые ЛИЧНЫМИ ОБЛАСТЯМИ SQL.
Конструкт PL/SQL, называемый КУРСОРОМ, позволяет вам обращаться к личной области SQL по имени и извлекать из нее информацию.
Есть два вида курсоров: НЕЯВНЫЕ и ЯВНЫЕ. PL/SQL неявно объявляет курсор для любого предложения манипулирования данными SQL, в том числе для запроса, возвращающего только одну строку.
Для запросов, возвращающих более одной строки, вы можете явно объявить курсор, чтобы обрабатывать возвращаемые строки по одной.
Таким образом, каждое SQL-утверждение, выполняемое сервером ORACLE, имеет индивидуальный курсор, связанный с:
−неявным курсором, объявленным для всех DML-утверждений;
−явным курсором, объявленным и поименованным программистом. Явный курсор – это поименованный запрос, содержащий некоторое фик-
сированное число строк в выборке. Чаще всего, курсор содержит данные одной строки выбираемой таблицы. По существу, курсор является окном, через которое пользователь получает доступ к информации базы данных. Курсоры, в частности, могут использоваться для присваивания конкретных значений переменным программы.
Объявление курсора:
CURSOR cursor_name IS select_statement;
53
Например:
DECLARE CURSOR c1 IS
SELECT empno, ename, job FROM emp WHERE deptno = 20;
Множество строк, возвращаемых многострочным запросом, называется АКТИВНЫМ МНОЖЕСТВОМ. Его размер равен числу строк, удовлетворяющих вашим условиям поиска. Как показывает рис. 1.3, явный курсор «указывает» на текущую строку в активном множестве. Это позволяет вашей программе обрабатывать строки по одной за раз.
Обработка многострочного запроса напоминает обработку файла. Например, программа на языке COBOL открывает файл, обрабатывает записи, а затем закрывает файл. Аналогично, программа PL/SQL открывает курсор, обрабатывает строки, возвращенные запросом, а затем закрывает курсор. Точно так же, как указатель файла отмечает текущую позицию в открытом файле, курсор отмечает текущую позицию в активном множестве.
Рассмотрим подробнее работу явного курсора:
−DECLARE – создаёт именованную SQL-область;
−OPEN – определяет активное множество;
−FETCH – передаёт текущий ряд в переменную;
−EMPTY – проверка на существование ряда, возврат к FETCH, если ряды существуют;
−CLOSE – реализовать активное множество.
При этом должны выполняться следующие правила:
−нельзя включать INTO в предложение курсора;
−если требуется использовать последовательность, то необходимо применить ORDER BY в предложении курсора.
Запрос: SELECT empno, ename, job FROM emp WHERE deptno = 20;
Активное множество:
|
7369 |
SMITH |
CLERK |
|
|
|
|
|
|
|
7566 |
JONES |
MANAGER |
|
|
|
|
|
|
Курсор –––> |
7788 |
SCOTT |
ANALYST |
Текущая строка |
|
|
|
|
|
|
7876 |
ADAMS |
CLERK |
|
|
|
|
|
|
|
7902 |
FORD |
ANALYST |
|
|
|
|
|
|
Рис. 4.1. Обработка запроса
54
OPEN Курсор –––> Активное множество
FETCH |
Курсор –––> |
7369 |
SMITH |
CLERK |
Текущая строка |
|
|
|
|
|
|
|
|
7566 |
JONES |
MANAGER |
|
|
|
|
|
|
|
|
|
7788 |
SCOTT |
ANALYST |
|
|
|
|
|
|
|
|
|
7876 |
ADAMS |
CLERK |
|
|
|
|
|
|
|
|
|
7902 |
FORD |
ANALYST |
|
|
|
|
|
|
|
CLOSE Курсор –––>
Рис. 4.2. Управление курсором
Предложение OPEN выполняет запрос, ассоциированный с курсором, идентифицирует активное множество и позиционирует курсор перед его первой строкой. Предложение FETCH извлекает текущую строку и продвигает курсор к следующей строке. После того, как обработана последняя строка, предложение CLOSE закрывает курсор.
Рассмотрим пример доступа к информации, хранимой в базе данных, с использованием курсоров. Пусть в базе данных хранится таблица LECTURE, сформированная предложениями:
CREATE TABLE LECTURE
(LECT_ID NUMBER, SURNAME VARCHAR2(30), NAME VARCHAR2(10), FAC_ID NUMBER);
INSERT INTO LECTURE VALUES(1, 'Иванов’, 'Иван’, 100); INSERT INTO LECTURE VALUES(2, 'Петров', 'Петр’, 400); INSERT INTO LECTURE VALUES(3, 'Сидоров', 'Юрий’, 100);
Опишем курсор Cur1, ориентированный на получение данных из таблицы
LECTURE: DECLARE
CURSOR Curl IS SELECT * FROM LECTURE;
Первым шагом, необходимым для работы с курсором, является открытие курсора, которое выполняется командой:
OPEN Curl;
Выборка данных из курсора может быть выполнена в набор переменных подходящих типов, командой FETCH, имеющей следующий синтаксис:
FETCH cursor_name INTO [fvariablel, variable2,...] |
[record_name];
55
При этом должны соблюдаться следующие правила:
−значения текущей строки записываются в переменные;
−команда FETCH должна содержать то же самое количество переменных, которое содержит и курсор;
−каждая переменная должна соответствовать колонкам.
Например:
FETCH Curl INTO Argl, Arg2, Arg3, Arg4;
Полностью процедура получения данных из таблицы LECTURE представлена в примере.
Пример 4.17.
SQL> set serveroutput on;
SQL> set echo on;
SQL> set terrnout on; SQL> DECLARE
Argl NUMBER; |
– Переменная для первого аргумента |
Arg2 VARCHAR2(30); |
– Переменная для второго аргумента |
АгgЗ VARCHAR2(10); |
– Переменная для третьего аргумента |
Arg4 NUMBER; |
– Переменная для четвёртого аргумента |
CURSOR Curl IS SELECT * FROM LECTURE; – Определение кур-
сора |
|
BEGIN |
|
OPEN Curl; |
-- Курсор должен быть открыт |
FOR I IN 1..3 |
LOOP |
FETCH Curl INTO Argl,Arg2, Arg3,Arg4;
DBMSJDUTPUT.PUT_LINE(TO_CHAR(Argl); END LOOP;
CLOSE Cur1; END;
/
Вданной программе неудачно управление счётчиком, поскольку цикл настроен на получение конкретного числа строк, которых может и не быть в таблице.
ВPL/SQL для курсоров предусмотрены специальные методы %NOTFOUND и %FOUND, принимающие противоположные булевские значения. Метод %NOTFOUND возвращает значение TRUE, если выборка в курсор пустая, т.е. не содержит строки. После открытия курсора, но до первой ко-
манды FETCH, методы %FOUND.
%NOTFOUND принимают неопределённое значение (UNKNOWN). Незнание этого факта может привести к достаточно распространенной ошибке. При организации цикла с использованием оператора WHILE и выполнением
56
проверки на истинность %FOUND на входе, цикл не будет выполнен ни разу, несмотря на наличие данных в таблице.
Метод %ROWCOUNT возвращает число строк, выбранных после открытия курсора. Бывает полезно использование метода %ISOPEN логического типа, возвращающего TRUE, если курсор открыт: этот метод применяется перед использованием команды FETCH для проверки – открыт ли курсор или нет.
Обратите внимание на повторный вывод последней строки. Попытайтесь исправить организацию цикла для устранения повторного вывода.
Курсор может содержать параметр, синтаксис такого курсора имеет следующий вид:
− 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');
Оператор определения курсора может содержать параметрический запрос. Значения параметра задаются при открытии курсора.
После выбора всех строк из таблицы курсор должен быть закрыт, синтаксис команды:
CLOSE cursor name;
Если возникнет необходимость, курсор может быть повторно открыт, однако, после закрытия курсора нельзя пользоваться командой FETCH.
В большинстве случаев, требующих явного курсора, вы можете использовать курсорные циклы FOR вместо предложений OPEN, FETCH и CLOSE, чтобы упростить кодирование. Курсорный цикл FOR неявно объявляет индекс своего цикла как запись %ROWTYPE, открывает курсор, итеративно извлекает строки данных из активного множества в поля записи, и закрывает курсор после того, как все строки обработаны.
Базовый синтаксис:
FOR record_name IN {cursor_name | (select_expr) } LOOP
. . . .
END LOOP;
57
