ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 12.04.2021

Просмотров: 1876

Скачиваний: 3

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

!

26

Пр

акт

ич

еск

ое

зан

ят
ие

4

Со

зда

ни

е

ис

по

лне

ни

е

и

отл

адк

а

хра

ни

мы

х

пр

оце

дур

и

тр

игг
еро

в

!

!

 
 

E-

mail

mar

ket

@re

lex.r

u

ЗАО

execute direct "update SEQUENCES set CUR_VALUE = CUR_VALUE 
+ “+itoa(change)+” where TAB_NAME = '"  

Теперь

процедура

транслируется

удачно

о

чем

свидетельствует

исчезнувшее

окно

с

ошибками

Заметим

что

при

подаче

запроса

из

  inl 

мы

не

получим

полной

расшифровки

ошибок

только

общий

код

завершения

 7200 – 

ошибка

трансляции

хранимой

процедуры

Попробуйте

запустить

процедуру

с

разными

значениями

параметра

  change. 

Можно

запустить

процедуру

из

  inl, 

по

-

прежнему

указывая

всего

один

параметр

Второй

параметр

будет

обрабатываться

по

умолчанию

как

единица

4.3. 

Обработка

ошибок

исключения

Наша

процедура

будет

некорректно

работать

если

в

качестве

значения

параметра

change 

передать

значение

меньшее

единицы

или

  NULL. 

Мы

можем

вставить

соответствующую

проверку

в

начало

тела

процедуры

if  change = NULL or change < 1 then 
   signal 

INVPARAM

endif 

Оператор

  signal 

вызывает

исключение

с

именем

INVPARAM

Это

исключение

необходимо

описать

в

секции

деклараций

процедуры

например

перед

ключевым

словом

code: 

exception INVPARAM for BADPARAM; 

Здесь

мы

назначили

исключению

имя

стандартного

и

критичного

исключения

BADPARAM, 

т

.

е

оно

тут

же

завершает

исполнение

хранимой

процедуры

и

передает

состояние

исключения

В

качестве

результата

таким

образом

завершенной

процедуры

всегда

будет

 NULL. 

Попробуем

запустить

процедуру

и

указать

неправильное

значение

  (

например

,  0) 

в

качестве

параметра

  change. 

Отладчик

всегда

останавливается

в

строке

в

которой

произошло

исключение

Если

мы

запустим

процедуру

с

неверными

параметрами

из

  inl, 

то

тоже

получим

информацию

об

исключении

Запрос

 execute, 

завершившийся

с

исключением

всегда

имеет

код

возврата

 7201. 

Чтобы

обработать

исключение

внутри

процедуры

необходимо

использовать

блок

EXCEPTIONS, 

как

было

рассмотрено

в

лекции

.  

Например

если

присоединиться

к

БД

от

имени

пользователя

отличного

от

создателя

процедуры

то

при

попытке

выполнить

процедуру

  (

ее

имя

в

запросе

  execute, 

кстати

должно

будет

уже

включать

имя

владельца

отделенной

точкой

от

собственно

имени

может

возникнуть

ошибка

доступа

к

таблице

  SEQUENCES  2202  (

у

пользователя

скорее

всего

не

будет

таблицы

с

именем

 SEQUENCES).   

(

Замечание

конечно

мы

могли

бы

в

запросах

явно

написать

 SYSTEM.SEQUENCES; 

это

более

верно

но

тем

не

менее

может

возникнуть

ошибка

нарушения

прав

доступа

чтобы

процедура

реально

работала

для

нескольких

пользователей

обычно

удобно

создать

общие

  (PUBLIC) 

синонимы

на

используемые

таблицы

или

же

использовать

полное

имя

таблицы

и

в

любом

случае

надо

назначить

необходимые

права

grant execute on GENERATEPK to PUBLIC;

). 

Если

мы

подадим

запрос

на

выполнение

  SYSTEM.GENERATEPK 

из

-

под

другого

пользователя

  (

не

  SYSTEM), 

то

увидим

что

процедура

всегда

возвращает

  1. 

Чтобы

разобраться

в

чем

дело

можно

запустить

ожидание

процедуры

и

прийти

в

режим

ее

отладки

В

отладчике

мы

видим

что

при

попытке

исполнения

запросов

происходит

исключение

  2202  (

нет

такой

таблицы

), 

но

процедура

продолжает

исполняться

Это

происходит

из

-

за

того

что

исключение

некритичное

и

при

отсутствии

обработки

оно

просто

игнорируется

Значит

нам

необходимо

обработать

это

исключение

В

секции

определений

объявим

исключение


background image

!

!

Пр

акт

ич

еск

ое

зан

ят
ие

4

Со

зда

ни

е

ис

по

лне

ни

е

и

отл

адк

а

хра

ни

мы

х

пр

оце

дур

и

тр

игг
еро

в

!

27

 
 

E-

mail

mar

ket

@re

lex.r

u

ЗАО

exception NOTAB for 2202; 

А

в

конец

процедуры

 (

перед

 end) 

добавим

блок

обработки

исключения

exceptions 
   when NOTAB then 
     resignal; 

Оператор

  resignal 

завершает

процедуру

и

передает

состояние

исключения

на

уровень

выше

Теперь

наша

процедура

корректно

реагирует

на

ошибку

 2202 

исполнения

запросов

4.4. 

Упражнение

создание

еще

одной

процедуры

Заметим

что

в

нашей

задаче

с

генерациями

уникальных

значений

для

каждой

таблицы

не

учитывается

ситуация

когда

некоторая

таблица

будет

удалена

а

в

последствии

создана

другая

таблица

с

таким

же

именем

По

-

хорошему

надо

при

удалении

таблицы

удалять

и

соответствующую

запись

из

таблицы

 SEQUENCE. 

Это

логику

удобно

вынести

в

отдельную

хранимую

процедуру

назовем

ее

DropTabWithSequence. 

Процедура

должна

сначала

удалить

таблицу

а

затем

в

случае

успеха

удалить

соответствующую

запись

из

таблицы

 SEQUENCES.  

spman 

предоставляет

специальный

интерфейс

для

создания

процедур

по

сути

он

просто

подготовит

запрос

 create procedure 

для

Вас

Используйте

пункт

 «

Новая

процедура

» 

меню

  «

Файл

». 

Предупреждение

в

диалоге

создания

процедуры

регистр

символов

имени

имеет

значение

так

что

если

Вы

не

хотите

потом

точно

повторять

имя

процедуры

и

заключать

его

в

кавычки

имя

процедуры

надо

набрать

в

верхнем

регистре

В

результате

получаем

окно

с

шаблоном

текста

процедуры

Надо

дописать

входной

параметр

 (

имя

таблицы

и

тело

процедуры

 (

указание

для

проверки

любого

ненормального

кода

завершения

запроса

 drop table 

удобно

использовать

стандартную

функцию

 errcode). 

Примечание

Студенты

пытаются

написать

процедуру

сами

(

процедура

должна

иметь

примерно

такой

вид

create procedure "DROPTABWITHSEQUENCE"(in tabname char(64)) 

for debug 
code 
   execute direct "drop table "+tabname+";"; 
   if errcode() = 0 then 
      execute direct "delete from SEQUENCES where 

tab_name='"+tabname+"';"; 
      commit; 
   endif 
end; 

)  

4.5. 

Создание

триггера

Рассмотрим

пример

триггера

который

использует

созданную

нами

ранее

хранимую

процедуру

для

генерации

значений

первичного

ключа

при

вставке

записей

в

некоторую

таблицу

 OBJECT: 

create table object(id int primary key, value varchar(64)); 

Триггер

позволяет

принудительно

установить

значение

поля

 ID 

новой

записи

какое

бы

значение

не

задал

пользователь

в

исходном

запросе

create trigger INS_OBJECT before insert on object 


background image

!

28

Пр

акт

ич

еск

ое

зан

ят
ие

4

Со

зда

ни

е

ис

по

лне

ни

е

и

отл

адк

а

хра

ни

мы

х

пр

оце

дур

и

тр

игг
еро

в

!

!

 
 

E-

mail

mar

ket

@re

lex.r

u

ЗАО

for each row execute for debug 
code 
   call GeneratePk("OBJECT") into new.id; // 
end; 

Соответствующие

  SQL-

операторы

содержатся

в

файле

  trig_obj.sql. 

Его

можно

исполнить

обычным

способом

через

 inl. 

Теперь

попробуйте

добавить

несколько

записей

в

таблицу

  object. 

Потом

подать

  SELECT 

из

этой

таблицы

  – 

мы

видим

сгенерированные

значения

колонки

 ID. 

Это

иллюстрация

только

одной

области

применения

триггеров

Допустим

теперь

что

мы

хотим

хранить

информацию

обо

всех

изменениях

сделанных

в

таблице

  OBJECT 

в

разные

моменты

времени

.  

Для

этого

создадим

еще

одну

таблицу

create table object_history(id int, dt date, value 
varchar(64), status char(1)); 
alter table object_history add primary key(id, dt); 

Дополнительными

атрибутами

здесь

являются

 dt – 

дата

изменения

и

 status – 

статус

изменения

 – 

одна

из

букв

 ‘I’, ‘U’ 

или

 ‘D’. 

Чтобы

обеспечить

занесение

в

эту

таблицу

записей

после

успешного

изменения

таблицы

  OBJECT, 

можно

создать

триггеры

на

различные

виды

  DML-

запросов

аналогично

следующему

create trigger INS_OBJECT_HIST after insert on object 
for each row execute for debug 
code 
   execute direct  
 "insert into OBJECT_HISTORY(id, dt, value, status) 
values(“ +  
     itoa(new.id) + “, sysdate, '” + new.value + “', 
'I');"; // 
end; 

В

файле

 obj_hist.sql 

содержатся

запросы

на

создание

таблицы

 OBJECT_HISTORY 

и

двух

триггеров

на

добавление

и

на

изменение

данных

Прогоните

этот

файл

в

  inl 

и

попробуйте

добавить

и

обновить

несколько

записей

в

таблице

  OBJECT. 

Затем

сделайте

  SELECT 

из

таблицы

  OBJECT_HISTORY. 

Вы

должны

увидеть

историю

сделанных

изменений

Теперь

не

хватает

только

триггера

на

  DELETE. 

Создайте

его

самостоятельно

В

качестве

упражнения

используем

для

этого

утилиту

  spman. 

Утилита

  spman 

включает

диалоговое

окно

для

упрощения

создания

триггера

также

как

и

для

хранимых

процедур

Выберите

пункт

  «

Новый

триггер

» 

в

меню

  «

Файл

». 

Введите

все

характеристики

триггера

в

диалоговом

окне

У

вас

должно

открыться

окно

с

шаблоном

нового

триггера

примерно

такого

содержания

create trigger "DEL_OBJECT_HIST" 
after delete on OBJECT for each row 
execute for debug 


background image

!

!

Пр

акт

ич

еск

ое

зан

ят
ие

4

Со

зда

ни

е

ис

по

лне

ни

е

и

отл

адк

а

хра

ни

мы

х

пр

оце

дур

и

тр

игг
еро

в

!

29

 
 

E-

mail

mar

ket

@re

lex.r

u

ЗАО

code 
end; 

Вставьте

соответствующий

оператор

между

  code 

и

  end 

и

сохраните

триггер

  (

как

обычно

командой

сохранения

или

клавишей

 <F2>). 

При

сохранении

триггера

могут

возникнуть

ошибки

компиляции

которые

обрабатываются

так

же

как

и

для

хранимых

процедур

4.6. 

Модификация

триггера

Для

модификации

триггера

необходимо

удалить

старый

триггер

 (

запрос

 drop trigger), 

и

затем

пересоздать

новый

. spman 

автоматически

делает

эти

операции

при

необходимости

Модифицируем

наш

самый

первый

триггер

  (INS_OBJECT) 

так

чтобы

он

запрещал

добавление

в

таблицу

 OBJECTS 

строк

у

которых

значение

 value 

равно

 NULL (

простейшая

проверка

которая

может

быть

выполнена

и

декларативным

способом

но

потенциально

триггер

может

реализовать

любой

алгоритм

проверки

). 

Выбираем

в

  spman 

команду

  «

Открыть

триггер

» 

меню

  «

Файл

». 

В

результате

откроется

окно

существующего

триггера

В

начало

тела

триггера

добавим

проверку

if new.value = NULL then 
   return false; 
endif 

Возврат

 false 

из

триггера

означает

запрет

текущей

операции

Сохраняем

триггер

и

пробуем

теперь

выполнить

в

 inl 

такой

запрос

insert into object(id) values(0); 

Получаем

сообщение

о

том

что

добавлено

 0 

строк

 – 

это

результат

работы

триггера

4.7. 

Отладка

триггера

Триггер

можно

отлаживать

точно

так

же

как

и

хранимую

процедуру

Отличие

в

том

что

можно

отладить

триггер

только

ожидая

его

инициирования

внешним

запросом

Откроем

в

  spman 

триггер

  INS_OBJECT.   

Включим

отладочную

сессию

  (

клавиша

<F4>)  

и

режим

ожидания

 (

клавиши

 <Alt>-<F9>).  

Теперь

перейдем

в

 inl 

и

подадим

запрос

insert into object(id) values(0); 

В

результате

попадаем

в

отладку

триггера

Можно

отследить

по

шагам

что

происходит

внутри

него

.  

Повторим

то

же

самое

для

другого

допустимого

запроса

Видно

что

триггер

выполняется

по

другой

ветке

В

частности

можно

войти

внутрь

вызываемой

из

триггера

процедуры

.


background image

!

!

!

30

E-mail: market@relex.ru

ЗАО

НПП

 «

РЕЛЭКС

»

http://www.relex.ru

Практическое

занятие

 5

Разграничение

доступа

в

СУБД

ЛИНТЕР

Дискреционный

доступ

Практика

 2 

часа

 (

Лекция

 5)

Целью

занятия

является

освоение

способов

разграничения

доступа

к

базе

данных

на

основе

дискреционного

доступа

При

выполнении

задания

будет

использовано

приложение

 «

Интерактивный

 SQL» (INL). 

5.1. 

Создание

нового

пользователя

Полномочия

пользователей

Различные

пользователи

являются

владельцами

данных

которые

находятся

в

созданных

ими

таблицах

Рассмотрим

на

следующей

задаче

.

Задача

:

Создать

двух

пользователей

 A 

и

 B, 

создать

от

имени

пользователя

 A 

таблицу

для

хранения

телефонной

книги

предоставить

пользователю

  B 

доступ

для

чтения

и

добавления

данных

.

Решение

Запускаем

утилиту

  INL, 

вводим

имя

и

пароль

администратора

базы

данных

или

пользователя

обладающего

привилегией

администратора

базы

данных

 (DBA). 

1.

Создаем

пользователей

 A 

и

 B 

с

паролями

 ‘1’ 

и

 ’2’:

create user A identified by ‘1’; 
create user B identified by ‘2’;

2.

Даем

пользователю

 A 

привилегию

 RESOURCE: 

grant resource to A; 

3.

Выходим

из

утилиты

  INL 

командой

  exit 

и

запускаем

утилиту

повторно

с

именем

пользователя

 ‘A’ 

и

паролем

 ‘1': 

4.

Создаем

таблицу

для

хранения

телефонов

:

create table PHONES(ID integer autoinc,NAME char(20), PHONE char(12));

5.

Передаем

привилегии

на

чтение

и

вставку

пользователю

 “B’:

grant select,insert on PHONES to B; 

6.

Выходим

из

утилиты

  INL 

командой

  exit 

и

запускаем

утилиту

повторно

с

именем

пользователя

 ‘B’ 

и

паролем

 ‘2': 

7.

Осуществляем

вставку

данных

:

insert into A.PHONES(NAME,PHONE) values(‘

Иванов

’,’8-095-167-34-80’);

8.

Осуществляем

выборку

данных

:

select * from A.PHONES;

Задачи

для

самостоятельной

работы

1.

Создать

пользователя

с

привилегией

 DBA, 

создать

от

имени

этого

пользователя

таблицы

для

хранения

почтовых

адресов

предприятий

  (

название

почтовый

индекс

город

улица

дом

а

/

я

). 

Созданным

ранее

пользователям

  A,B  

предоставить

возможность

заполнения

модификации

удаления

и

просмотра

данных

из

этой

таблицы

Всем

остальным

пользователям

предоставить

возможность

только

чтения

данных

из

созданной

таблицы

5.2. 

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

представлений

для

разграничения

доступа

Для

  «

вертикального

» 

разграничения

доступа

к

таблице

используются

представления

Рассмотрим

это

на

следующей

задаче

.