Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
PMO_PMS_shpory_final.docx
Скачиваний:
7
Добавлен:
17.09.2019
Размер:
457.71 Кб
Скачать
  1. Расширения языка sql для использования в хранимых процедурах и триггерах. Циклы и ветвления. Обработка исключений и ошибок.

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

Помимо команды FOR SELECT... DO, организующей цикл по записям какой-либо выборки, существует другой вид цикла - WHILE...DO, который позволяет организовать цикл на основе проверки любых условий. Вот пример ХП, использующей цикл WHILE.. DO. Эта процедура возвращает квадраты целых чисел от 0 до 99:  CREATE PROCEDJRE QUAD   RETURNS (QUADRAT INTEGER)   AS  DECLARE VARIABLE I INTEGER;   BEGIN   I = 1;  WHILE (i<100) DO   BEGIN  QUADRAT= I*I;  I=I+1;   SUSPEND;   END   END  В результате выполнения запроса SELECT • FROM QUAD мы получим таблицу, содержащую один столбец QUADRAT, в котором будут квадраты целых чисел от 1 до 99  Помимо перебора результатов SQL-выборки и классического цикла, в языке хранимых процедур используется оператор IF...THEN..ELSE, позволяющий организовать ветвление в зависимости от выполнения каких-либо условий

  1. Вычисляет среднюю цену в таблице Table_example (см. глава "Таблицы Первичные ключи и генераторы")

  2. Далее для каждой записи в таблице делает след>ющ)ю проверку, если существующая цена (PRICE) больше средней цены, то устанавливает цену, равную величине средней цены, плюс задаваемый фиксированный процент

  3. Если существующая цена меньше или равна средней цене, то устанавливает цену, равную прежней цене, плюс половина разницы между прежней и средней ценой.

  4. Возвращает все измененные строки в таблице.

CREATE PROCEDURE IncreasePrices (  Percent2Increase DOUBLE PRECISION)  RETURNS (ID INTEGER, NAME VARCHAR(80),  new_price DOUBLE PRECISION) AS  DECLARE VARIABLE avg_price DOUBLE PRECISION;  BEGIN  SELECT AVG(Price_l)  FROM Table_Example  INTO :avg_price;  FOR  SELECT ID, NAME, PRICE_1   FROM Table_Example   INTO :ID, :NAME, :new_price   DO  BEGIN  /*здесь обрабатываем каждую запись*/  IF (new_pnce > avg_price) THEN /*если существующая цена больше средней цены*/  BEGIN  /*установим новую цену, равную величине средней цены, плюс фиксированный процент */  new_price = (avg_price + avg_price*(Percent2lncrease/100));   UPDATE Table_example   SET PRICE_1 = :new_price   WHERE ID = :ID;   END   ELSE   BEGIN  /* Если существующая цена меньше или равна средней цене, то устанавливает цену, равную прежней цене, плюс половина разницы между прежней и средней ценой */  new_price = (new_price + ((avg_price - new_price)/2));   UPDATE Table_example   SET PRICE_1 = :new_price   WHERE ID = :ID;   END  SUSPEND;   END   END  Данный пример хранимой процедуры иллюстрирует применение основных конструкций языка хранимых процедур и триггеров. Далее мы рассмотрим способы применения хранимых процедур для решения некоторых часто возникающих задач.

Расширенные возможности языка хранимых процедур InterBase

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

Исключения

Создается исключение следующим образом:  СРЕАТЕ EXCEPTION <имя_исключения> <текст_исключения>;  Например, мы можем создать исключение такого вида:  CREATE EXCEPTION test_except 'Test exception';  Исключение легко удалить или изменить - удаление совершается командой DROP EXCEPTION <имя_удаляемого_исключения>, а изменение - ALTER EXCEPTION <имя_исключения> <текст_исключения>  Чтобы использовать исключение в хранимой процедуре или триггере, необходимо воспользоваться командой следующего вида:  EXCEPTION <имя_исключения>;  Нам необходимо отследить случай деления на нуль и возбудить исключение, если делитель равен нулю.  Для нашего примера создадим следующее исключение:  CREATE EXCEPTION zero_divide 'Cannot divide by zero!';  Создадим хранимую процедуру, использующую это исключение:  CREATE PROCEDURE sp_test_except(Delltel DOUBLE PRECISION)  RETURNS (rslt DOUBLE PRECISION, status VARCHAR(SO))  AS  BEGIN  Status='Everything is Ok';  SELECT result FROM sp_divide(12,:Delitel) INTO :rslt;  SUSPEND;  WHEN EXCEPTION Zero_divide DO   BEGIN  Status='zero value found!';   rslt=-l;   SUSPEND;   END   END  Эта процедура вызывает процедуру SP_DIVIDE. Если параметр Delitel не равен нулю, то процедура SP_DIVIDE выполняется без проблем и в возвращаемое значение rslt помещается частное от деления, а статусная переменная status принимает значение 'Everything is Ok'. В случае, если возникла исключительная ситуация деления на нуль, то результирующая переменная rslt будет равна -1, а в переменной status будет содержаться сообщение об ошибке - 'zero value found!'. Разумеется, в обработчике исключения можно произвести и более сложную обработку, например записать некорректные данные в особую таблицу или попытаться изменить данные для выполнения операции и вновь попробовать ее выполнить и т. д.

Обработка ошибок SQL и InterBase

Ошибка - это фактически то же самое исключение, только возбуждаемое InterBase. Принцип обработки ошибок тот же самый что и исключений: если возникает какая-то ошибка, то сервер ищет ее обработчик, последовательно просматривая все уровни вложенности (если они есть) хранимой процедуры, начиная с того уровня, на котором возникла ошибка.  Если обработчик найден, то выполняется код внутри его, а затем управление передается на первый оператор за обработчиком исключений.  Конструкция, с помощью которой производится обработка ошибок, такая же, как и для обработки исключений, только вместо EXCEPTION стоит либо GDSCODE, либо SQLCODE:  WHEN GDSCODE SQLCODE <код_ошибки> DO   BEGIN  /*обрабатываем ошибку*/   END  В зависимости от того, стоит ли в конструкции обработки ошибок GDSCODE или SQLCODE, обрабатываются различные ошибки. Если стоит SQLCODE, то обрабатываются ошибки SQL, а если GDSCODE - то ошибки InterBase. Примером ошибки SQL является ошибка с SQLCODE=-802 "Arithmetic exception, numeric overflow, or string truncation" или SQLCODE=-817 "Attempted update during read-only transaction" Список ошибок SQL и соответствующих им значений SQLCODE приведен в таблице "SQLCODE codes and messages'. Примером ошибки InterBase является ошибка isc_bad_dbkey 335544322L "invalid database key".   Таким образом, внутри хранимой процедуры можно "перехватить" практически любую ошибку и корректно на нее отреагировать. Можно перечислять обработчики ошибок один за другим, чтобы определить реакцию на разные ошибки.  Для того чтобы написать безусловный обработчик, реагирующий на любую ошибку - SQL, InterBase или исключение, следует воспользоваться конструкцией WHEN DO с ключевым словом ANY:  WHEN ANY DO   BEGIN   /*действия при любой нестандартной операции ошибке  или исключении */   END 

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