Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
work_4.doc
Скачиваний:
4
Добавлен:
09.11.2019
Размер:
158.72 Кб
Скачать

2.4 Обработка ошибок в pl/pgSql-функциях

Ошибки, возникающие при выполнении команд в блоке, отслеживаются с помощью предложения EXCEPTION, синтаксис котрого имеет вид:

BEGIN

… ; -- тело блока

EXCEPTION

WHEN условие [ OR условие ... ] THEN

обработчик_исключения

[ WHEN условие [ OR условие... ] THEN

обработчик_исключения

... ]

END;

Если возникает ошибка, то выполнение команд в блоке прерывается и управление передается в раздел EXCEPTION, где производится поиск первого из условий, удовлетворяющих возникшей ошибке, и запускается соответствующий обработчик. После чего управление передается следующей после END команде. Если ни одно из условий не удовлетворяет ошибке, обработка исключения передается первому из объемлющих блоков, в котором есть раздел EXCEPTION. Если такого блока нет, выполнение функции останавливается и выводится сообщение об ошибке. Список кодов ошибок приведен в документации к PostgreSQL в Приложении А.

Для отслеживания ошибок при выполнении команд SQL в PostgreSQL можно использовать специальную системную переменную FOUND типа boolean. Эта переменная является локальной и меняет исходное значение false на true в следующих случаях:

  • SELECT, UPDATE, INSERT, DELETE  если хотя бы одна строка включается в результат, т.е. выбирается, модифицируется, вставляется или удаляется;

  • FOR  если выполняется хотя бы одна итерация цикла;

  • RETURN QUERY, RETURN QUERY EXECUTE  если запрос возвращает хотя бы одну строку.

Примеры

/* Добавление строки в таблицу Доставка БД BookShop */

DROP TABLE "Доставка";

CREATE TABLE "Доставка"

( "Заказ" bigint NOT NULL,

"Курьер" character varying(40) DEFAULT 'foo'::character varying,

"Дата_время" timestamp without time zone DEFAULT now(),

"Доставлен" boolean DEFAULT false,

CONSTRAINT "PK_delivery" PRIMARY KEY ("Заказ") );

CREATE FUNCTION insert_delivery( order_id bigint, courier character varying, date_time timestamp without time zone)

RETURNS VOID AS

$$ BEGIN

INSERT INTO “Доставка” ("Заказ", "Курьер" , "Дата_время") VALUES ($1,$2,$3);

RETURN;

/* нарушение ограничения уникальности для первичного ключа*/

EXCEPTION WHEN unique_violation THEN

LOOP

UPDATE “Доставка” SET "Курьер" = $2, "Дата_время" = $3

WHERE "Заказ" = $1;

IF FOUND THEN RETURN;

END LOOP;

END; $$

LANGUAGE plpgsql;

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

3Триггеры

Триггеры – это специальный тип функций, которые выполняются автоматически при выполнении инструкций языка манипулирования данными (INSERT, UPDATE, DELETE). Триггеры обычно используются для внесения каскадных изменений в связанные таблицы или для выполнения сложных ограничений, которые нельзя реализовать стандартными средствами SQL.

Триггеры делятся на два вида: триггеры (FOR EACH ROW), вызываемые для каждой из строк, участвующих в операции, и триггеры (FOR EACH STATEMENT), которые вызываются один раз для каждой операции. Триггеры также могут вызываться до (before-триггеры) начала выполнения операции и после (after-триггеры).

Триггеры создаются с помощью команды CREATE TRIGGER, в которой указывается, какая функция будет выполняться при вызове триггера. Эти функции могут создаваться на любом из поддерживаемых процедурных языков, например, на PL/pgSQL. Они должны быть определены без параметров и с возвращаемым значением типа trigger. Когда такая функция запускается на исполнение, в ее основном блоке (блок самого верхнего уровня) создаются несколько переменных, в которых фиксируются параметры соответствующего триггера, и две буферные переменные:

NEW  переменная типа RECORD, в которой содержится новая строка для INSERT/UPDATE-триггеров типа FOR EACH ROW или значение NULL для триггеров типа FOR EACH STATEMENT и для INSERT/UPDATE-триггеров типа FOR EACH ROW;

OLD  переменная типа RECORD, в которой содержится старая строка для UPDATE/DELETE-триггеров типа FOR EACH ROW или значение NULL для триггеров типа FOR EACH STATEMENT и для INSERT-триггеров типа FOR EACH ROW.

Примеры:

/* Создаем таблицу */

CREATE TABLE emp (

a text NOT NULL,

b integer NOT NULL CHECK (b>0),

last_date timestamp,

last_user text );

/* Создаем триггерную функцию */

CREATE FUNCTION stamp() RETURNS trigger AS

$stamp$

BEGIN

-- Проверка a= null и b= null и b>0'

IF NEW.a IS NULL THEN

RAISE EXCEPTION 'a не может бать null !';

END IF;

IF NEW.b IS NULL THEN

RAISE EXCEPTION ' b не может бать null ! ', NEW.a;

END IF;

IF NEW.b < 0 THEN

RAISE EXCEPTION ‘ b = % должно быть положительным !', NEW.b;

END IF;

-- Заносим в таблицу текущее время и текущего пользователя

NEW.last_date := current_timestamp;

NEW.last_user := current_user;

RETURN NEW;

END;

$stamp$ LANGUAGE plpgsql;

/ * Создаем тригер */

CREATE TRIGGER stamp BEFORE INSERT OR UPDATE ON emp

FOR EACH ROW EXECUTE PROCEDURE stamp();

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]