plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная...

48
plsql #plsql

Transcript of plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная...

Page 1: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

plsql

#plsql

Page 2: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

1

1: PLSQL 2

2

Examples 2

PLSQL 2

, 3

PLSQL 4

% TYPE % ROWTYPE. 4

5

5

2: IF-THEN-ELSE 6

6

Examples 6

IF-THEN 6

IF-THEN-ELSE 6

IF-THEN-ELSE ELSIF- 7

3: 8

Examples 8

split 8

4: 9

9

9

Examples 9

«FOR loop» 9

«FOR loop» 9

SYS_REFCURSOR 10

, 10

: 10

11

5: 12

Examples 12

Page 3: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

12

6: 13

Examples 13

PL / SQL 13

7: 15

15

Examples 15

15

15

16

17

18

, , 19

20

8: 22

22

Examples 22

22

, , 23

9: 25

25

Examples 27

27

27

28

. 28

10: 30

30

Examples 30

30

WHILE Loop 30

FOR Loop 31

Page 4: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

11: PLSQL 33

33

Examples 33

33

, 33

/ 34

12: 35

35

Examples 35

BASE_TYPE 35

MID_TYPE 36

LEAF_TYPE 37

38

13: 40

40

40

Examples 40

INSERT UPDATE 40

14: 42

42

Examples 42

GUID 42

42

44

Page 5: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

ОколоYou can share this PDF with anyone you feel could benefit from it, downloaded the latest version from: plsql

It is an unofficial and free plsql ebook created for educational purposes. All the content is extracted from Stack Overflow Documentation, which is written by many hardworking individuals at Stack Overflow. It is neither affiliated with Stack Overflow nor official plsql.

The content is released under Creative Commons BY-SA, and the list of contributors to each chapter are provided in the credits section at the end of this book. Images may be copyright of their respective owners unless otherwise specified. All trademarks and registered trademarks are the property of their respective company owners.

Use the content presented in this book at your own risk; it is not guaranteed to be correct nor accurate, please send your feedback and corrections to [email protected]

https://riptutorial.com/ru/home 1

Page 6: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

глава 1: Начало работы с PLSQL

замечания

В этом разделе представлен обзор того, что такое plsql, и почему разработчик может захотеть его использовать.

Следует также упомянуть о любых крупных предметах в рамках plsql и ссылаться на связанные темы. Поскольку Documentation for plsql является новым, вам может потребоваться создать начальные версии этих связанных тем.

Examples

Определение PLSQL

PL / SQL (язык процедур / язык структурированных запросов) является процедурным расширением Oracle Corporation для SQL и реляционной базы данных Oracle. PL / SQL

доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная с версии 11.2.1) и IBM DB2 (начиная с версии 9.7).

Базовый блок в PL / SQL называется блоком, который состоит из трех частей: декларативной части, исполняемой части и части исключения.

DECLARE <declarations section> BEGIN <executable command(s)> EXCEPTION <exception handling> END;

Объявления. Этот раздел начинается с ключевого слова DECLARE. Это необязательный раздел и определяет все переменные, курсоры, подпрограммы и другие элементы, которые будут использоваться в программе.

Исполняемые команды - этот раздел заключен между ключевыми словами BEGIN и END,

и это обязательный раздел. Он состоит из исполняемых инструкций PL / SQL программы. Он должен иметь по крайней мере одну исполняемую строку кода, которая может быть просто командой NULL, чтобы указать, что ничего не должно выполняться.

Обработка исключений - этот раздел начинается с ключевого слова EXCEPTION. Этот раздел снова является необязательным и содержит исключения (исключения), которые обрабатывают ошибки в программе.

Каждый оператор PL / SQL заканчивается точкой с запятой (;). Блоки PL / SQL могут быть

https://riptutorial.com/ru/home 2

Page 7: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

вложены в другие блоки PL / SQL с помощью BEGIN и END.

В анонимном блоке требуется только исполняемая часть блока, другие части не являются обязательными. Ниже приведен пример простого анонимного кода, который не делает ничего, кроме выполнения без сообщений об ошибках.

BEGIN NULL; END; /

Отсутствие команды excecutable приводит к ошибке, поскольку PL / SQL не поддерживает пустые блоки. Например, исключение кода ниже приводит к ошибке:

BEGIN END; /

Приложение вызовет ошибку:

END; * ERROR at line 2: ORA-06550: line 2, column 1: PLS-00103: Encountered the symbol "END" when expecting one of the following: ( begin case declare exit for goto if loop mod null pragma raise return select update while with <an identifier> <a double-quoted delimited-identifier> <a bind variable> << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge

Символ «*» в строке ниже ключевого слова «END»; означает, что блок, который заканчивается этим блоком, пуст или плохо сконструирован. Каждый блок исполнения нуждается в инструкциях, даже если он ничего не делает, как в нашем примере.

Привет, мир

set serveroutput on DECLARE message constant varchar2(32767):= 'Hello, World!'; BEGIN dbms_output.put_line(message); END; /

set serveroutput on команд set serveroutput on SQL * Plus и SQL Developer необходим для включения вывода dbms_output . Без команды ничего не отображается.

end; строка сигнализирует о завершении анонимного блока PL / SQL. Чтобы запустить код из командной строки SQL, вам может потребоваться ввести / в начале первой пустой

https://riptutorial.com/ru/home 3

Page 8: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

строки после последней строки кода. Когда вышеуказанный код выполняется в приглашении SQL, он производит следующий результат:

Hello, World! PL/SQL procedure successfully completed.

О PLSQL

PL / SQL означает расширение процедурных языков для SQL. PL / SQL доступен только как «технология разрешения» в других программных продуктах; он не существует как автономный язык. Вы можете использовать PL / SQL в реляционной базе данных Oracle, в Oracle Server и в средствах разработки приложений на стороне клиента, таких как Oracle

Forms. Вот некоторые из способов использования PL / SQL:

Чтобы создать хранимые процедуры. ,1. Чтобы создать триггеры базы данных.2. Для реализации клиентской логики в приложении Oracle Forms.3.

Чтобы связать домашнюю страницу World Wide Web с базой данных Oracle.4.

Разница между% TYPE и% ROWTYPE.

%TYPE : Используется для объявления поля с тем же типом, что и столбец указанной таблицы.

DECLARE vEmployeeName Employee.Name%TYPE; BEGIN SELECT Name INTO vEmployeeName FROM Employee WHERE RowNum = 1; DBMS_OUTPUT.PUT_LINE(vEmployeeName); END; /

% ROWTYPE: используется для объявления записи с теми же типами, что и в указанной таблице, представлении или курсоре (= несколько столбцов).

DECLARE rEmployee Employee%ROWTYPE; BEGIN rEmployee.Name := 'Matt'; rEmployee.Age := 31; DBMS_OUTPUT.PUT_LINE(rEmployee.Name); DBMS_OUTPUT.PUT_LINE(rEmployee.Age); END; /

https://riptutorial.com/ru/home 4

Page 9: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

Создать или заменить вид

В этом примере мы создадим представление. Вид в основном используется как простой способ получения данных из нескольких таблиц.

Пример 1: Просмотр с выбором на один стол.

CREATE OR REPLACE VIEW LessonView AS SELECT L.* FROM Lesson L;

Пример 2: Просмотр с помощью выбора на нескольких таблицах.

CREATE OR REPLACE VIEW ClassRoomLessonView AS SELECT C.Id, C.Name, L.Subject, L.Teacher FROM ClassRoom C, Lesson L WHERE C.Id = L.ClassRoomId;

Чтобы вызвать эти представления в запросе, вы можете использовать оператор select.

SELECT * FROM LessonView; SELECT * FROM ClassRoomLessonView;

Создать таблицу

Ниже мы создадим таблицу с тремя столбцами. В столбце Id должен быть заполнен, так что мы определяем его NOT NULL . В столбце « Contract мы также добавляем чек, чтобы разрешалось только «Y» или «N».

Если вставленная вставка и этот столбец не указаны во время вставки, то по умолчанию вставлен «N».

CREATE TABLE Employee ( Id NUMBER NOT NULL, Name VARCHAR2(60), Contract CHAR DEFAULT 'N' NOT NULL, --- CONSTRAINT p_Id PRIMARY KEY(Id), CONSTRAINT c_Contract CHECK (Contract IN('Y','N')) );

Прочитайте Начало работы с PLSQL онлайн: https://riptutorial.com/ru/plsql/topic/1962/начало-работы-с-plsql

https://riptutorial.com/ru/home 5

Page 10: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

глава 2: Заявление IF-THEN-ELSE

Синтаксис

IF [условие 1] THEN•

[инструкции для выполнения, когда условие 1 имеет значение ИСТИНА];•

ELSIF [условие 2] THEN•

[инструкции для выполнения, когда условие 2 имеет значение ИСТИНА];•

ELSE•

[инструкции для выполнения, когда оба условия 1 и условие 2 являются FALSE];•

END IF;•

Examples

IF-THEN

DECLARE v_num1 NUMBER(10); v_num2 NUMBER(10); BEGIN v_num1 := 2; v_num2 := 1; IF v_num1 > v_num2 THEN dbms_output.put_line('v_num1 is bigger than v_num2'); END IF; END;

IF-THEN-ELSE

DECLARE v_num1 NUMBER(10); v_num2 NUMBER(10); BEGIN v_num1 := 2; v_num2 := 10; IF v_num1 > v_num2 THEN dbms_output.put_line('v_num1 is bigger than v_num2'); ELSE dbms_output.put_line('v_num1 is NOT bigger than v_num2'); END IF;

https://riptutorial.com/ru/home 6

Page 11: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

END;

IF-THEN-ELSE ELSIF-

DECLARE v_num1 NUMBER(10); v_num2 NUMBER(10); BEGIN v_num1 := 2; v_num2 := 2; IF v_num1 > v_num2 THEN dbms_output.put_line('v_num1 is bigger than v_num2'); ELSIF v_num1 < v_num2 THEN dbms_output.put_line('v_num1 is NOT bigger than v_num2'); ELSE dbms_output.put_line('v_num1 is EQUAL to v_num2'); END IF; END;

Прочитайте Заявление IF-THEN-ELSE онлайн: https://riptutorial.com/ru/plsql/topic/5871/

заявление-if-then-else

https://riptutorial.com/ru/home 7

Page 12: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

глава 3: Коллекции и отчеты

Examples

Использовать коллекцию как возвращаемый тип для функции split

Необходимо указать тип; здесь t_my_list ; коллекция - TABLE OF something

CREATE OR REPLACE TYPE t_my_list AS TABLE OF VARCHAR2(100);

Вот функция. Обратите внимание: () используется как своего рода конструктор, а также ключевые слова COUNT и EXTEND которые помогают создавать и расширять вашу коллекцию;

CREATE OR REPLACE FUNCTION cto_table(p_sep in Varchar2, p_list IN VARCHAR2) RETURN t_my_list AS --- this function takes a string list, element being separated by p_sep -- as separator l_string VARCHAR2(4000) := p_list || p_sep; l_sep_index PLS_INTEGER; l_index PLS_INTEGER := 1; l_tab t_my_list := t_my_list(); BEGIN LOOP l_sep_index := INSTR(l_string, p_sep, l_index); EXIT WHEN l_sep_index = 0; l_tab.EXTEND; l_tab(l_tab.COUNT) := TRIM(SUBSTR(l_string,l_index,l_sep_index - l_index)); l_index := l_sep_index + 1; END LOOP; RETURN l_tab; END cto_table; /

Затем вы можете увидеть содержимое коллекции с помощью функции TABLE() из SQL; он может использоваться как список внутри инструкции SQL IN ( ..) :

select * from A_TABLE where A_COLUMN in ( TABLE(cto_table('|','a|b|c|d')) ) --- gives the records where A_COLUMN in ('a', 'b', 'c', 'd') --

Прочитайте Коллекции и отчеты онлайн: https://riptutorial.com/ru/plsql/topic/9779/коллекции-и-отчеты

https://riptutorial.com/ru/home 8

Page 13: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

глава 4: курсоры

Синтаксис

Курсор cursor_name: your_select_statement•

Курсор cursor_name (param TYPE) Является вашим_select_statement_using_param•FOR x in ( your_select_statement ) LOOP ...•

замечания

Объявленные курсоры сложны в использовании, и в большинстве случаев вы должны предпочитать цикл FOR . Что очень интересно в курсорах по сравнению с простыми циклами FOR , так это то, что вы можете их параметризовать.

Лучше избегать выполнения циклов с PL / SQL и курсоров вместо использования Oracle

SQL в любом случае. Однако для людей, привыкших к процедурному языку, это может быть гораздо легче понять.

Если вы хотите проверить, существует ли запись, а затем делать разные вещи в зависимости от того, существует ли запись или нет, тогда имеет смысл использовать операторы MERGE в чистых запросах ORACLE SQL вместо использования курсоров. (Обратите внимание, что MERGE доступен только в версиях Oracle> = 9i).

Examples

Параметрированный курсор «FOR loop»

DECLARE CURSOR c_emp_to_be_raised(p_sal emp.sal%TYPE) IS SELECT * FROM emp WHERE sal < p_sal; BEGIN FOR cRowEmp IN c_emp_to_be_raised(1000) LOOP dbms_Output.Put_Line(cRowEmp .eName ||' ' ||cRowEmp.sal||'... should be raised ;)'); END LOOP; END; /

Неявный курсор «FOR loop»

BEGIN FOR x IN (SELECT * FROM emp WHERE sal < 100) LOOP dbms_Output.Put_Line(x.eName ||' '||x.sal||'... should REALLY be raised :D'); END LOOP; END; /

https://riptutorial.com/ru/home 9

Page 14: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

Первое преимущество заключается в том, что нет утомительной декларации (подумайте об этом ужасном «КУРСОРЕ», которое у вас было в предыдущих версиях)

второе преимущество заключается в том, что вы сначала создаете свой запрос выбора, а затем, когда у вас есть то, что вы хотите, вы сразу можете получить доступ к полям вашего запроса ( x.<myfield> ) в вашем цикле PL / SQL

Цикл открывает курсор и выбирает по одной записи за каждый цикл. В конце цикла курсор закрывается.

Неявные курсоры быстрее, потому что работа интерпретатора возрастает по мере увеличения кода. Чем меньше кода, тем меньше работает интерпретатор.

Работа с SYS_REFCURSOR

SYS_REFCURSOR можно использовать как возвращаемый тип, когда вам нужно легко обрабатывать список, возвращенный не из таблицы, а, более конкретно, из функции:

функция, возвращающая курсорCREATE OR REPLACE FUNCTION list_of (required_type_in IN VARCHAR2) RETURN SYS_REFCURSOR IS v_ SYS_REFCURSOR; BEGIN CASE required_type_in WHEN 'CATS' THEN OPEN v_ FOR SELECT nickname FROM ( select 'minou' nickname from dual union all select 'minâ' from dual union all select 'minon' from dual ); WHEN 'DOGS' THEN OPEN v_ FOR SELECT dog_call FROM ( select 'bill' dog_call from dual union all select 'nestor' from dual union all select 'raoul' from dual ); END CASE; -- Whit this use, you must not close the cursor. RETURN v_; END list_of; /

и как его использовать:DECLARE v_names SYS_REFCURSOR;

https://riptutorial.com/ru/home 10

Page 15: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

v_ VARCHAR2 (32767); BEGIN v_names := list_of('CATS'); LOOP FETCH v_names INTO v_; EXIT WHEN v_names%NOTFOUND; DBMS_OUTPUT.put_line(v_); END LOOP; -- here you close it CLOSE v_names; END; /

Обработка КУРСОРА

Объявить курсор для сканирования списка записей•Открой это•Получить текущую запись в переменные (это увеличивает положение)•Использовать %notfound для обнаружения конца списка•Не забудьте закрыть курсор, чтобы ограничить потребление ресурсов в текущем контексте

-

DECLARE CURSOR curCols IS -- select column name and type from a given table SELECT column_name, data_type FROM all_tab_columns where table_name='MY_TABLE'; v_tab_column all_tab_columns.column_name%TYPE; v_data_type all_tab_columns.data_type%TYPE; v_ INTEGER := 1; BEGIN OPEN curCols; LOOP FETCH curCols INTO v_tab_column, v_data_type; IF curCols%notfound OR v_ > 2000 THEN EXIT; END IF; dbms_output.put_line(v_||':Column '||v_tab_column||' is of '|| v_data_type||' Type.'); v_:= v_ + 1; END LOOP; -- Close in any case IF curCols%ISOPEN THEN CLOSE curCols; END IF; END; /

Прочитайте курсоры онлайн: https://riptutorial.com/ru/plsql/topic/5303/курсоры

https://riptutorial.com/ru/home 11

Page 16: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

глава 5: Массовый сбор

Examples

Обработка объемных данных

локальные коллекции не допускаются в отдельных операторах. Следовательно, первым шагом является создание коллекции уровня схемы. Если коллекция не является уровнем схемы и используется в операторах SELECT, это приведет к появлению «PLS-00642:

локальные типы коллекций, недопустимые в операторах SQL»,

CREATE OR REPLACE TYPE table1_t IS OBJECT ( a_1 INTEGER, a_2 VARCHAR2(10) );

--Greg разрешения на сбор, чтобы он мог публично использоваться в базе данных

GRANT EXECUTE ON table1_t TO PUBLIC; CREATE OR REPLACE TYPE table1_tbl_typ IS TABLE OF table1_t; GRANT EXECUTE ON table1_tbl_typ TO PUBLIC;

- выбор данных из таблицы в коллекцию, а затем цикл по коллекции и печать данных.

DECLARE table1_tbl table1_tbl_typ; BEGIN table1_tbl := table1_tbl_typ(); SELECT table1_t(a_1,a_2) BULK COLLECT INTO table1_tbl FROM table1 WHERE ROWNUM<10; FOR rec IN (SELECT a_1 FROM TABLE(table1_tbl))--table(table1_tbl) won't give error) LOOP dbms_output.put_line('a_1'||rec.a_1); dbms_output.put_line('a_2'||rec.a_2); END LOOP; END; /

Прочитайте Массовый сбор онлайн: https://riptutorial.com/ru/plsql/topic/6855/массовый-сбор

https://riptutorial.com/ru/home 12

Page 17: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

глава 6: Модель и язык заданий

Examples

Модель присвоений в PL / SQL

Все языки программирования позволяют присваивать значения переменным. Обычно значение присваивается переменной, стоящей с левой стороны. Прототип операций общего назначения в любом современном языке программирования выглядит следующим образом:

left_operand assignment_operand right_operand instructions_of_stop

Это назначит правый операнд левому операнду. В PL / SQL эта операция выглядит так:

left_operand := right_operand;

Левый операнд всегда должен быть переменной . Правильный операнд может быть значением, переменной или функцией:

set serveroutput on declare v_hello1 varchar2(32767); v_hello2 varchar2(32767); v_hello3 varchar2(32767); function hello return varchar2 is begin return 'Hello from a function!'; end; begin -- from a value (string literal) v_hello1 := 'Hello from a value!'; -- from variable v_hello2 := v_hello1; -- from function v_hello3 := hello; dbms_output.put_line(v_hello1); dbms_output.put_line(v_hello2); dbms_output.put_line(v_hello3); end; /

Когда блок кода выполняется в SQL * Plus, на консоли выводится следующий вывод:

Hello from a value! Hello from a value! Hello from a function!

В PL / SQL есть функция, которая позволяет нам назначать «справа налево». Это можно сделать в инструкции SELECT INTO. Прототип этого узла вы найдете ниже:

https://riptutorial.com/ru/home 13

Page 18: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

SELECT [ literal | column_value ] INTO local_variable FROM [ table_name | aliastable_name ] WHERE comparison_instructions;

Этот код присваивает символьный литерал локальной переменной:

set serveroutput on declare v_hello varchar2(32767); begin select 'Hello world!' into v_hello from dual; dbms_output.put_line(v_hello); end; /

Когда блок кода выполняется в SQL * Plus, на консоли выводится следующий вывод:

Hello world!

Назначение «справа налево» не является стандартом , но это ценная функция для программистов и пользователей. Обычно он используется, когда программист использует курсоры в PL / SQL - этот метод используется, когда мы хотим вернуть одно скалярное значение или набор столбцов в одной строке курсора из курсора SQL.

Дальнейшее чтение:

Присвоение значений переменным•

Прочитайте Модель и язык заданий онлайн: https://riptutorial.com/ru/plsql/topic/6959/модель-и-язык-заданий

https://riptutorial.com/ru/home 14

Page 19: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

глава 7: Обработка исключений

Вступление

Oracle производит множество исключений. Вы можете быть удивлены, насколько утомительным может быть ваш код с некоторым неясным сообщением. Чтобы улучшить способность кода PL / SQL легко фиксироваться, необходимо обрабатывать исключения на самом низком уровне. Никогда не скрывайте исключение «под ковром», если только вы здесь, чтобы сохранить свою часть кода только для вас и никому больше не поддерживать.

Предопределенные ошибки .

Examples

Обработка исключений

Что такое исключение?

Исключение в PL / SQL является ошибкой, созданной во время выполнения программы.

У нас есть три типа исключений:

Исключенные внутри страны исключения•Предопределенные исключения•Пользовательские исключения•

1.

Что такое обработка исключений?

Обработка исключений - это возможность поддерживать нашу программу даже при появлении ошибки времени выполнения, вызванной, например, ошибками кодирования, сбоями оборудования. Мы избегаем его внезапного выхода из строя.

2.

Синтаксис

Общий синтаксис для секции исключения:

declare declaration Section begin some statements exception when exception_one then

https://riptutorial.com/ru/home 15

Page 20: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

do something when exception_two then do something when exception_three then do something when others then do something end;

Секция исключений должна быть в конце блока PL / SQL. PL / SQL дает нам возможность блокировать блоки, тогда каждый блок может иметь свой собственный раздел исключения, например:

create or replace procedure nested_blocks is begin some statements begin some statements exception when exception_one then do something end; exception when exception_two then do something end;

Если исключение будет поднято во вложенном блоке, оно должно быть обработано во внутреннем разделе исключения, но если внутренняя секция исключения не обрабатывает это исключение, то это исключение перейдет в секцию исключения внешнего блока.

Исключенные внутри страны исключения

Внутренне определенное исключение не имеет имени, но имеет свой собственный код.

Когда его использовать?

Если вы знаете, что в вашей операции с базой данных могут возникать определенные исключения, те, у которых нет имен, вы можете дать им имена, чтобы вы могли специально писать для них обработчики исключений. В противном случае вы можете использовать их только с others обработчиками исключений.

Синтаксис

declare my_name_exc exception; pragma exception_init(my_name_exc,-37); begin ... exception when my_name_exc then

https://riptutorial.com/ru/home 16

Page 21: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

do something end;

my_name_exc exception; это объявление имени исключения.

pragma exception_init(my_name_exc,-37); присваивать имя коду ошибки внутреннего исключения.

пример

У нас есть emp_id, который является первичным ключом в таблице emp и внешним ключом в таблице dept. Если мы попытаемся удалить emp_id, когда у него есть дочерние записи, он будет исключен с кодом -2292.

create or replace procedure remove_employee is emp_exception exception; pragma exception_init(emp_exception,-2292); begin delete from emp where emp_id = 3; exception when emp_exception then dbms_output.put_line('You can not do that!'); end; /

Документация Oracle гласит: «Внутренне определенное исключение с объявленным пользователем именем по-прежнему является внутренне определенным исключением, а не определяемым пользователем исключением».

Предопределенные исключения

Предопределенные исключения являются внутренне определенными исключениями, но имеют имена. База данных Oracle автоматически генерирует этот тип исключений.

пример

create or replace procedure insert_emp is begin insert into emp (emp_id, ename) values ('1','Jon'); exception when dup_val_on_index then dbms_output.put_line('Duplicate value on index!'); end; /

Ниже приведены примеры исключений с их кодами:

https://riptutorial.com/ru/home 17

Page 22: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

Имя исключения Код ошибки

ДАННЫЕ НЕ НАЙДЕНЫ -1403

ACCESS_INTO_NULL -6530

CASE_NOT_FOUND -6592

ROWTYPE_MISMATCH -6504

TOO_MANY_ROWS -1422

ZERO_DIVIDE -1476

Полный список имен исключений и их кодов на веб-сайте Oracle.

Пользовательские исключения

Как видно из названия, пользовательские исключения создаются пользователями. Если вы хотите создать свое собственное исключение, вы должны:

Объявить исключение1. Поднимите его из своей программы2. Создайте подходящий обработчик исключений, чтобы поймать его.3.

пример

Я хочу обновить все зарплаты рабочих. Но если нет рабочих, создайте исключение.

create or replace procedure update_salary is no_workers exception; v_counter number := 0; begin select count(*) into v_counter from emp; if v_counter = 0 then raise no_workers; else update emp set salary = 3000; end if; exception when no_workers then raise_application_error(-20991,'We don''t have workers!'); end; /

Что значит raise ?

Исключения создаются сервером базы данных автоматически, когда есть необходимость, но если вы хотите, вы можете явно выражать любое исключение, используя raise .

https://riptutorial.com/ru/home 18

Page 23: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

Процедура raise_application_error(error_number,error_message);

error_number должен находиться между -20000 и -20999•

error_message для отображения при возникновении ошибки.•

Определите настраиваемое исключение, поднимите его и посмотрите, откуда он

Чтобы проиллюстрировать это, вот функция, которая имеет 3 разных «неправильных» поведения

параметр полностью тупой: мы используем пользовательское выражение•параметр имеет опечатку: мы используем стандартную ошибку Oracle NO_DATA_FOUND•

другой, но не обработанный случай•

Не стесняйтесь адаптировать его к своим стандартам:

DECLARE this_is_not_acceptable EXCEPTION; PRAGMA EXCEPTION_INIT(this_is_not_acceptable, -20077); g_err varchar2 (200) := 'to-be-defined'; w_schema all_tables.OWNER%Type; PROCEDURE get_schema( p_table in Varchar2, p_schema out Varchar2) Is w_err varchar2 (200) := 'to-be-defined'; BEGIN w_err := 'get_schema-step-1:'; If (p_table = 'Delivery-Manager-Is-Silly') Then raise this_is_not_acceptable; end if; w_err := 'get_schema-step-2:'; Select owner Into p_schema From all_tables where table_name like(p_table||'%'); EXCEPTION WHEN NO_DATA_FOUND THEN -- handle Oracle-defined exception dbms_output.put_line('[WARN]'||w_err||'This can happen. Check the table name you entered.'); WHEN this_is_not_acceptable THEN -- handle your custom error dbms_output.put_line('[WARN]'||w_err||'Please don''t make fun of the delivery manager.'); When others then dbms_output.put_line('[ERR]'||w_err||'unhandled exception:'||sqlerrm); raise; END Get_schema; BEGIN g_err := 'Global; first call:'; get_schema('Delivery-Manager-Is-Silly', w_schema); g_err := 'Global; second call:'; get_schema('AAA', w_schema); g_err := 'Global; third call:'; get_schema('', w_schema);

https://riptutorial.com/ru/home 19

Page 24: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

g_err := 'Global; 4th call:'; get_schema('Can''t reach this point due to previous error.', w_schema); EXCEPTION When others then dbms_output.put_line('[ERR]'||g_err||'unhandled exception:'||sqlerrm); -- you may raise this again to the caller if error log isn't enough. -- raise; END; /

Предоставление регулярной базы данных:

[WARN]get_schema-step-1:Please don't make fun of the delivery manager. [WARN]get_schema-step-2:This can happen. Check the table name you entered. [ERR]get_schema-step-2:unhandled exception:ORA-01422: exact fetch returns more than requested number of rows [ERR]Global; third call:unhandled exception:ORA-01422: exact fetch returns more than requested number of rows

Помните, что исключение здесь для обработки редких случаев. Я видел приложения, которые создавали исключение при каждом доступе, просто чтобы запросить пароль пользователя, сказав «не подключен» ... столько отходов вычислений.

Исключение ошибок связи

Каждая стандартная ошибка Oracle связана с номером ошибки. Важно предугадать, что может пойти не так в коде. Здесь для подключения к другой базе данных это может быть:

-28000 заблокирован•-28001 пароль истек•-28002 льготный период•-1017 неправильный пользователь / пароль•

Вот способ проверить, что не так с пользователем, используемым ссылкой базы данных:

declare v_dummy number; begin -- testing db link execute immediate 'select COUNT(1) from [email protected]' into v_dummy ; -- if we get here, exception wasn't raised: display COUNT's result dbms_output.put_line(v_dummy||' users on PASS db'); EXCEPTION -- exception can be referred by their name in the predefined Oracle's list When LOGIN_DENIED then dbms_output.put_line('ORA-1017 / USERNAME OR PASSWORD INVALID, TRY AGAIN'); When Others then -- or referred by their number: stored automatically in reserved variable SQLCODE If SQLCODE = '-2019'

https://riptutorial.com/ru/home 20

Page 25: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

Then dbms_output.put_line('ORA-2019 / Invalid db_link name'); Elsif SQLCODE = '-1035' Then dbms_output.put_line('ORA-1035 / DATABASE IS ON RESTRICTED SESSION, CONTACT YOUR DBA'); Elsif SQLCODE = '-28000' Then dbms_output.put_line('ORA-28000 / ACCOUNT IS LOCKED. CONTACT YOUR DBA'); Elsif SQLCODE = '-28001' Then dbms_output.put_line('ORA-28001 / PASSWORD EXPIRED. CONTACT YOUR DBA FOR CHANGE'); Elsif SQLCODE = '-28002' Then dbms_output.put_line('ORA-28002 / PASSWORD IS EXPIRED, CHANGED IT'); Else -- and if it's not one of the exception you expected dbms_output.put_line('Exception not specifically handled'); dbms_output.put_line('Oracle Said'||SQLCODE||':'||SQLERRM); End if; END; /

Прочитайте Обработка исключений онлайн: https://riptutorial.com/ru/plsql/topic/6050/

обработка-исключений

https://riptutorial.com/ru/home 21

Page 26: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

глава 8: Обработка исключений

Вступление

Oracle производит множество исключений. Вы можете быть удивлены, насколько утомительным может быть ваш код с некоторым неясным сообщением. Чтобы улучшить способность кода PL / SQL легко фиксироваться, необходимо обрабатывать исключения на самом низком уровне. Никогда не скрывайте исключение «под ковром», если только вы здесь, чтобы сохранить свою часть кода только для вас и никому больше не поддерживать.

Предопределенные ошибки .

Examples

Исключение ошибок связи

Каждая стандартная ошибка Oracle связана с номером ошибки. Его важно предвидеть, что может пойти не так в коде. Здесь для подключения к другой базе данных это может быть:

-28000 заблокирован•-28001 пароль истек•-28002 льготный период•-1017 неправильный пользователь / пароль•

Вот способ проверить, что не так с пользователем, используемым ссылкой базы данных:

declare v_dummy number; begin -- testing db link execute immediate 'select COUNT(1) from [email protected]' into v_dummy ; -- if we get here, exception wasn't raised: display COUNT's result dbms_output.put_line(v_dummy||' users on PASS db'); EXCEPTION -- exception can be referred by their name in the predefined Oracle's list When LOGIN_DENIED then dbms_output.put_line('ORA-1017 / USERNAME OR PASSWORD INVALID, TRY AGAIN'); When Others then -- or referred by their number: stored automatically in reserved variable SQLCODE If SQLCODE = '-2019' Then dbms_output.put_line('ORA-2019 / Invalid db_link name'); Elsif SQLCODE = '-1035' Then

https://riptutorial.com/ru/home 22

Page 27: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

dbms_output.put_line('ORA-1035 / DATABASE IS ON RESTRICTED SESSION, CONTACT YOUR DBA'); Elsif SQLCODE = '-28000' Then dbms_output.put_line('ORA-28000 / ACCOUNT IS LOCKED. CONTACT YOUR DBA'); Elsif SQLCODE = '-28001' Then dbms_output.put_line('ORA-28001 / PASSWORD EXPIRED. CONTACT YOUR DBA FOR CHANGE'); Elsif SQLCODE = '-28002' Then dbms_output.put_line('ORA-28002 / PASSWORD IS EXPIRED, CHANGED IT'); Else -- and if it's not one of the exception you expected dbms_output.put_line('Exception not specifically handled'); dbms_output.put_line('Oracle Said'||SQLCODE||':'||SQLERRM); End if; END; /

Определите настраиваемое исключение, поднимите его и посмотрите, откуда он

Чтобы проиллюстрировать это, вот функция, которая имеет 3 разных «неправильных» поведения

параметр полностью тупой: мы используем пользовательское выражение•параметр имеет опечатку: мы используем стандартную ошибку Oracle NO_DATA_FOUND•

другой, но не обработанный случай•

Не стесняйтесь адаптировать его к своим стандартам:

DECLARE this_is_not_acceptable EXCEPTION; PRAGMA EXCEPTION_INIT(this_is_not_acceptable, -20077); g_err varchar2 (200) := 'to-be-defined'; w_schema all_tables.OWNER%Type; PROCEDURE get_schema( p_table in Varchar2, p_schema out Varchar2) Is w_err varchar2 (200) := 'to-be-defined'; BEGIN w_err := 'get_schema-step-1:'; If (p_table = 'Delivery-Manager-Is-Silly') Then raise this_is_not_acceptable; end if; w_err := 'get_schema-step-2:'; Select owner Into p_schema From all_tables where table_name like(p_table||'%'); EXCEPTION WHEN NO_DATA_FOUND THEN -- handle Oracle-defined exception dbms_output.put_line('[WARN]'||w_err||'This can happen. Check the table name you entered.'); WHEN this_is_not_acceptable THEN -- handle your custom error

https://riptutorial.com/ru/home 23

Page 28: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

dbms_output.put_line('[WARN]'||w_err||'Please don''t make fun of the delivery manager.'); When others then dbms_output.put_line('[ERR]'||w_err||'unhandled exception:'||sqlerrm); raise; END Get_schema; BEGIN g_err := 'Global; first call:'; get_schema('Delivery-Manager-Is-Silly', w_schema); g_err := 'Global; second call:'; get_schema('AAA', w_schema); g_err := 'Global; third call:'; get_schema('', w_schema); g_err := 'Global; 4th call:'; get_schema('Can''t reach this point due to previous error.', w_schema); EXCEPTION When others then dbms_output.put_line('[ERR]'||g_err||'unhandled exception:'||sqlerrm); -- you may raise this again to the caller if error log isn't enough. -- raise; END; /

Предоставление регулярной базы данных:

[WARN]get_schema-step-1:Please don't make fun of the delivery manager. [WARN]get_schema-step-2:This can happen. Check the table name you entered. [ERR]get_schema-step-2:unhandled exception:ORA-01422: exact fetch returns more than requested number of rows [ERR]Global; third call:unhandled exception:ORA-01422: exact fetch returns more than requested number of rows

Помните, что исключение здесь для обработки редких случаев. Я видел приложения, которые возбуждали исключение при каждом доступе, просто чтобы запросить пароль пользователя, говоря «не подключен» ... столько отходов вычислений.

Прочитайте Обработка исключений онлайн: https://riptutorial.com/ru/plsql/topic/9480/

обработка-исключений

https://riptutorial.com/ru/home 24

Page 29: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

глава 9: пакеты

Синтаксис

CREATE [OR REPLACE] PACKAGE имя_пакета

[AUTHID {CURRENT_USER | DEFINER}]

{IS | КАК}

[PRAGMA SERIALLY_REUSABLE;]

[collection_type_definition ...]

[record_type_definition ...]

[subtype_definition ...]

[collection_declaration ...]

[constant_declaration ...]

[exception_declaration ...]

[object_declaration ...]

[record_declaration ...]

[variable_declaration ...]

[cursor_spec ...]

[function_spec ...]

[procedure_spec ...]

[call_spec ...]

[PRAGMA RESTRICT_REFERENCES (утверждения) ...]

END [имя_пакета];

СОЗДАТЬ ИЛИ ЗАМЕНИТЬ ПАКЕТ PackageName IS

ФУНКЦИЯ FunctionName (параметр1 IN VARCHAR2, параметр2 IN NUMBER) RETURN VARCHAR2;

END PackageName;

https://riptutorial.com/ru/home 25

Page 30: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

CREATE [OR REPLACE] PACKAGE BODY имя_пакета

{IS | КАК}

[PRAGMA SERIALLY_REUSABLE;]

[collection_type_definition ...]

[record_type_definition ...]

[subtype_definition ...]

[collection_declaration ...]

[constant_declaration ...]

[exception_declaration ...]

[object_declaration ...]

[record_declaration ...]

[variable_declaration ...]

[cursor_body ...]

[function_spec ...]

[procedure_spec ...]

[call_spec ...]

END [имя_пакета];

СОЗДАТЬ ИЛИ ЗАМЕНИТЬ ПАКЕТНЫЙ ТЕЛО PackageName IS

ФУНКЦИЯ FunctionName (параметр1 IN VARCHAR2, paramter2 IN NUMBER) RETURN VARCHAR2 IS

декларации

НАЧАТЬ

операторы для выполнения

RETURN переменная varchar2

END FunctionName;

END PackageName;

https://riptutorial.com/ru/home 26

Page 31: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

Examples

Использование пакета

Пакеты в PLSQL представляют собой набор процедур, функций, переменных, исключений, констант и структур данных. Как правило, ресурсы в пакете связаны друг с другом и выполняют аналогичные задачи.

Зачем использовать пакеты

модульность•Лучшая производительность / функциональность•

Части пакета

Спецификация - иногда называется заголовком пакета. Содержит объявления переменных и типов и подписи функций и процедур, которые находятся в пакете, которые публично вызывают извне пакета.

Body Package - содержит код и частные объявления.

Спецификация пакета должна быть скомпилирована перед телом пакета, иначе компиляция тела пакета сообщит об ошибке.

перегрузка

Функции и процедуры в пакетах могут быть перегружены. Следующий пакет TEST имеет две процедуры, называемые print_number , которые ведут себя по-разному в зависимости от параметров, с которыми они вызываются.

create or replace package TEST is procedure print_number(p_number in integer); procedure print_number(p_number in varchar2); end TEST; / create or replace package body TEST is procedure print_number(p_number in integer) is begin dbms_output.put_line('Digit: ' || p_number); end; procedure print_number(p_number in varchar2) is begin dbms_output.put_line('String: ' || p_number); end; end TEST; /

https://riptutorial.com/ru/home 27

Page 32: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

Мы называем обе процедуры. Первый с целым параметром, второй с varchar2.

set serveroutput on; -- call the first procedure exec test.print_number(3); -- call the second procedure exec test.print_number('three');

Вывод приведенного выше сценария:

SQL> Digit: 3 PL/SQL procedure successfully completed String: three PL/SQL procedure successfully completed

Ограничения на перегрузку

Могут быть перегружены только локальные или упакованные подпрограммы или методы типа. Поэтому вы не можете перегружать автономные подпрограммы. Кроме того, вы не можете перегружать две подпрограммы, если их формальные параметры отличаются только именем или параметром

Определите заголовок и тело пакета с помощью функции.

В этом примере мы определяем заголовок пакета и тело пакета с функцией. После этого мы вызываем функцию из пакета, возвращающую возвращаемое значение.

Заголовок пакета :

CREATE OR REPLACE PACKAGE SkyPkg AS FUNCTION GetSkyColour(vPlanet IN VARCHAR2) RETURN VARCHAR2; END; /

Корпус упаковки :

CREATE OR REPLACE PACKAGE BODY SkyPkg AS FUNCTION GetSkyColour(vPlanet IN VARCHAR2) RETURN VARCHAR2 AS vColour VARCHAR2(100) := NULL; BEGIN IF vPlanet = 'Earth' THEN vColour := 'Blue'; ELSIF vPlanet = 'Mars' THEN vColour := 'Red';

https://riptutorial.com/ru/home 28

Page 33: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

END IF; RETURN vColour; END; END; /

Вызов функции из корпуса пакета :

DECLARE vColour VARCHAR2(100); BEGIN vColour := SkyPkg.GetSkyColour(vPlanet => 'Earth'); DBMS_OUTPUT.PUT_LINE(vColour); END; /

Прочитайте пакеты онлайн: https://riptutorial.com/ru/plsql/topic/4764/пакеты

https://riptutorial.com/ru/home 29

Page 34: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

глава 10: петля

Синтаксис

LOOP1. [заявления];2.

EXIT WHEN [условие для цикла выхода];3. END LOOP;4.

Examples

Простая петля

DECLARE v_counter NUMBER(2); BEGIN v_counter := 0; LOOP v_counter := v_counter + 1; dbms_output.put_line('Line number' || v_counter); EXIT WHEN v_counter = 10; END LOOP; END;

WHILE Loop

Цикл WHILE выполняется до тех пор, пока не будет выполнено условие конца. Простой пример:

DECLARE v_counter NUMBER(2); --declaration of counter variable BEGIN v_counter := 0; --point of start, first value of our iteration WHILE v_counter < 10 LOOP --exit condition dbms_output.put_line('Current iteration of loop is ' || v_counter); --show current iteration number in dbms script output v_counter := v_counter + 1; --incrementation of counter value, very important step END LOOP; --end of loop declaration END;

Этот цикл будет выполнен до тех пор, пока текущее значение переменной v_counter не будет меньше десяти.

https://riptutorial.com/ru/home 30

Page 35: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

Результат:

Current iteration of loop is 0 Current iteration of loop is 1 Current iteration of loop is 2 Current iteration of loop is 3 Current iteration of loop is 4 Current iteration of loop is 5 Current iteration of loop is 6 Current iteration of loop is 7 Current iteration of loop is 8 Current iteration of loop is 9

Самое главное, что наш цикл начинается с значения «0», поэтому первая строка результатов «Текущая итерация цикла равна 0».

FOR Loop

Loop FOR работает по аналогичным правилам, как и другие циклы. FOR цикл выполняется точное число раз, и это число известно в начале - нижний и верхний пределы напрямую задаются в коде. На каждом шаге этого примера цикл увеличивается на 1.

Простой пример:

DECLARE v_counter NUMBER(2); --declaration of counter variable BEGIN v_counter := 0; --point of start, first value of our iteration, execute of variable FOR v_counter IN 1..10 LOOP --The point, where lower and upper point of loop statement is declared - in this example, loop will be executed 10 times, start with value of 1 dbms_output.put_line('Current iteration of loop is ' || v_counter); --show current iteration number in dbms script output END LOOP; --end of loop declaration END;

И результат:

Current iteration of loop is 1 Current iteration of loop is 2 Current iteration of loop is 3 Current iteration of loop is 4 Current iteration of loop is 5 Current iteration of loop is 6 Current iteration of loop is 7 Current iteration of loop is 8 Current iteration of loop is 9 Current iteration of loop is 10

Loop FOR имеет дополнительное свойство, которое работает в обратном порядке.

https://riptutorial.com/ru/home 31

Page 36: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

Использование дополнительного слова «REVERSE» в объявлении нижнего и верхнего пределов цикла позволяет это сделать. Каждое выполнение значения декремента цикла v_counter на 1.

Пример:

DECLARE v_counter NUMBER(2); --declaration of counter variable BEGIN v_counter := 0; --point of start FOR v_counter IN REVERSE 1..10 LOOP dbms_output.put_line('Current iteration of loop is ' || v_counter); --show current iteration number in dbms script output END LOOP; --end of loop declaration END;

И результат:

Current iteration of loop is 10 Current iteration of loop is 9 Current iteration of loop is 8 Current iteration of loop is 7 Current iteration of loop is 6 Current iteration of loop is 5 Current iteration of loop is 4 Current iteration of loop is 3 Current iteration of loop is 2 Current iteration of loop is 1

Прочитайте петля онлайн: https://riptutorial.com/ru/plsql/topic/6157/петля

https://riptutorial.com/ru/home 32

Page 37: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

глава 11: Процедура PLSQL

Вступление

Процедура PLSQL - это группа операторов SQL, хранящихся на сервере для повторного использования. Это увеличивает производительность, потому что SQL-запросы не нужно перекомпилировать каждый раз, когда они выполняются.

Хранимые процедуры полезны, когда один и тот же код требуется для нескольких приложений. Хранимые процедуры исключают избыточность и вводят простоту в код. Когда требуется передача данных между клиентом и сервером, процедуры могут снизить стоимость связи в определенных ситуациях.

Examples

Синтаксис

CREATE [OR REPLACE] PROCEDURE procedure_name [(parameter_name [IN | OUT | IN OUT] type [, ...])] {IS | AS} < declarations > BEGIN < procedure_body > EXCEPTION -- Exception-handling part begins <exception handling goes here > WHEN exception1 THEN exception1-handling-statements END procedure_name;

имя процедуры задает имя процедуры.•Опция [ИЛИ ЗАМЕНИТЬ] позволяет изменить существующую процедуру.•Дополнительный список параметров содержит имя, режим и типы параметров. IN

представляет, что значение будет передано извне, а OUT представляет, что этот параметр будет использоваться для возврата значения вне процедуры. Если режим не указан, предполагается, что параметр имеет режим IN.

В разделе декларации мы можем объявлять переменные, которые будут использоваться в части тела.

procedure-body содержит исполняемую часть.•

Ключевое слово AS используется вместо ключевого слова IS для создания автономной процедуры.

исключение будет обрабатывать исключения из процедуры. Этот раздел не является обязательным.

Привет, мир

https://riptutorial.com/ru/home 33

Page 38: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

Следующая простая процедура отображает текст «Hello World» в клиенте, который поддерживает dbms_output .

CREATE OR REPLACE PROCEDURE helloworld AS BEGIN dbms_output.put_line('Hello World!'); END; /

Вам нужно выполнить это в приглашении SQL, чтобы создать процедуру в базе данных, или вы можете запустить запрос ниже, чтобы получить тот же результат:

SELECT 'Hello World!' from dual;

Параметры ввода / вывода

PL / SQL использует ключевые слова IN, OUT, IN OUT для определения того, что может случиться с переданным параметром.

IN указывает, что параметр только для чтения, и значение не может быть изменено процедурой.

OUT указывает, что параметр только для записи, и процедура может назначить ему значение, но не ссылаться на значение.

IN OUT указывает, что параметр доступен для справки и изменения.

PROCEDURE procedureName(x IN INT, strVar IN VARCHAR2, ans OUT VARCHAR2) ... ... END procedureName; procedureName(firstvar, secondvar, thirdvar);

Переменные, перечисленные в приведенном выше примере, должны быть напечатаны так, как они определены в разделе параметров процедуры.

Прочитайте Процедура PLSQL онлайн: https://riptutorial.com/ru/plsql/topic/2580/процедура-plsql

https://riptutorial.com/ru/home 34

Page 39: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

глава 12: Типы объектов

замечания

Важно отметить, что тело объекта может не всегда быть необходимым. Если конструктор по умолчанию достаточен, и никакая другая функциональность не должна быть реализована, то его не следует создавать.

Конструктор по умолчанию представляет собой поставляемый Oracle конструктор, который состоит из всех атрибутов, перечисленных в порядке объявления. Например, экземпляр BASE_TYPE может быть сконструирован следующим вызовом, хотя мы явно не объявляем его.

l_obj := BASE_TYPE(1, 'Default', 1);

Examples

BASE_TYPE

Объявление типа:

CREATE OR REPLACE TYPE base_type AS OBJECT ( base_id INTEGER, base_attr VARCHAR2(400), null_attr INTEGER, -- Present only to demonstrate non-default constructors CONSTRUCTOR FUNCTION base_type ( i_base_id INTEGER, i_base_attr VARCHAR2 ) RETURN SELF AS RESULT, MEMBER FUNCTION get_base_id RETURN INTEGER, MEMBER FUNCTION get_base_attr RETURN VARCHAR2, MEMBER PROCEDURE set_base_id(i_base_id INTEGER), MEMBER PROCEDURE set_base_attr(i_base_attr VARCHAR2), MEMBER FUNCTION to_string RETURN VARCHAR2 ) INSTANTIABLE NOT FINAL

Тип кузова:

CREATE OR REPLACE TYPE BODY base_type AS CONSTRUCTOR FUNCTION base_type ( i_base_id INTEGER, i_base_attr VARCHAR2 ) RETURN SELF AS RESULT IS BEGIN self.base_id := i_base_id;

https://riptutorial.com/ru/home 35

Page 40: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

self.base_attr := i_base_attr; RETURN; END base_type; MEMBER FUNCTION get_base_id RETURN INTEGER IS BEGIN RETURN self.base_id; END get_base_id; MEMBER FUNCTION get_base_attr RETURN VARCHAR2 IS BEGIN RETURN self.base_attr; END get_base_attr; MEMBER PROCEDURE set_base_id(i_base_id INTEGER) IS BEGIN self.base_id := i_base_id; END set_base_id; MEMBER PROCEDURE set_base_attr(i_base_attr VARCHAR2) IS BEGIN self.base_attr := i_base_attr; END set_base_attr; MEMBER FUNCTION to_string RETURN VARCHAR2 IS BEGIN RETURN 'BASE_ID ['||self.base_id||']; BASE_ATTR ['||self.base_attr||']'; END to_string; END;

MID_TYPE

Объявление типа:

CREATE OR REPLACE TYPE mid_type UNDER base_type ( mid_attr DATE, CONSTRUCTOR FUNCTION mid_type ( i_base_id INTEGER, i_base_attr VARCHAR2, i_mid_attr DATE ) RETURN SELF AS RESULT, MEMBER FUNCTION get_mid_attr RETURN DATE, MEMBER PROCEDURE set_mid_attr(i_mid_attr DATE), OVERRIDING MEMBER FUNCTION to_string RETURN VARCHAR2 ) INSTANTIABLE NOT FINAL

Тип кузова:

CREATE OR REPLACE TYPE BODY mid_type AS CONSTRUCTOR FUNCTION mid_type ( i_base_id INTEGER, i_base_attr VARCHAR2, i_mid_attr DATE ) RETURN SELF AS RESULT IS

https://riptutorial.com/ru/home 36

Page 41: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

BEGIN self.base_id := i_base_id; self.base_attr := i_base_attr; self.mid_attr := i_mid_attr; RETURN; END mid_type; MEMBER FUNCTION get_mid_attr RETURN DATE IS BEGIN RETURN self.mid_attr; END get_mid_attr; MEMBER PROCEDURE set_mid_attr(i_mid_attr DATE) IS BEGIN self.mid_attr := i_mid_attr; END set_mid_attr; OVERRIDING MEMBER FUNCTION to_string RETURN VARCHAR2 IS BEGIN RETURN (SELF AS base_type).to_string || '; MID_ATTR [' || self.mid_attr || ']'; END to_string; END;

LEAF_TYPE

Объявление типа:

CREATE OR REPLACE TYPE leaf_type UNDER mid_type ( leaf_attr VARCHAR2(1000), CONSTRUCTOR FUNCTION leaf_type ( i_base_id INTEGER, i_base_attr VARCHAR2, i_mid_attr DATE, i_leaf_attr VARCHAR2 ) RETURN SELF AS RESULT, MEMBER FUNCTION get_leaf_attr RETURN VARCHAR2, MEMBER PROCEDURE set_leaf_attr(i_leaf_attr VARCHAR2), OVERRIDING MEMBER FUNCTION to_string RETURN VARCHAR2 ) INSTANTIABLE FINAL

Тип кузова:

CREATE OR REPLACE TYPE BODY leaf_type AS CONSTRUCTOR FUNCTION leaf_type ( i_base_id INTEGER, i_base_attr VARCHAR2, i_mid_attr DATE, i_leaf_attr VARCHAR2 ) RETURN SELF AS RESULT IS BEGIN self.base_id := i_base_id; self.base_attr := i_base_attr; self.mid_attr := i_mid_attr;

https://riptutorial.com/ru/home 37

Page 42: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

self.leaf_attr := i_leaf_attr; RETURN; END leaf_type; MEMBER FUNCTION get_leaf_attr RETURN VARCHAR2 IS BEGIN RETURN self.leaf_attr; END get_leaf_attr; MEMBER PROCEDURE set_leaf_attr(i_leaf_attr VARCHAR2) IS BEGIN self.leaf_attr := i_leaf_attr; END set_leaf_attr; OVERRIDING MEMBER FUNCTION to_string RETURN VARCHAR2 IS BEGIN RETURN (SELF AS mid_type).to_string || '; LEAF_ATTR [' || self.leaf_attr || ']'; END to_string; END;

Доступ к хранимым объектам

CREATE SEQUENCE test_seq START WITH 1001; CREATE TABLE test_tab ( test_id INTEGER, test_obj base_type, PRIMARY KEY (test_id) ); INSERT INTO test_tab (test_id, test_obj) VALUES (test_seq.nextval, base_type(1,'BASE_TYPE')); INSERT INTO test_tab (test_id, test_obj) VALUES (test_seq.nextval, base_type(2,'BASE_TYPE')); INSERT INTO test_tab (test_id, test_obj) VALUES (test_seq.nextval, mid_type(3, 'MID_TYPE',SYSDATE - 1)); INSERT INTO test_tab (test_id, test_obj) VALUES (test_seq.nextval, mid_type(4, 'MID_TYPE',SYSDATE + 1)); INSERT INTO test_tab (test_id, test_obj) VALUES (test_seq.nextval, leaf_type(5, 'LEAF_TYPE',SYSDATE - 20,'Maple')); INSERT INTO test_tab (test_id, test_obj) VALUES (test_seq.nextval, leaf_type(6, 'LEAF_TYPE',SYSDATE + 20,'Oak'));

Возвращает ссылку на объект:

SELECT test_id ,test_obj FROM test_tab;

Возвращает ссылку на объект, нажав все на подтип

SELECT test_id ,TREAT(test_obj AS mid_type) AS obj FROM test_tab;

https://riptutorial.com/ru/home 38

Page 43: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

Возвращает дескриптор строки каждого объекта по типу

SELECT test_id ,TREAT(test_obj AS base_type).to_string() AS to_string -- Parenthesis are needed after the function name, or Oracle will look for an attribute of this name. FROM test_tab;

Прочитайте Типы объектов онлайн: https://riptutorial.com/ru/plsql/topic/7699/типы-объектов

https://riptutorial.com/ru/home 39

Page 44: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

глава 13: Триггеры

Вступление

Вступление:

Триггеры - полезная концепция в PL / SQL. Триггер - это особый тип хранимой процедуры, который не требует явного вызова пользователем. Это группа инструкций, которая автоматически запускается в ответ на конкретное действие модификации данных в конкретной таблице или отношении или при выполнении определенных условий. Триггеры помогают поддерживать целостность и безопасность данных. Они делают работу удобной, автоматически выполняя требуемые действия.

Синтаксис

СОЗДАТЬ [ИЛИ ЗАМЕНИТЬ] TRIGGER trigger_name•

ПЕРЕД ОБНОВЛЕНИЕМ [или ВСТАВИТЬ] [или УДАЛИТЬ]•ON table_name•[ДЛЯ КАЖДОГО РУКА]•DECLARE•- объявления переменных•

НАЧАТЬ•- код запуска•

ИСКЛЮЧЕНИЕ•КОГДА ...•-- Обработка исключений•

КОНЕЦ;•

Examples

Перед вызовом INSERT или UPDATE

CREATE OR REPLACE TRIGGER CORE_MANUAL_BIUR BEFORE INSERT OR UPDATE ON CORE_MANUAL FOR EACH ROW BEGIN if inserting then -- only set the current date if it is not specified if :new.created is null then :new.created := sysdate; end if; end if; -- always set the modified date to now if inserting or updating then

https://riptutorial.com/ru/home 40

Page 45: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

:new.modified := sysdate; end if; end; /

Прочитайте Триггеры онлайн: https://riptutorial.com/ru/plsql/topic/7674/триггеры

https://riptutorial.com/ru/home 41

Page 46: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

глава 14: функции

Синтаксис

CREATE [OR REPLACE] FUNCTION имя_функции [(параметр [, параметр])]

RETURN return_datatype

IS | КАК

[Declaration_section]

BEGIN исполняемый_секретарь

[EXCEPTION exception_section]

END [имя_функции];

Examples

Создать GUID

Create Or Replace Function Generateguid Return Char Is V_Guid Char(40); Begin Select Substr(Sys_Guid(),1,8)||'-'||Substr(Sys_Guid(),9,4)||'-' ||Substr(Sys_Guid(),13,4)||'-'||Substr(Sys_Guid(),17,4)||'-' ||Substr(Sys_Guid(),21) Into V_Guid From Dual; Return V_Guid; Exception When Others Then dbms_output.put_line('Error '|| SQLERRM); End Generateguid;

Функции вызова

Существует несколько способов использования функций.

Вызов функции с оператором присваивания

DECLARE x NUMBER := functionName(); --functions can be called in declaration section BEGIN x := functionName(); END;

https://riptutorial.com/ru/home 42

Page 47: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

Вызов функции в выражении IF

IF functionName() = 100 THEN Null; END IF;

Вызов функции в выражении SELECT

SELECT functionName() FROM DUAL;

Прочитайте функции онлайн: https://riptutorial.com/ru/plsql/topic/4005/функции

https://riptutorial.com/ru/home 43

Page 48: plsql - RIP Tutorial · 2019-01-18 · PL / SQL доступен в Oracle Database (начиная с версии 7), в базе данных TimesTen в памяти (начиная

кредиты

S. No

Главы Contributors

1Начало работы с PLSQL

Community, Dinidu, JDro04, m.misiorny, Prashant Mishra, Tenzin, user272735

2Заявление IF-THEN-ELSE

massko

3Коллекции и отчеты

J. Chomel

4 курсоры dipdapdop, J. Chomel, Jucan

5 Массовый сбор Prashant Mishra

6Модель и язык заданий

m.misiorny, user272735

7Обработка исключений

Ice, J. Chomel, jiri.hofman, Tony Andrews, Zug Zwang

8 пакеты JDro04, jiri.hofman, StewS2, Tenzin

9 петля m.misiorny, massko

10 Процедура PLSQL Dinidu, Doruk, Harjot, JDro04, Kekar, William Robertson

11 Типы объектов HepC

12 Триггеры Harjot, jiri.hofman

13 функции JDro04, Jon Clements, user3216906

https://riptutorial.com/ru/home 44