Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
PAGE 2
17 Перехоплення помилок (PostgreSQL 9.0 Beta, Documentation)
За замовчуванням будь-які помилка, яка виникає в PL/pgSQL перериває виконання функції та зовнішні транзакції. Помилки можна перехоплювати і обробляти за допомогою додатка EXCEPTION до блока BEGIN:
[ <<label>> ]
[ DECLARE
declarations ]
BEGIN
statements
EXCEPTION
WHEN condition [ OR condition ... ] THEN handler_statements
[ WHEN condition [ OR condition ... ] THEN handler_statements ... ]
END;
Якщо помилка не відбувається, то цей блок просто виконує всі оператори, а потім управління передається наступному оператору. Якщо відбулася помилка у операторі, то виконання програми припиняється і управління передається до списку винятків EXCEPTION. У списку відбувається пошук першої умови відповідності помилки. Якщо збіг знайдено, то відповідний handler_statements виконується, після чого управління передається наступному оператору. Якщо відповідність не знайдено, то помилка залишається необробленою так, ніби застереження не було, відбувається переривання роботи функції.
Імена умов можуть бути будь-якими з перелічених у додатку А. Категорія імені збігається з будь-якою помилкою в своїй категорії. Спеціальні умови OTHERS ім'я відповідають тим же помилкам типу, крім QUERY_CANCELED. (Це можливо, але часто нерозумно потрапляти в пастку QUERY_CANCELED за іменем., бо імена не чутливі до регістру). Крім того, помилки можуть бути вказані за кодом SQLSTATE, наприклад, ці секції еквівалентні:
WHEN division_by_zero THEN ...
WHEN SQLSTATE 22012 THEN ...
Якщо нова помилка відбувається протягом обраного handler_statements, то вона не може бути піймана цією секцією EXCEPTION. Її може зловити лише зовнішшній блок EXCEPTION. Коли помилка спіймана у блоці EXCEPTION, то локальні змінні функції PL/pgSQL залишаються, такими ж, коли сталася помилка, але всі зміни в постійне стан бази даних в межах блоку відкат. Як приклад, розглянемо такий фрагмент:
CREATE OR REPLACE FUNCTION p_err(k integer, data character)
RETURNS text AS
$$
DECLARE
s text:='Добре';
BEGIN
UPDATE tab SET naz = 'Липки' WHERE kod = 1; --у таб. Київ
BEGIN
s:=s||' виконано';
INSERT INTO tab VALUES(3, 'Петрос');
INSERT INTO tab VALUES(2, 'Ужгород'); -- у таб.= Ямал
EXCEPTION WHEN unique_violation THEN
s:=s||' все.'||E'\n';
RAISE NOTICE 'Код унікальний, тому не дорівнює %',k;
END;
return s;
END;
$$
LANGUAGE plpgsql;
1 Київ
2 Ямал
select p_err(2,'ooo');
Добре виконано все.
NOTICE: Код унікальний, тому не дорівнює 2
1 Липки
2 Ямал
Коли управління досягає завдання у, то воно не буде виконане через помилку division_by_zero . Це буде спійманий застереженням. Значення х буде збільшене, але наслідки команди UPDATE будуть скасовані. Команда INSERT попереднього блоку не скасовується, тому в результаті таблиця mytab міститиме Tom Jones, а не Joe Jones Порада: блок, який містить застереження є значно більш дорогим для входу і виходу, ніж блок без нього. Тому, не слід його використовувати без особливої необхідності.
У обробник винятків, змінної SQLSTATE містить код помилки, який відповідає винятком того, що був піднятий (див. Таблицю А-1 для список можливих кодів помилок). змінна SQLERRM містить повідомлення про помилку, пов'язані з виключенням. Ці змінні не визначені поза обробників виключень.
Приклад 39-2. Винятки з UPDATE / INSERT
Цей приклад використовує обробку винятків під час вставки даних у таблицю db:
CREATE TABLE db(a INT PRIMARY KEY, b TEXT);
CREATE OR REPLACE FUNCTION merge_db(key INT, data TEXT)
RETURNS VOID AS
$$
BEGIN
INSERT INTO db(a, b) VALUES (key, data);
EXCEPTION
WHEN unique_violation THEN
RAISE NOTICE unique_violation;
END;
$$
LANGUAGE plpgsql;
Таблиця db містить такі два записи:
1 Давид
2 Денис
В результаті виклику функції командою select merge_db(1, 'Петро'); результати не змінюються і видається повідомлення NOTICE: unique_violation. При відсутності секції RAISE NOTICE програма завершується без повідомлення. Якщо в цю секцію помістити якийсь текст, то він буде виданий.
Без блока EXCEPTION одержимо помилку ERROR: duplicate key value violates unique constraint "db_pkey".
Appendix A. PostgreSQL Error Codes
All messages emitted by the PostgreSQL server are assigned five-character error codes that follow the SQL standards conventions for “SQLSTATE” codes. Applications that need to know which error condition has occurred should usually test the error code, rather than looking at the textual error message. The error codes are less likely to change across PostgreSQL releases, and also are not subject to change due to localization of error messages. Note that some, but not all, of the error codes produced by PostgreSQL are defined by the SQL standard; some additional error codes for conditions not defined by the standard have been invented or borrowed from other databases.
According to the standard, the first two characters of an error code denote a class of errors, while the last three characters indicate a specific condition within that class. Thus, an application that does not recognize the specific error code can still be able to infer what to do from the error class.
Table A-1 lists all the error codes defined in PostgreSQL 9.0beta2. (Some are not actually used at present, but are defined by the SQL standard.) The error classes are also shown. For each error class there is a “standard” error code having the last three characters 000. This code is used only for error conditions that fall within the class but do not have any more-specific code assigned.
The PL/pgSQL condition name for each error code is the same as the phrase shown in the table, with underscores substituted for spaces. For example, code 22012, DIVISION BY ZERO, has condition name DIVISION_BY_ZERO. Condition names can be written in either upper or lower case. (Note that PL/pgSQL does not recognize warning, as opposed to error, condition names; those are classes 00, 01, and 02.)
Table A-1. Коди помилок PL/pgSQL (SOLSTATE)
Error Code |
Meaning Condition |
Name |
Class 00 Successful Completion |
||
Class 01 Warning |
||
Class 02 No Data (this is also a warning class per the SQL standard) |
||
02000 |
NO DATA |
|
Class 0B Invalid Transaction Initiation |
||
0B000 |
INVALID TRANSACTION INITIATION |
|
Class 22 Data Exception |
||
22012 |
DIVISION BY ZERO |
division_by_zero |
22005 |
ERROR IN ASSIGNMENT |
error_in_assignment |
2200B |
ESCAPE CHARACTER CONFLICT |
|
22023 |
INVALID PARAMETER VALUE |
|
22003 |
NUMERIC VALUE OUT OF RANGE |
|
Class 23 Integrity Constraint Violation |
||
23000 |
INTEGRITY CONSTRAINT VIOLATION |
integrity_constraint_violation |
23001 |
RESTRICT VIOLATION |
restrict_violation |
23502 |
NOT NULL VIOLATION |
not_null_violation |
23503 |
FOREIGN KEY VIOLATION |
foreign_key_violation |
23505 |
UNIQUE VIOLATION (порушення унікальності) |
unique_violation |
23514 |
CHECK VIOLATION |
check_violation |
Class 26 Invalid SQL Statement Name |
||
26000 |
INVALID SQL STATEMENT NAME |
|
Class 40 Transaction Rollback |
||
40000 |
TRANSACTION ROLLBACK |
|
Class 42 Syntax Error or Access Rule Violation |
||
42601 |
SYNTAX ERROR |
|
42830 |
INVALID FOREIGN KEY |
invalid_foreign_key |
42602 |
INVALID NAME |
invalid_name |
42P07 |
DUPLICATE TABLE |
duplicate_table |
Class 54 Program Limit Exceeded |
||
54000 |
PROGRAM LIMIT EXCEEDED |
program_limit_exceeded |
54001 |
STATEMENT TOO COMPLEX |
statement_too_complex |
54011 |
TOO MANY COLUMNS |
too_many_columns |
54023 |
TOO MANY ARGUMENTS |
too_many_arguments |
Class 58 System Error (errors external to PostgreSQL itself) |
||
58030 |
IO ERROR |
io_error |
58P01 |
UNDEFINED FILE |
undefined_file |
58P02 |
DUPLICATE FILE |
duplicate_file |
Class P0 PL/pgSQL Error |
||
P0000 |
PLPGSQL ERROR |
plpgsql_error |
P0001 |
RAISE EXCEPTION |
raise_exception |
P0002 |
NO DATA FOUND |
no_data_found |
P0003 |
TOO MANY ROWS |
too_many_rows |
Class XX Internal Error |
||
XX000 |
INTERNAL ERROR |
internal_error |
XX001 |
DATA CORRUPTED |
data_corrupted |
CREATE OR REPLACE FUNCTION errory(integer)
RETURNS text AS
$$
DECLARE
k ALIAS FOR $1;
s text:='Результ.: ';
BEGIN
s:=s||erry(k);
s:=s||' штук';
RETURN s;
END;
$$
LANGUAGE plpgsql;
--select errory(5): Результ.: k= 10 штук (при --k:=m/0;)
--select errory(5):Результ.: k= 10 Ділення на 0 штук
CREATE OR REPLACE FUNCTION erry(m integer)
RETURNS text AS
$$
DECLARE
s text;
k integer;
BEGIN
k:=2*m;
s:='k='||TO_CHAR(k,'99')||E'\n';
--erry(7) дає: k=14
-- k:=m/0; erry(7) дає: k=14 Ділення на 0
RETURN s;
EXCEPTION
WHEN SQLSTATE '22012' THEN
--WHEN division_by_zero THEN те ж, що SQLSTATE '22012'
s:=s||' Ділення на 0';
RETURN s; END;
$$
LANGUAGE plpgsql ;
Ініціалізовану помилку блок EXCEPTION обробляє так же, як і виникнену. Покажемо це на прикладі з розділу про ініціалізацію помилки. У функцію raise_err() цього прикладу додамо блок EXCEPTION. Для виклику функції raise_err() застосуємо функцію raise_error().
CREATE OR REPLACE FUNCTION raise_err()
RETURNS integer AS
$$
DECLARE
i integer:= 3;
BEGIN
RAISE DEBUG 'Вивести повідомлення рівня DEBUG';
i:=i*2;
RAISE NOTICE 'Рівень NOTICE';
RAISE NOTICE 'Рівень NOTICE з виводом і=%', i;
RAISE EXCEPTION 'Рівень EXCEPTION і=% (кінець)', i;
EXCEPTION
WHEN raise_exception THEN
i:=12345;
RETURN i;
END;
$$
LANGUAGE plpgsql;
select raise_err();
Результати:
NOTICE: Рівень NOTICE
NOTICE: Рівень NOTICE з виводом і=6
12345
select raise_errory();
Результати:
NOTICE: Рівень NOTICE
NOTICE: Рівень NOTICE з виводом і=6
rrrrrr 12345