Два критерия профессионализма программирования Oracle: употребление ссылки на курсор в программеВладимир Пржиялковский
Церковь была отворена, за оградой стояло несколько саней; Содержание
АннотацияРассматриваются ссылки на курсор, представляющие собой инструмент продвинутого программирования в Oracle. Приводятся примеры работы через ссылки на курсор в программах на PL/SQL и Java и в SQL*Plus. Ссылки на курсорВ пору моего обучения в техническом ВУЗе люди, как и сейчас, были склонны называть себя как угодно, и в народе бытовал критерий настоящего математика. Право им назваться отдавалось тому, кто знал, что такое поле Галуа. Так и не ставши математиком, не берусь судить о корректности этого критерия (сдается, он ребяческий), однако, занимаясь Oracle, могу предложить другой критерий профессионализма: для программиста этой СУБД. В диалекте SQL, придуманном фирмой Oracle, есть много разных конструкций, не всякому известных; например, аналитические функции, или же средства для работы с рукотворными объектами. Но это вещи специфические, не каждому программисту потребные, а вот ссылки на курсор - явление безусловно общего характера. Ссылка на курсор дает возможность не заводить структуры курсора (CURSOR … IS …) в клиентской программе, а ограничиться в ней выделением памяти только для адреса курсора, в то время как сам курсор будет располагаться целиком в СУБД. Программист способен прожить и без ссылок на курсор, однако те могут дать программам заметные конструктивные выгоды:
Поскольку принципиально для программирования ссылки на курсоры не нужны, большинство разработчиков обходится обычным способом общения с СУБД. Выгоды же извлекают программисты, которых и можно в данном контексте признать профессионалами. Ссылки на курсор реализованы в Oracle программно и в SQL. В программе они реализуются в виде специальной переменной, и именно этот вариант показан в этой статье. Клиентскими средами будут выступать PL/SQL, SQL*Plus и Java. Описание ссылки на курсор и использование в PL/SQLНа каком бы языке вы не общались с БД посредством ссылки на курсор, без программирования на PL/SQL не обойтись. Формальная сторона работы со ссылкой на курсор в PL/SQL обставлена просто. Во-первых, чтобы завести в PL/SQL переменную-ссылку на курсор, нужно сначала описать ее тип. Это делается в разделе описания с помощью предложения TYPE: TYPE имя_типа_ссылки_на_курсор IS REF CURSOR [RETURN тип_записи ]; Если конструкция RETURN присутствует, ссылка на курсор называется строгой ; если нет - нестрогой . Нестрогая может ссылаться на любой курсор (запрос), а строгая - только на тот, что возвращает результат указанного типа. Пример описания обоих типов ссылки на курсор: DECLARE TYPE departments_curtype IS REF CURSOR RETURN dept%ROWTYPE; BEGIN NULL; END; Открытие курсора с помощью переменной-ссылки на курсор: OPEN ссылка_на_курсор FOR предложение_SELECT ; Команды FETCH и CLOSE используются как обычно, только вместо имени курсора указываем имя ссылки на курсор. Во-вторых, для удобства программирования поддерживается "системный" тип SYS_REFCURSOR нестрогой ссылки на курсор. Так, в блоке выше, в разделе описания можно было бы не приводить предложение TYPE, а сразу сказать: generic_curvar SYS_REFCURSOR; Тип SYS_REFCURSOR сокращает текст программы, а иногда позволяет и обойтись без создания служебного пакета (пример чего в этой статье не рассматривается). Создание пакета в PL/SQLПриводимые ниже примеры в каждой из трех сред программирования будут использовать для доступа к БД через ссылку на курсор один и тот же пакет. В реальной жизни именно на подобный пакет и ляжет описание требуемой программной логики. Тут же он во имя наглядности устроен максимально просто, (почти) безо всякой программно-прикладной логики, но это обстоятельство и обеспечивает ему универсальность. Выдадим в SQL*Plus: CONNECT scott/tiger CREATE OR REPLACE PACKAGE generic_ref_cursor AS CREATE OR REPLACE PACKAGE BODY generic_ref_cursor AS В реальной практике такому выхолощенному пакету вполне может найтись свое место, однако часто будут использоваться и другие, общие с приведенным выше только тем, что
Остальное регламентируется исключительно логикой приложения и организации программы. Пример программирования в PL/SQLВ этом примере с помощью нашего пакета открываем курсор и передаем ссылку на курсор в программу. Извлечение результатов предложений SELECT выполняется отдельными процедурами, причем для результатов с разной структурой мы вынуждены предусмотреть разные процедуры извлечения. Это - плата за минимализм и общность пакета. Выдадим в SQL*Plus: SET SERVEROUTPUT ON DECLARE PROCEDURE fetchandclose ( rc IN sys_refcursor ) IS BEGIN DBMS_OUTPUT.PUT_LINE ( '' ); LOOP FETCH rc INTO somename; EXIT WHEN rc%NOTFOUND; DBMS_OUTPUT.PUT_LINE ( somename ); END LOOP; CLOSE rc; END; PROCEDURE fetch2andclose ( rc IN sys_refcursor ) IS BEGIN DBMS_OUTPUT.PUT_LINE ( '' ); LOOP FETCH rc INTO somename, somenumber; EXIT WHEN rc%NOTFOUND; DBMS_OUTPUT.PUT_LINE ( RPAD ( somename, 10, ' ' ) // somenumber ); END LOOP; CLOSE rc; END; BEGIN generic_ref_cursor.get_ref_cursor ( 'SELECT dname FROM dept', lrc ); generic_ref_cursor.get_ref_cursor ( 'SELECT job, sal FROM emp', lrc ); (Чтобы не усложнять пример, результат на экране почти не оформляется). Обратим внимание: программам, обрабатывающим по общей схеме однотипные курсоры, мы передаем не тексты запроса, а ссылки на уже открытый и динамически (а не статически, как в случае его определения в отдельном пакете) сформированный курсор. Пример программирования в SQL*PlusSQL*Plus позволяет заводить собственные переменные, в том числе и типа нестрогой ссылки на курсор. Открывается курсор, как и в примере выше, нашим пакетом, а вот извлечение возможно обычной командой PRINT. Эта команда умеет распознавать структуру фактического курсора, что очень удобно для работы. Выдадим в SQL*Plus: VARIABLE refcur REFCURSOR BEGIN ( 'SELECT ename, sal FROM emp', :refcur ); END; PRINT refcur BEGIN ( 'SELECT * FROM emp', :refcur ); END; PRINT refcur В отличие от предыдущего примера команда PRINT закрывает курсор, так что вторичная выдача PRINT refcur приведет к ошибке. Пример программирования в JavaВ клиентской программе на Java обращаться к БД через ссылку на курсор можно с помощью собственных расширений, сделанных фирмой Oracle в реализации ею драйвера JDBC. В программе ниже предполагается имя СУБД MYDB. Обратите внимание, что текст с запросом SQL передается нашему пакету объектом класса CallableStatement, а извлечение в программу ссылки на курсор делается после приведения этого объекта к сугубо Oracle'овскому классу OracleCallableStatement. Получение в программу ссылки на курсор соответствует формированию объекта класса ResultSet, обработка которого делается стандартно. Выдача второго запроса в программе ниже демонстрирует возможность использования одного и того же пакета для получения результата разной структуры. Очевидно, по своей гибкости эта техника находится посередине между тем, что имеется в PL/SQL и в SQL*Plus. Подготовим файл GenericRefCursor.java:
В ОС оттранслируем класс GenericRefCursor и выполним программу: >javac GenericRefCursor.java Ограничения использования ссылки на курсорМысли, возникающие по поводу возможного использования ссылок на курсор в программе, несколько осаждаются существующими ограничениями, часть которых, если вдуматься, имеют свою логику. Как упоминалось, ссылки на курсор не представлены типом SQL (до некоторой степени это естественно), и не могут храниться в качестве переменных пакета PL/SQL. Более полно:
Ссылки по теме |