В этой статье есть несколько проблем. Помогите улучшить ее или обсудите эти проблемы на странице обсуждения . ( Узнайте, как и когда удалять эти сообщения )
|
PL/SQL ( Procedural Language for SQL ) — это процедурное расширение Oracle Corporation для SQL и реляционной базы данных Oracle . PL/SQL доступен в Oracle Database (начиная с версии 6 — хранимые процедуры/функции/пакеты/триггеры PL/SQL с версии 7), базе данных TimesTen в памяти (начиная с версии 11.2.1) и IBM Db2 (начиная с версии 9.7). [1] Oracle Corporation обычно расширяет функциональность PL/SQL с каждым последующим выпуском Oracle Database.
PL/SQL включает в себя элементы процедурного языка, такие как условия и циклы , и может обрабатывать исключения (ошибки времени выполнения). Он позволяет объявлять константы и переменные , процедуры, функции, пакеты, типы и переменные этих типов, а также триггеры. Поддерживаются массивы с использованием коллекций PL/SQL. Реализации, начиная с версии 8 Oracle Database, включают функции, связанные с объектно-ориентированным подходом . Можно создавать единицы PL/SQL, такие как процедуры, функции, пакеты, типы и триггеры, которые хранятся в базе данных для повторного использования приложениями, использующими любой из программных интерфейсов Oracle Database.
Первая публичная версия определения PL/SQL [2] появилась в 1995 году. Она реализует стандарт ISO SQL/PSM . [3]
Основная особенность SQL (непроцедурный) является также его недостатком: операторы управления ( принятие решений или итеративное управление ) не могут быть использованы, если должен использоваться только SQL. PL/SQL предоставляет функциональность других процедурных языков программирования, такую как принятие решений, итерация и т. д. Программная единица PL/SQL — это одно из следующего: анонимный блок PL/SQL, процедура , функция , спецификация пакета , тело пакета, триггер, спецификация типа, тело типа, библиотека. Программные единицы — это исходный код PL/SQL, который разрабатывается, компилируется и в конечном итоге выполняется в базе данных. [4]
Базовой единицей исходной программы PL/SQL является блок, который группирует связанные объявления и операторы. Блок PL/SQL определяется ключевыми словами DECLARE, BEGIN, EXCEPTION и END. Эти ключевые слова делят блок на декларативную часть, исполняемую часть и часть обработки исключений. Раздел объявлений является необязательным и может использоваться для определения и инициализации констант и переменных. Если переменная не инициализирована, то по умолчанию она имеет значение NULL . Необязательная часть обработки исключений используется для обработки ошибок времени выполнения. Требуется только исполняемая часть. Блок может иметь метку. [5]
Например:
<<label>> -- это необязательно DECLARE -- этот раздел необязателен number1 NUMBER ( 2 ); number2 number1 %TYPE := 17 ; -- значение по умолчанию text1 VARCHAR2 ( 12 ) := ' Hello world ' ; text2 DATE := SYSDATE ; -- текущая дата и время BEGIN -- этот раздел обязателен, должен содержать хотя бы один исполняемый оператор SELECT street_number INTO number1 FROM address WHERE name = 'INU' ; EXCEPTION -- этот раздел необязателен WHEN OTHERS THEN DBMS_OUTPUT . PUT_LINE ( 'Код ошибки ' || TO_CHAR ( sqlcode )); DBMS_OUTPUT . PUT_LINE ( 'Сообщение об ошибке ' || sqlerrm ); END ;
Символ :=
функционирует как оператор присваивания для сохранения значения в переменной.
Блоки могут быть вложенными, т. е. поскольку блок является исполняемым оператором, он может появляться в другом блоке везде, где допускается исполняемый оператор. Блок может быть отправлен в интерактивный инструмент (такой как SQL*Plus) или встроен в программу Oracle Precompiler или OCI . Интерактивный инструмент или программа запускает блок один раз. Блок не хранится в базе данных, и по этой причине он называется анонимным блоком (даже если у него есть метка).
Назначение функции PL/SQL обычно заключается в вычислении и возврате одного значения. Это возвращаемое значение может быть одним скалярным значением (например, числом, датой или строкой символов) или одной коллекцией (например, вложенной таблицей или массивом). Пользовательские функции дополняют встроенные функции, предоставляемые корпорацией Oracle. [6]
Функция PL/SQL имеет вид:
CREATE OR REPLACE FUNCTION < имя_функции > [( объявления входных / выходных переменных )] RETURN return_type [ AUTHID < CURRENT_USER | DEFINER > ] < IS | AS > -- заголовок часть количество номер ; -- блок объявлений BEGIN -- исполняемая часть < блок PL / SQL с оператором возврата > RETURN < возвращаемое_значение > ; [ Исключение отсутствует ] RETURN < возвращаемое_значение > ; END ;
Конвейерные табличные функции возвращают коллекции [7] и принимают вид:
CREATE OR REPLACE FUNCTION < имя_функции > [ ( объявления входных / выходных переменных )] RETURN тип_возврата [ AUTHID < CURRENT_USER | DEFINER > ] [ < AGGREGATE | PIPELINED > ] < IS | USING > [ блок объявлений ] BEGIN < блок PL / SQL с оператором возврата > PIPE ROW < тип возврата > ; RETURN ; [ блок исключений ] PIPE ROW < тип возврата > ; RETURN ; END ;
Функция должна использовать только тип параметра IN по умолчанию. Единственным выходным значением функции должно быть возвращаемое ею значение.
Процедуры напоминают функции тем, что они являются именованными программными единицами, которые могут вызываться повторно. Основное отличие состоит в том, что функции могут использоваться в операторе SQL, тогда как процедуры не могут . Другое отличие состоит в том, что процедура может возвращать несколько значений, тогда как функция должна возвращать только одно значение. [8]
Процедура начинается с обязательной части заголовка, содержащей имя процедуры и, по желанию, список параметров процедуры. Далее следуют декларативная, исполняемая и обрабатывающая исключения части, как в анонимном блоке PL/SQL. Простая процедура может выглядеть так:
CREATE PROCEDURE create_email_address ( -- Начинается часть заголовка процедуры name1 VARCHAR2 , name2 VARCHAR2 , company VARCHAR2 , email OUT VARCHAR2 ) -- Заголовок процедуры заканчивается AS -- Начинается декларативная часть (необязательно) error_message VARCHAR2 ( 30 ) := 'Адрес электронной почты слишком длинный.' ; BEGIN -- Начинается исполняемая часть (обязательно) email := name1 || '.' || name2 || '@' || company ; EXCEPTION -- Начинается часть обработки исключений (необязательно) WHEN VALUE_ERROR THEN DBMS_OUTPUT . PUT_LINE ( error_message ); END create_email_address ;
В примере выше показана автономная процедура — этот тип процедуры создается и сохраняется в схеме базы данных с помощью оператора CREATE PROCEDURE. Процедура также может быть создана в пакете PL/SQL — это называется пакетной процедурой. Процедура, созданная в анонимном блоке PL/SQL, называется вложенной процедурой. Автономные или пакетные процедуры, сохраненные в базе данных, называются «хранимыми процедурами » .
Процедуры могут иметь три типа параметров: IN, OUT и IN OUT.
PL/SQL также поддерживает внешние процедуры через стандартный процесс базы данных Oracle ext-proc
. [9]
Пакеты — это группы концептуально связанных функций, процедур, переменных, таблиц PL/SQL и операторов записи TYPE, констант, курсоров и т. д. Использование пакетов способствует повторному использованию кода. Пакеты состоят из спецификации пакета и необязательного тела пакета. Спецификация — это интерфейс к приложению; она объявляет доступные типы, переменные, константы, исключения, курсоры и подпрограммы. Тело полностью определяет курсоры и подпрограммы и, таким образом, реализует спецификацию. Два преимущества пакетов: [10]
Триггер базы данных похож на хранимую процедуру, которую Oracle Database автоматически вызывает всякий раз, когда происходит указанное событие. Это именованный блок PL/SQL, который хранится в базе данных и может вызываться многократно. В отличие от хранимой процедуры, вы можете включать и отключать триггер, но вы не можете явно вызывать его. Пока триггер включен, база данных автоматически вызывает его, то есть триггер срабатывает, всякий раз, когда происходит его событие запуска. Пока триггер отключен, он не срабатывает.
Вы создаете триггер с помощью оператора CREATE TRIGGER. Вы указываете событие запуска в терминах операторов запуска и элемента, на который они воздействуют. Говорят, что триггер создан или определен для элемента — который является либо таблицей, либо представлением , либо схемой, либо базой данных. Вы также указываете момент времени, который определяет, срабатывает ли триггер до или после выполнения оператора запуска, и срабатывает ли он для каждой строки, на которую влияет оператор запуска.
Если триггер создан на таблице или представлении, то событие срабатывания состоит из операторов DML, а триггер называется триггером DML. Если триггер создан на схеме или базе данных, то событие срабатывания состоит либо из операторов DDL, либо из операторов операций с базой данных, а триггер называется системным триггером.
Триггер INSTEAD OF — это либо: триггер DML, созданный в представлении, либо системный триггер, определенный в операторе CREATE. База данных запускает триггер INSTEAD OF вместо запуска оператора запуска.
Триггеры могут быть написаны для следующих целей:
Основные типы данных в PL/SQL включают NUMBER, CHAR, VARCHAR2, DATE и TIMESTAMP.
имя_переменной число ([ P , S ]) := 0 ;
Чтобы определить числовую переменную, программист добавляет тип переменной NUMBER к определению имени. Чтобы указать (необязательную) точность (P) и (необязательный) масштаб (S), можно дополнительно добавить их в круглых скобках, разделенных запятой. («Точность» в этом контексте относится к числу цифр, которые может содержать переменная, а «масштаб» относится к числу цифр, которые могут следовать за десятичной точкой.)
Другие типы данных для числовых переменных включают: binary_float, binary_double, dec, decimal, double precision, float, integer, int, numeric, real, small-int, binary_integer.
имя_переменной varchar2 ( 20 ) := 'Текст' ; -- например: адрес varchar2 ( 20 ) := 'дорога с видом на озеро' ;
Чтобы определить символьную переменную, программист обычно добавляет тип переменной VARCHAR2 к определению имени. Далее в скобках следует максимальное количество символов, которое может хранить переменная.
Другие типы данных для символьных переменных включают: varchar, char, long, raw, long raw, nchar, nchar2, clob, blob и bfile.
имя_переменной дата := to_date ( '01-01-2005 14:20:23' , 'ДД-ММ-ГГГГ чч24:ми:сс' );
Переменные даты могут содержать дату и время. Время может быть опущено, но нет способа определить переменную, которая содержит только время. Типа DATETIME нет. И есть тип TIME. Но нет типа TIMESTAMP, который может содержать мелкозернистую временную метку вплоть до миллисекунды или наносекунды. Функцию TO_DATE
можно использовать для преобразования строк в значения даты. Функция преобразует первую строку в кавычках в дату, используя в качестве определения вторую строку в кавычках, например:
to_date ( '31-12-2004' , 'дд-мм-гггг' )
или
to_date ( '31-дек-2004' , 'дд-мес-гггг' , 'NLS_DATE_LANGUAGE = Американский' )
Для преобразования дат в строки используется функция TO_CHAR (date_string, format_string)
.
PL/SQL также поддерживает использование литералов даты и интервала ANSI. [11] Следующий пункт задает 18-месячный диапазон:
ГДЕ dateField МЕЖДУ ДАТОЙ '2004-12-30' - ИНТЕРВАЛ '1-6' ГОД К МЕСЯЦУ И ДАТОЙ '2004-12-30'
Исключения — ошибки во время выполнения кода — бывают двух типов: определяемые пользователем и предопределенные.
Исключения , определяемые пользователем, всегда явно вызываются программистами с помощью команд RAISE
или RAISE_APPLICATION_ERROR
в любой ситуации, когда они определяют невозможность продолжения нормального выполнения. Команда RAISE
имеет следующий синтаксис:
RAISE < имя исключения > ;
Корпорация Oracle предопределила несколько исключений, таких как , NO_DATA_FOUND
и т. д.
Каждое исключение имеет номер ошибки SQL и сообщение об ошибке SQL, связанное с ним. Программисты могут получить к ним доступ с помощью функций и .TOO_MANY_ROWS
SQLCODE
SQLERRM
Имя_переменной Имя_таблицы . Имя_столбца %type;
Этот синтаксис определяет переменную типа указанного столбца в указанных таблицах.
Программисты указывают пользовательские типы данных с помощью следующего синтаксиса:
тип data_type — запись ( field_1 type_1 := xyz , field_2 type_2 := xyz , ... , field_n type_n := xyz );
Например:
объявить тип t_address is record ( имя адрес . имя %type , улица адрес . улица %type , улица_номер_дома адрес . улица_номер_дома %type , почтовый индекс адрес . почтовый индекс %type ); v_address t_address ; начало выборка имя , улица , улица_номер_дома , почтовый индекс в v_address из адреса где rownum = 1 ; конец ;
В этом примере программы определяется собственный тип данных, называемый t_address , который содержит поля name, street, street_number и postcode .
Итак, согласно примеру, мы можем копировать данные из базы данных в поля программы.
Используя этот тип данных, программист определил переменную v_address и загрузил в нее данные из таблицы ADDRESS.
Программисты могут обращаться к отдельным атрибутам в такой структуре с помощью точечной нотации, например:
v_address.street := 'Главная улица';
Следующий фрагмент кода показывает конструкцию IF-THEN-ELSIF-ELSE. Части ELSIF и ELSE являются необязательными, поэтому можно создавать более простые конструкции IF-THEN или IF-THEN-ELSE.
ЕСЛИ x = 1 ТО последовательность_высказываний_1 ; ELSIF x = 2 ТО последовательность_высказываний_2 ; ELSIF x = 3 ТО последовательность_высказываний_3 ; ELSIF x = 4 ТО последовательность_высказываний_4 ; ELSIF x = 5 ТО последовательность_высказываний_5 ; ИНАЧЕ последовательность_высказываний_N ; КОНЕЦ ЕСЛИ ;
Оператор CASE упрощает некоторые большие структуры IF-THEN-ELSIF-ELSE.
СЛУЧАЙ КОГДА x = 1 ТОГДА последовательность_высказываний_1 ; КОГДА x = 2 ТОГДА последовательность_высказываний_2 ; КОГДА x = 3 ТОГДА последовательность_высказываний_3 ; КОГДА x = 4 ТОГДА последовательность_высказываний_4 ; КОГДА x = 5 ТОГДА последовательность_высказываний_5 ; ИНАЧЕ последовательность_высказываний_N ; КОНЕЦ СЛУЧАЯ ;
Оператор CASE можно использовать с предопределенным селектором:
СЛУЧАЙ x КОГДА 1 ТОГДА последовательность_высказываний_1 ; КОГДА 2 ТОГДА последовательность_высказываний_2 ; КОГДА 3 ТОГДА последовательность_высказываний_3 ; КОГДА 4 ТОГДА последовательность_высказываний_4 ; КОГДА 5 ТОГДА последовательность_высказываний_5 ; ИНАЧЕ последовательность_высказываний_N ; КОНЕЦ СЛУЧАЯ ;
PL/SQL называет массивы «коллекциями». Язык предлагает три типа коллекций:
Программисты должны указать верхний предел для varrays, но не для индексных таблиц или вложенных таблиц. Язык включает несколько методов коллекций , используемых для управления элементами коллекций: например, FIRST, LAST, NEXT, PRIOR, EXTEND, TRIM, DELETE и т. д. Индексные таблицы можно использовать для имитации ассоциативных массивов, как в этом примере функции memo для функции Аккермана в PL/SQL .
С помощью индексных таблиц массив может быть проиндексирован по числам или строкам. Он параллелен карте Java , которая содержит пары ключ-значение. Существует только одно измерение, и оно не ограничено.
С вложенными таблицами программист должен понимать, что вложено. Здесь создается новый тип, который может состоять из ряда компонентов. Затем этот тип может быть использован для создания столбца в таблице, и в этот столбец вложены эти компоненты.
С Varrays вам нужно понимать, что слово «переменная» в фразе «массивы переменного размера» не относится к размеру массива так, как вы могли бы подумать. Размер, с которым объявлен массив, на самом деле фиксирован. Количество элементов в массиве является переменным вплоть до объявленного размера. Тогда, возможно, массивы переменного размера не являются такими уж переменными по размеру.
Курсор — это указатель на частную область SQL, которая хранит информацию, поступающую из оператора SELECT или языка манипулирования данными (DML) (INSERT, UPDATE, DELETE или MERGE). Курсор содержит строки (одну или несколько), возвращаемые оператором SQL. Набор строк, которые содержит курсор , называется активным набором. [12]
Курсор может быть явным или неявным. В цикле FOR явный курсор должен использоваться, если запрос будет использоваться повторно, в противном случае предпочтительнее неявный курсор. Если курсор используется внутри цикла, рекомендуется использовать FETCH, когда требуется массовый сбор или динамический SQL.
Как процедурный язык по определению, PL/SQL предоставляет несколько итерационных конструкций, включая базовые операторы LOOP, циклы WHILE , циклы FOR и циклы Cursor FOR. Начиная с Oracle 7.3 был введен тип REF CURSOR, позволяющий возвращать наборы записей из хранимых процедур и функций. В Oracle 9i был введен предопределенный тип SYS_REFCURSOR, что означает, что нам больше не нужно определять собственные типы REF CURSOR.
<<parent_loop>> Операторы LOOP<<child_loop>> операторы цикла exit parent_loop when <condition> ; -- Завершает оба цикла exit when <condition> ; -- Возвращает управление в parent_loop end loop child_loop ; if <condition> then continue ; -- переходит к следующей итерации end if ; выход, когда < условие > ; КОНЕЦ ЦИКЛА parent_loop ;
[13]
Циклы можно завершить с помощью EXIT
ключевого слова или путем вызова исключения .
DECLARE var NUMBER ; BEGIN /* Примечание: переменные цикла for в PL/SQL — это новые объявления, имеющие область действия только внутри цикла */ FOR var IN 0 .. 10 LOOP DBMS_OUTPUT . PUT_LINE ( var ); END LOOP ; ЕСЛИ var IS NULL THEN DBMS_OUTPUT.PUT_LINE ( 'var is null' ) ; ИНАЧЕ DBMS_OUTPUT.PUT_LINE ( ' var is not null' ) ; КОНЕЦ IF ; КОНЕЦ ;
Выход:
0 1 2 3 4 5 6 7 8 9 10 var имеет значение null
FOR RecordIndex IN ( SELECT person_code FROM people_table ) LOOP DBMS_OUTPUT . PUT_LINE ( RecordIndex . person_code ); END LOOP ;
Циклы Cursor-for автоматически открывают курсор , считывают его данные и снова закрывают курсор.
В качестве альтернативы программист PL/SQL может заранее определить оператор SELECT курсора, чтобы (например) разрешить повторное использование или сделать код более понятным (что особенно полезно в случае длинных или сложных запросов).
DECLARE CURSOR cursor_person IS SELECT person_code FROM people_table ; BEGIN FOR RecordIndex IN cursor_person LOOP DBMS_OUTPUT . PUT_LINE ( recordIndex . person_code ); END LOOP ; END ;
Концепция person_code внутри цикла FOR выражается с помощью точечной нотации ("."):
RecordIndex . person_code
В то время как программисты могут легко встраивать операторы языка манипулирования данными (DML) непосредственно в код PL/SQL, используя простые операторы SQL, язык определения данных (DDL) требует более сложных операторов "Dynamic SQL" в коде PL/SQL. Однако операторы DML лежат в основе большинства кода PL/SQL в типичных программных приложениях.
В случае динамического SQL PL/SQL ранние версии Oracle Database требовали использования сложной DBMS_SQL
библиотеки пакетов Oracle. Однако более поздние версии ввели более простой "Native Dynamic SQL" вместе с соответствующим EXECUTE IMMEDIATE
синтаксисом.
PL/SQL работает аналогично встроенным процедурным языкам, связанным с другими реляционными базами данных . Например, Sybase ASE и Microsoft SQL Server имеют Transact-SQL , PostgreSQL имеет PL/pgSQL (который в некоторой степени эмулирует PL/SQL), MariaDB включает анализатор совместимости PL/SQL, [14] а IBM Db2 включает SQL Procedural Language, [15] который соответствует стандарту SQL/PSM ISO SQL .
Разработчики PL/SQL смоделировали его синтаксис по образцу Ada . Pascal является общим предком и для Ada , и для PL/SQL, поэтому PL/SQL также во многих аспектах напоминает Pascal. Однако структура пакета PL/SQL не похожа на базовую структуру программы Object Pascal , реализованную модулем Borland Delphi или Free Pascal . Программисты могут определять публичные и частные глобальные типы данных, константы и статические переменные в пакете PL/SQL. [16]
PL/SQL также позволяет определять классы и создавать их экземпляры как объекты в коде PL/SQL. Это напоминает использование в объектно-ориентированных языках программирования, таких как Object Pascal , C++ и Java . PL/SQL называет класс «Абстрактным типом данных» (ADT) или «Пользовательским типом» (UDT) и определяет его как тип данных Oracle SQL в отличие от определяемого пользователем типа PL/SQL, что позволяет использовать его как в Oracle SQL Engine, так и в Oracle PL/SQL engine. Конструктор и методы абстрактного типа данных написаны на PL/SQL. Полученный абстрактный тип данных может работать как класс объекта в PL/SQL. Такие объекты также могут сохраняться как значения столбцов в таблицах базы данных Oracle.
PL/SQL принципиально отличается от Transact-SQL , несмотря на поверхностное сходство. Перенос кода с одного на другой обычно требует нетривиальной работы, не только из-за различий в наборах функций двух языков, [17] , но и из-за весьма существенных различий в том, как Oracle и SQL Server справляются с параллелизмом и блокировкой .
Продукт StepSqlite — это компилятор PL/SQL для популярной небольшой базы данных SQLite , который поддерживает подмножество синтаксиса PL/SQL. В релизе Berkeley DB 11g R2 от Oracle добавлена поддержка SQL на основе популярного API SQLite путем включения версии SQLite в Berkeley DB. [18] Следовательно, StepSqlite также можно использовать как сторонний инструмент для запуска кода PL/SQL в Berkeley DB. [19]
{{cite web}}
: CS1 maint: multiple names: authors list (link)Конвейерная табличная функция [...] возвращает результирующий набор в виде коллекции [...] итеративно. [...] Когда каждая строка готова к назначению коллекции, она «выводится» из функции.
Всякий раз, когда механизм выполнения PL/SQL сталкивается с внешним вызовом процедуры, Oracle Database запускает процесс extproc. База данных передает информацию, полученную из спецификации вызова, вextproc
процесс, что помогает ему найти внешнюю процедуру в библиотеке и выполнить ее с использованием предоставленных параметров. Процессextproc
загружает динамически связанную библиотеку, выполняет внешнюю процедуру и возвращает результат обратно в базу данных.
ли Berkeley DB PL/SQL?