Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Lab_04_Oracle %28PL_SQL%29 / Додатково_Теорія_01_Блоки_керуючі_структури_ PL_SQL

.pdf
Скачиваний:
6
Добавлен:
11.02.2015
Размер:
518.25 Кб
Скачать

Процедура PL/SQL успішно завершена.

SQL> /

Уведіть значення для db_name: NTBASE

колишній 3: IF '&db_name' = 'NTBASE' новий 3: IF 'NTBASE' = 'NTBASE'

Ви правильно назвали ім'я БД.

Цей рядок друкується в кожному разі.

Процедура PL/SQL успішно завершена.

10. Вкладені оператори IF

Кожний із операторів IF може містити інші, вкладені, умовні оператори для здійснення подальшої, більш детальної перевірки умов перед виконанням певних дій.

Кожна вкладена команда IF повинна закінчуватися своїм оператором END IF. У наступному прикладі виробляється фіксація транзакції, якщо змінної fix привласнене значення «yes»; і відкіт транзакції в протилеж-ному випадку за умови, що ім'я БД введене правильно.

SQL> SET SERVEROUTPUT ON SQL> BEGIN

2DBMS_OUTPUT.enable;

3IF '&fix' = 'yes'

4THEN

5DBMS_OUTPUT.put_line('Фіксую транзакцію.');

6COMMIT;

7ELSE

8DBMS_OUTPUT.put_line('Роблю відкіт транзакції.');

9IF '&db_name' = 'NTBASE'

10THEN

11DBMS_OUTPUT.put_line('Відкіт дозволяється.');

12ROLLBACK;

13ELSE

14DBMS_OUTPUT.put_line('У відкоті відмовлено.');

15COMMIT;

16END IF;

17END IF;

18DBMS_OUTPUT.put_line('Транзакція відпрацьована.');

19END;

20/

Уведіть значення для fix: yes

колишній 3: IF '&fix' = 'yes' новий 3: IF 'yes' = 'yes'

Уведіть значення для db_name: NTBASE

колишній 9: IF '&db_name' = 'NTBASE' новий 9: IF 'NTBASE' = 'NTBASE'

Фіксую транзакцію. Транзакція відпрацьована.

Процедура PL/SQL успішно завершена.

SQL> /

Уведіть значення для fix: no

колишній

3:

IF '&fix' = 'yes'

новий

3:

IF 'no' = 'yes'

Уведіть значення для db_name: ppp

колишній

9:

IF '&db_name' = 'NTBASE'

новий

9:

 

IF 'ppp' = 'NTBASE'

Роблю відкіт транзакції. У відкоті відмовлено.

Транзакція відпрацьована.

Процедура PL/SQL успішно завершена.

SQL> /

Уведіть значення для fix: no

колишній 3: IF '&fix' = 'yes' новий 3: IF 'no' = 'yes'

Уведіть значення для db_name: NTBASE

колишній 9: IF '&db_name' = 'NTBASE' новий 9: IF 'NTBASE' = 'NTBASE'

Роблю відкіт транзакції. Відкіт дозволяється. Транзакція відпрацьована.

Процедура PL/SQL успішно завершена.

Поточна дія, що повинна бути виконана в області ELSE команди IF, складається з завдання ще однієї команди IF. У цьому випадку зручніше використовувати оператор ELSIF, щоб уникнути зайвого завдання конструкції END IF наприкінці чергової вкладеної команди IF. З метою реалізації можливості вкладених дій оператор ELSIF при необхідності може задаватися рекурсивно від одного до необхідного числа раз, у наступному вигляді:

IF <умова1> THEN <дії> [ELSIF <умова2> THEN <дії>] [ELSIF <умова3> THEN <дії>]

...

[ELSIF <условие> THEN <дії>] [ELSE <дії>]

END IF;

Наприклад:

SQL> UNDEFINE num

SQL> SET SERVEROUTPUT ON SQL> DECLARE

2n NUMBER(1);

3BEGIN

4IF LENGTH('&&num') > 1 THEN n := -1;

5ELSE n := TO_NUMBER('&&num');

6END IF;

7DBMS_OUTPUT.enable;

8IF n = 0 THEN DBMS_OUTPUT.put_line('Нуль');

9ELSIF n = 1 THEN DBMS_OUTPUT.put_line('Один'); 10 ELSIF n = 2 THEN DBMS_OUTPUT.put_line('Два'); 11 ELSIF n = 3 THEN DBMS_OUTPUT.put_line('Три');

12 ELSIF n = 4 THEN DBMS_OUTPUT.put_line('Чотири'); 13 ELSIF n = 5 THEN DBMS_OUTPUT.put_line('П'ять'); 14 ELSIF n = 6 THEN DBMS_OUTPUT.put_line('Шість'); 15 ELSIF n = 7 THEN DBMS_OUTPUT.put_line('Сім');

16 ELSIF n = 8 THEN DBMS_OUTPUT.put_line('Вісім'); 17 ELSIF n = 9 THEN DBMS_OUTPUT.put_line('Дев'ять');

18ELSE DBMS_OUTPUT.put_line('Не знаю');

19END IF;

20DBMS_OUTPUT.put_line('Мовна програма наговорилася.');

21END;

22/

Уведіть значення для num: 2

колишній 4: IF LENGTH('&&num') > 1 THEN n := -1; новий 4: IF LENGTH('2') > 1 THEN n := -1; колишній 5: ELSE n := TO_NUMBER('&&num'); новий 5: ELSE n := TO_NUMBER('2');

Два Мовна програма наговорилася.

Процедура PL/SQL успішно завершена.

SQL> UNDEF num SQL> /

Уведіть значення для num: 36

колишній 4: IF LENGTH('&&num') > 1 THEN n := -1; новий 4: IF LENGTH('36') > 1 THEN n := -1; колишній 5: ELSE n := TO_NUMBER('&&num'); новий 5: ELSE n := TO_NUMBER('36');

Не знаю Мовна програма наговорилася.

11. Базовий цикл LOOP і оператор EXIT

PL/SQL має набір засобів для організації циклів і переходу з них на іншу частину програми за необхідністю. Найпростіший цикл (базовий цикл) складається з тіла циклу – набору команд, що підлягають цикліч-ному виконанню, – а також роздільників циклу LOOP і END LOOP з на-ступним загальним видом:

LOOP

тіло_циклу

END LOOP;

Щораз, коли керування доходить до оператора END LOOP, здійснюється повернення на початок циклу, тобто на оператор LOOP. Звичайно, такий цикл буде виконуватися нескінченно, якщо в ньому немає команд, що виводять керування за його межі.

Цикл може бути перерваний, якщо всередині нього виконається команда EXIT. Команда EXIT передає керування на команду, що випливає за END LOOP, у такий спосіб закінчуючи роботу циклу. Загальний вид оператора EXIT наступний:

EXIT мітка_циклу(WHEN (умова));

Наприклад: EXIT мітка;

EXIT мітка WHEN var1 <= var2; EXIT мітка WHEN var3 LIKE '%S%';

EXIT мітка WHEN var4 BETWEEN '01.12.1998' AND '01.09.2003'; EXIT мітка WHEN var5 IS NOT NULL;

EXIT мітка WHEN bool_var x IN ('Y','N','YES','NO') (a = b OR c = 5) AND p < 400;

Команда EXIT може бути задана як на кожній з галузей умовного оператора, так і окремо граничною командою усередині циклу. У цьому випадку для завдання виходу із циклу за умовою в команді EXIT може бути заданий оператор WHEN. Наприклад:

SQL> SET SERVEROUTPUT ON SQL> DECLARE

2counter NUMBER(2) := 0;

3BEGIN

4DBMS_OUTPUT.enable;

5LOOP

6counter := counter + 1;

7IF counter = 5 THEN EXIT WHEN ;

8END IF;

9INSERT INTO "СООБЩ" ("ЧИСЛО1","СИМВОЛ1") VALUES

(counter,' LOOP-Тест'); 10 ROLLBACK;

11 DBMS_OUTPUT.put_line('Транзакція №' || counter);

12 END LOOP;

13 END; 14/

Транзакція №1 Транзакція №2 Транзакція №3 Транзакція №4

Процедура PL/SQL успішно завершена.

Аналогічний приклад з виходом за умовою WHEN:

SQL> SET SERVEROUTPUT ON SQL> DECLARE

2counter NUMBER(2) := 0;

3BEGIN

4DBMS_OUTPUT.enable;

5LOOP

6counter := counter + 1;

7EXIT WHEN counter = 5;

8INSERT INTO "СООБЩ" ("ЧИСЛО1","СИМВОЛ1") VALUES

(counter,' LOOP-Тест');

9ROLLBACK;

10DBMS_OUTPUT.put_line('Транзакція №' || counter);

11END LOOP;

12END;

13/

Транзакція №1 Транзакція №2 Транзакція №3 Транзакція №4

Процедура PL/SQL успішно завершена.

Іншим варіантом виходу з циклу може служити завдання усередині циклу оператора безумовного переходу GOTO на мітку, що стоїть поза циклом. Це, однак, є відступом від методу структурного програмування.

12. Цикл умовної ітерації WHILE

У більших програмах може знадобитися якийсь час на пошуки в коді умови виходу із циклу LOOP, і завжди є ймовірність його пропустити або помістити в розділ коду, що не завжди виконується. Тому в мові PL/SQL є цикл умовної ітерації WHILE, який дозволяє переходити на чергову ітерацію за умовою. Загальний вид циклу наступний:

WHILE (умова)

LOOP

(тіло_циклу);

END LOOP;

Умова перевіряється перед стартом кожної чергової ітерації, і переривання виконання циклу виробляється, коли результат перевірки умови повертає FALSE. Якщо умова повертає значення FALSE перед першою ітерацією, то цикл не виконується ні разу. Приклад використання циклу WHILE:

SQL> SET SERVEROUTPUT ON SQL> DECLARE

2counter NUMBER(2) := 0;

3BEGIN

4DBMS_OUTPUT.enable;

5WHILE counter < 5

6LOOP

7counter := counter + 1;

8INSERT INTO "СООБЩ" ("ЧИСЛО1","СИМВОЛ1") VALUES

(counter,' WHILE-Тест');

9ROLLBACK;

10DBMS_OUTPUT.put_line('Транзакція №' || counter);

11END LOOP;

12END;

13/

Транзакція №1 Транзакція №2 Транзакція №3 Транзакція №4 Транзакція №5

Процедура PL/SQL успішно завершена.

Зрозуміло, якщо задекларовані в умові змінні не будуть змінюватися в процесі виконання тіла циклу, то перевірка умови буде завжди видавати позитивний результат і відбудеться зациклення. Крім основної умови виходу, може також бути задана команда EXIT як альтернативний варіант переривання циклу.

13. Цикл FOR

Цикл типу FOR має ту ж загальну структуру, що й базовий цикл, але з додаванням керуючого оператора FOR на початку циклу, що визначає необхідне число ітерацій. Загальний вигляд циклу фіксованої ітерації такий:

FOR <контрольна_змінна> IN [REVERSE] <min_значення>.. <max_значення>

LOOP <тіло_циклу>

END LOOP;

де «контрольна_змінна» становить собою ім'я цілочисельної змінної, чиє значення буде автоматично збільшуватися або зменшуватися в циклі. Ця змінна створюється циклом і може бути використана для посилання на її значення в будь-якій команді усередині циклу. Значення контрольної змінної залишається певним до закінчення виконання циклу;

«min_значення» і «max_значення» – цілочисельні вираження визначального діапазону значень контрольної змінної.

За замовчуванням контрольна змінна приймає спочатку мінімальне значення, потім зростає на +1 з кожною ітерацією циклу, поки не досягне максимального значення. При цьому наприкінці останньої ітерації виробляється вихід із циклу, наприклад:

SQL> SET SERVEROUTPUT ON SQL> BEGIN

2DBMS_OUTPUT.enable;

3FOR i IN 1 .. 5

4LOOP

5INSERT INTO "СООБЩ" ("ЧИСЛО1","СИМВОЛ1") VALUES (i,'

FOR-Тест');

6ROLLBACK;

7DBMS_OUTPUT.put_line('Транзакція №' || i);

8END LOOP;

9END;

10/

Транзакція №1 Транзакція №2 Транзакція №3 Транзакція №4 Транзакція №5

Процедура PL/SQL успішно завершена.

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

За допомогою ключового слова REVERSE можна задавати зменшення контрольної змінної від початкового максимального значення до кінцевого мінімального (порядок завдання мінімального й максимального значень у команді при цьому не міняється), наприклад:

SQL> SET SERVEROUTPUT ON SQL> BEGIN

2DBMS_OUTPUT.enable;

3FOR i IN REVERSE 1 .. 5

4LOOP

5INSERT INTO "СООБЩ" ("ЧИСЛО1","СИМВОЛ1") VALUES (i,' FOR-Тест');

6ROLLBACK;

7DBMS_OUTPUT.put_line('Транзакція №' || i);

8END LOOP;

9END;

10/

Транзакція №5 Транзакція №4 Транзакція №3 Транзакція №2 Транзакція №1

Процедура PL/SQL успішно завершена.

Крім основної умови виходу в циклах типу FOR і WHILE, може також бути задана команда EXIT як альтернативний варіант переривання їхнього виконання.

14. Керування вкладеними циклами

Цикли можуть бути вкладеними один в один на кілька рівнів. При цьому цикл типу FOR може бути вкладений у цикл WHILE і т. п. Вихід із вкладеного циклу як правило не спричиняє виходу з зовнішнього циклу (якщо, звичайно, не виникло особливої ситуації, що завжди перериває виконання блоку). Все-таки існує можливість перервати виконання й зовнішній цикл із внутрішнього за допомогою команди EXIT – якщо задати мітки циклів. Цикли можуть позначатися постановкою мітки перед ключовим словом LOOP і після END LOOP у такий спосіб:

<< мітка >>

LOOP

тіло_циклу

END LOOP <<мітка>>;

Якщо вкладений цикл містить команду EXIT, то при вказівці в ній мітки зовнішнього циклу відбудеться переривання зовнішнього циклу, наприклад:

SQL> SET SERVEROUTPUT ON SQL> DECLARE

2j NUMBER(2);

3BEGIN

4DBMS_OUTPUT.enable;

5<<main>>

6FOR i IN 1 .. 5

7LOOP

8DBMS_OUTPUT.put_line('Ітерація зовнішнього циклу №' || i);

9j := 1;

10WHILE j < 10

11LOOP

12EXIT main WHEN main.i = 3;