PL SQL - DmitryGontarenko/usefultricks GitHub Wiki
PL/SQL - это процедурный язык, разработанный компанией Oracle, который явялется расширением стандартного SQL.
В PL/SQL все символы приводятся к верхнему регистру, поэтому объявленные переменные в примере ниже - будут идентичны.
a varchar2(255);
A varchar2(255);
Специальные символы:
Большенство символов (арифметических и логических), схожи со стандартными. Рассмотрим особенные для PL/SQL:
:=
- присвоение;
||
- конкатенация строк;
Базовой единицей языка PL/SQL является блок и он имеет три раздела - Declaration (объявления), Body (тело) и Exception (исключения). Но использовать их всегда вместе - необязательно.
declare
-- объявления
begin
-- выполняемый код
exception
-- обработка исключений
end;
/ -- символ завершения для запуска блока на компиляцию
Пример:
set serveroutput on
begin
dbms_output.put_line('Hello World!');
end;
/
Результат:
Hello World!
PL/SQL procedure successfully completed.
Рассмотрим подробнее:
begin
и end
- это обрамляющий программный блок.
Строка set serveroutput on
объявляется перед началом сеанса и говорит о том, что в консоль надо выводить все значения из dbms_output
.
Символ /
запускает скрипт на исполнение.
Рассмотрим пример с блоком declare
:
declare
a integer := 2;
b integer;
begin
b := 3;
dbms_output.put_line(a+b); -- result: 5
end;
/
Мы объявили две переменные целочисленного типа в блоке declare
. Переменную a
мы инициализировали сразу, а переменной b
присвоили значения уже в теле. И как результат мы вывели сумму двух значений этих переменных.
Но при выводе чисел в консоль произошло неявное преобразование типа - из числа в строку. Что бы преобразовать явно, можно воспользоваться методом to_char()
:
dbms_output.put_line(TO_CHAR(a+b));
Так же можно преобразовать и строку в число, воспользовавшись методом to_number()
:
dbms_output.put_line(TO_CHAR(TO_NUMBER(inn)+a+b));
Рассмотрим некоторые особенности при инициализации переменных:
declare
age integer := 123; -- простоая переменная integer (подтип number)
price number(4,2) := 12.34; -- number с плавающей точкой (максимум 4 знака и 2 после запятой).
inn constant number := 12345; -- константа, в данном случае типа number
name varchar2(255) := 'Sarah'; -- строковая переменная, может принимать NULL
address varchar2(255) not null := 'Moscow'; -- строковая переменная, с проверкой на NULL
country varchar2(50) default 'Russia'; -- строковая переменная со значением по умолчанию
isOpen boolean not null := true; -- логическая переменная
begin
DBMS_OUTPUT.put_line(TO_CHAR(price)); -- 12,34
DBMS_OUTPUT.put_line(TO_CHAR(age)); -- 123
DBMS_OUTPUT.put_line(TO_CHAR(inn)); -- 12345
DBMS_OUTPUT.put_line(name); -- Sarah
DBMS_OUTPUT.put_line(address); -- Moscow
DBMS_OUTPUT.put_line(country); -- Russia
-- переменную типа boolean нельзя вывести в консоли
end;
/
Также для переменных в PL/SQL можно устанавливать тип поля таблицы.
Например, у нас есть таблица Developer
, которая содержит поле name varchar2(15)
.
Мы хотим использовать значения этого поля в теле функции, для этого мы должны создать переменную, такого же типа, что и поле.
declare
d_name varchar2(15);
begin
select name into d_name from developer where name = 'Sarah';
dbms_output.put_line(d_name); -- Sarah
end;
/
Но! если тип поля name
в исходной таблице изменится, например станет name varchar(50)
, мы уже не сможем присваивать значения этого поля для нашей переменной d_name
, т.к. количество допустимых символов будет различаться.
В этом случае нам поможет конструкция %type
, она имеет вид variable table.field%type
.
Применим ее для нашего скрипта:
declare
d_name developer.name%type;
begin
select name into d_name from developer where name = 'Sarah';
dbms_output.put_line(d_name); -- Sarah
end;
/
Теперь тип нашей переменной d_name
будет всегда привязан к типу поля name
.
В PS/SQL можно создавать подтипы, то есть типы, основанные на других. Такие типы, например, как integer и decimal основаны на типе number.
Определение подтипа имеет вид subtype new_type is type
.
Рассмотрим это на примере:
declare
subtype name_type is developer.name%type; -- создали новый тип name_type на основе типа name
d_name name_type(15); -- создали переменную на основе нового типа и ограничили количество допустимых символов
begin
select name into d_name from developer where name = 'Sarah';
dbms_output.put_line(TO_CHAR(d_name));
end;
/
Стоит заметить, что при создании подтипа - нельзя ограничивать масштаб, точность или диапазон значений. Но это можно делать потом, при создании переменных, как показано в примере выше.
Рассмотрим условные операторы if-then-else
.
Они имеют общий вид:
if(condition) then -- первое условие
elsif(condition) then -- второе условие
else -- ни одной из условий не выполнилось
end if; -- конец условного оператора
При втором и последующем условии используется стандартный оператор elsif
, не путать с elseif
.
Рассмотрим на примере и реализуем простейший калькулятор:
declare
a integer := 5;
b integer := 5;
operation varchar2(1) := '+';
begin
if(operation = '+') then
dbms_output.put_line('Result is '||TO_CHAR(a+b)); -- Result is 10
elsif (operation = '-') then
dbms_output.put_line('Result is '||TO_CHAR(a-b)); -- Result is 0
else
dbms_output.put_line('Требуемой операции не найдено');
end if;
end;
/
Операция с числами в данном случае получается "зашитой" в скрипте. Изменим инициализацию операции таким образом, что бы операцию можно было выбирать каждый раз при запуске программы. Это можно сделать с помощью использования литерала &
:
operation varchar2(1) := '&Operation';
Теперь, каждый раз при запуске программы - будет появляется окно, с просьбой инициализировать операцию (Enter value for Operation).
PL/SQL имеет три вида циклов:
- Безусловные циклы (выполняемые бесконечно);
- Интерактивные циклы (FOR);
- Условные циклы (WHILE).
Для выхода из цикла используются три оператора:
- EXIT - Безусловный выход из цикла. Можно использовать с условным оператором IF;
- EXIT WHEN - Выход при выполнении условия;
- GOTO - Выход из цикла во внешний контекст.
Для начала рассмотрим безусловный цикл:
declare
i integer := 0;
begin
loop
i := i + 1;
dbms_output.put_line(TO_CHAR(i)); -- 1 2 3 4 5
if (i >= 5) then
exit; -- используем безусловный выход из цикла
end if;
end loop;
loop
i := i + 1;
dbms_output.put_line(TO_CHAR(i)); -- 6 7 8 9 10
exit when (i >= 10); -- используем выход из цикла с условием
end loop;
end;
/
Условный цикл while
:
declare
i integer := 0;
begin
while (i < 5) loop
i := i + 1;
dbms_output.put_line(TO_CHAR(i)); -- 1 2 3 4 5
end loop;
end;
/
Интерактивный цикл for
:
declare
i integer := 0;
begin
for i in 1..5 loop
dbms_output.put_line(TO_CHAR(i)); -- 1 2 3 4 5
end loop;
end;
/
С помощью оператора reverse
, в цикле for
можно задать обратный порядок:
for i in reverse 1..5 loop
dbms_output.put_line(TO_CHAR(i)); -- 5 4 3 2 1
end loop;
Курсор - это ссылка на конкретную область памяти, в которой хранится информация о результирующем наборе оператора SELECT или другого DML оператора (INSERT, UPDATE, DELETE, MERGE).
Курсоры бывают:
- явными - запрос объявляется как явный курсор (обычно в разделе declare). После этого такой курсор можно открыть и выбирать нужные из него данные;
- неявными - команда
select .. into
считывает одну строку данных и присваивает ее в качества значения локальной переменной программы.
Основные методы работы с курсором:
- Объявить курсор -
cursor get_data is select * from table;
- Открыть курсор -
open get_data;
- Выбрать данные -
fetch get_data into variable;
- Закрыть курсор -
close get_data;
Пример:
declare
v_code developer.code%type;
cursor get_code is select code from developer; -- создаем курсор
begin
open get_code; -- открываем курсор
fetch get_code into v_code; -- инициализируем переменную данными из курсора
dbms_output.put_line(v_code);
close get_code; -- закрываем курсор
end;
/
Курсорс может содержать больее одного результата запроса, но fetch
будет возвращать только одну запись, при этом каждый вызов fetch
будет возвращать новую запись, скажем так "двигать указатель".
Что бы решить эту проблему и не вызывать множество раз fetch
- нужно использовать циклы.
Используем безусловный цикл:
declare
cursor get_developer is select * from developer; -- создаем курсор
v_developer get_developer%rowtype;
begin
open get_developer; -- открываем курсор
loop
exit when get_developer%notfound; -- проверяем курсор на наличие значений
fetch get_developer into v_developer; -- инициализируем переменную данными из курсора
dbms_output.put_line(v_developer.code||' - '||v_developer.name);
end loop;
close get_developer; -- закрываем курсор
end;
/
В этом использован атрибут %rowtype
- он позволяет хранить все типы полей конкретной таблицы в переменной.
Используем параметризированный цикл for
:
declare
cursor get_developer_for_name(d_name varchar2) is
select name from developer where name = d_name; -- создаем курсор
begin
for i in get_developer_for_name('Sarah') loop
dbms_output.put_line('Developer`s name ' ||i.name);
end loop;
end;
/
При работе с циклом for
он автоматически открывает и закрывает курсор, поэтому делать это вручную не надо.
При использовании цикла for
необязательно создвать курсор, можно сразу использовать результирующий наборselect
:
begin
for i in (select name from developer where name = 'Sarah') loop
dbms_output.put_line('Developer`s name ' ||i.name);
end loop;
end;
/
Атрибуты курсора.
Курсоры могут содержать некоторые атрибуты:
- %rowtype - применяется для типизирования переменных (рассмотрен в примере выше);
- %rowcount - возвращает число строк считанных курсором.
Возвращают логическое значение:
- %found - проверяет, может ли fetch вернуть какие-либо данные;
- %notfound - противоположная %found команда (рассмотрен в примере выше);
- %isopen - возвращает true, если курсор открыт.
Атрибуты неявного курсора.
Любой DML оператор представляет собой неявный курсор и выполняется в пределах конкретной области. Неявные курсоры не надо открывать или закрывать вручную, PL/SQL делает это автоматически.
При всем этом, для неявных курсоров все равно можно использовать атрибуты - sql%[attribute]
.
Состав атрибутов у неявных курсоров такой же, как и у явных.
Рассмотрим пример:
begin
update developer set name = 'John' where id = 141319;
if (sql%notfound) then
insert into developer (id, name) values (141319, 'John');
end if;
end;
/
В данном случае сработал оператор %notfound
, т.к. SQL-операция ничего не нашла по заданному условию, а затем произошла вставка данных (такая конструкция немного напоминает работу оператора merge
).
RECORD - составной тип данных.
Синтаксис объявления составного типа:
type [name] is record (
[field_1] [type] [not null] [:= data],
[field_2] [type] [not null] [:= data],
[field_n] [type] [not null] [:= data]
);
Рассмотрим на примере:
declare
type record_address is record ( -- составной тип
country varchar2(255) not null := 'Russia',
city varchar2(255)
);
v_address record_address; -- переменная типа record_address
begin
v_address.city := 'st. Petersburg'; -- инициализируем один из элементов составного типа
dbms_output.put_line(v_address.country||' - '||v_address.city); -- Russia - st. Petersburg
end;
/
Присваивать значения для данных типа record
можно как и при объявлении самого составного типа, так и в теле функции.
Например, присвоить значения можно также через оператор select
, сделав запрос из реальной таблицы:
declare
type record_address is record ( -- составной тип
country address.country%type,
city address.city%type
);
v_address record_address; -- переменная типа record_address
begin
select country, city
into v_address
from address where name = 'John';
end;
/
TABLE в PS/SQL - это упорядоченный набор элементов одного типа. Каждый элемент имеет уникальный порядковый номер, который определяет его позицию в упорядоченной коллекции.
Синтаксис - type [name] is table of [type] index by binary_integer;
.
Рассмотрим на примере:
declare
type table_address is table of varchar2(255) -- таблица типа varchar2
index by binary_integer;
type table_developer is table of developer%rowtype -- таблица типа developer
index by binary_integer;
v_address table_address; -- переменная типа table_address
v_developer table_developer; -- переменная типа table_developer
begin
v_address(1) := 'London'; -- задаем значение элементу с индексом 1
select * into v_developer(5) from developer where name = 'Kate'; -- задаем значение элементу с индексом 5
dbms_output.put_line(v_address(1)); -- London
dbms_output.put_line(v_developer(5).name||' - '||v_developer(5).age); -- Kate - 28
end;
/
Также table
может содержать разные атрибуты:
- count - возвращает число строк таблицы -
table.count
; - delete(n, m) - удаляет строки в таблицы -
table.delete(1)
; - exists(n) - возвращает true, если указанный элемент находится в таблице -
table.exists(1)
; - first и last - возвращает индекс первой или последний строки -
table.last
; - next(n) и prior(n) - возвращают индекс строки таблицы, которая следует или предшествует строке -
table.next(1)
.
В PL/SQL используется множество разных функций, с полным списком которых можно ознакомиться в официальной документации.
Рассмотрим основные из них:
-- функции строки
dbms_output.put_line(lower('Hello world')); -- hello world
dbms_output.put_line(upper('Hello world')); -- HELLO WORLD
dbms_output.put_line(replace('Hello world', 'world')); -- Hello
dbms_output.put_line(replace('Hello world', 'world', 'everyone')); -- Hello everyone
dbms_output.put_line(substr('Hello world', 0, 5)); -- Hello
dbms_output.put_line(length('Hello world')); -- 11
-- функции даты
dbms_output.put_line(add_months('09-02-2021', 5)); -- 09.07.21
dbms_output.put_line(last_day('29-01-2015')); -- 31.01.15
dbms_output.put_line(months_between('25-04-2015', '16-03-2015')); -- 1,2
dbms_output.put_line(next_day('29-01-2021', 'Суббота')); -- 30.01.21
dbms_output.put_line(sysdate); -- 29.01.21, возвращает текущую дату
dbms_output.put_line(to_char(sysdate, 'DD.MM.YY HH24:MI:SS')); -- 29.01.21 14:29:13
dbms_output.put_line(to_char(to_date('29.01.21', 'DD.MM.YY'), 'DD Month YYYY')); -- 29 Январь 2021
Базовая единица PL/SQL блок - является по сути анонимным и компилируется каждый раз при выполнении. Он не хранится в базе данных и не может быть вызван из другого блока (ввиду отсутствия какого-либо имени/идентификатора).
Для таких случаев используются именованные блоки - процедуры и функции. Такие блоки хранятся в БД и могут быть использованы повторно.
Синтаксиси создания процедуры - create [or replace] procedure my_procedure[(param)] as ...
Можно использовать как ключевое слово as
, так и is
- они являются синонимами.
Удаление процедуры - drop procedure my_proc;
Тело процедуры содержит собственный исполняемой код и распологается между ключевыми словами begin
и exception
(который можно опустить), после него идет закрывающий end
.
Раздел объявления переменных (аналог declare
) располагается между операторами as
или is
.
Рассмотрим пример:
create or replace procedure my_proc as -- создаем процедуру
begin
dbms_output.put_line('Hello!');
end my_proc;
/
-- вызваем процедуру
set SERVEROUTPUT ON -- разрешаем вывод в консоль
exec my_proc; -- Hello!
Данный пример показывает, что созданная процедура теперь хранится в БД и может быть вызвана любое количество раз, даже, например, в анонимном блоке:
set SERVEROUTPUT ON
begin
my_proc;
end;
/
Процедура может содержать ряд аргументов.
Рассмотрим выходной параметр:
create or replace procedure my_proc(in_name IN varchar2) as
v_code_by_name varchar(50);
begin
select code into v_code_by_name
from employees where employees .name = in_name;
dbms_output.put_line('Kate`s code: ' || v_code_by_name);
end my_proc;
/
-- вызываем процедуру
set SERVEROUTPUT ON
exec my_proc('Kate'); -- Kate`s code: 123
Ключевое слово IN
при определении параметров процедуры обозначает, что параметр является входным, т.е. значения для него должно быть установлено при вызове процедуры.
Теперь рассмотрим выходной параметр:
-- создаем процедуру
create or replace procedure my_proc(in_name IN varchar2, out_code OUT number) as
begin
select code into out_code
from employees where employees.name = in_name;
end my_proc;
/
-- вызываем процедуру в блоке pl/sql
set SERVEROUTPUT ON
declare
v_code number; -- создаем переменную
begin
my_proc('Kate', v_code); -- передаем имя и созданную переменную
dbms_output.put_line('Kate`s code: ' || v_code); -- Kate`s code: 123
end;
/
Ключевое слово OUT
при определении параметров процедуры рассматривается как параметр только для записи, это так называемый выходной тип.
Суммируя вышесказанное, IN-параметр можно только считывать, но не изменить (мы работаем только с его содержимым, т.е. передаем параметр по значению, а не по ссылке);
А в OUT-параметр мы можем только записывать, но не считывать с него (т.е. даже при передаче не-пустого параметра мы не сможем его считать и его значение просто перепишется на новое).
Существует еще и параметр IN OUT - этот тип представляет собой комбинацию видов IN и OUT. Внутри процедуры значение параметра может быть считано и в него же можем быть записано значение.
-- создаем процедуру
create or replace procedure my_proc(io_param IN OUT varchar2) as
begin
select code into io_param
from employees where employees .name = io_param;
end my_proc;
/
-- вызываем процедуру в анонимном блоке
set SERVEROUTPUT ON
declare
v_code_by_name varchar2(50); -- создаем переменную
begin
v_code_by_name := 'Kate'; -- инициализируем переменную
my_proc(v_code_by_name); -- передаем созданную и проинициализированную переменную в процедуру
dbms_output.put_line('Kate`s code: ' || v_code_by_name); -- Kate`s code: 123
end;
/
Как видно из примера, процедура с начала считала значение Kate
из переданной переменной, а потом переписала ее значение на результат запроса - 123
.
Важно отметить, что в данном случае, при передачи обычного литерала, например my_proc('Kate')
, процедура не сработала бы, т.к. литерал не хранится в памяти после использования и туда нельзя записать выходное значение.
Еще один важный момент - накладывать ограничения на параметры функций в PL/SQL запрещено.
Т.е. такой код приведет к ошибке компиляции:
create or replace procedure my_proc(io_param IN OUT varchar2(50)) as ...
Мы попытались установить ограничение в 50 симолов для строкового типа.
Но возможна еще одна ошибка:
create or replace procedure my_proc(in_param IN OUT varchar2, io_param IN OUT number) as
begin
in_param := 'abs';
io_param := 15.5;
end my_proc;
/
Когда в теле процедуры мы инициализировали параметры, для них неявно задался тип: in_param varchar2(3) и io_param number(3,1).
Теперь попробуем вызвать эту процедуру в анонимном блоке, передава ей переменные с типом varchar(1) и number(3, 2):
set SERVEROUTPUT ON
declare
v_str varchar2(1);
v_num number(3,2);
begin
my_proc(v_str, v_num);
end;
/
Мы получим ошибки, для строковой переменной это - буфер символьных строк слишком маленький ошибка числа или значения, а для числовой - точность числа слишком большая ошибка числа или значения.
Cпособом избежать таких ошибок - является использование оператора %type
, а также документирование всех налагаемых на процедуру ограничений.
create or replace procedure my_proc(in_param IN OUT employees.name%type) -- при создании процедуры
v_str employees.name%type; -- при создании переменных
Именованные аргументы позволяют изменить порядок следования параметров и вызывать их в любой последовательности.
Рассмотрим на примере:
-- создаем процедуру
create or replace procedure my_proc(
in_1 IN number,
in_2 IN varchar2,
in_3 IN number) as
begin
null;
end my_proc;
/
-- вызываем процедуру
set SERVEROUTPUT ON
declare
v_1 number;
v_2 varchar2(50);
v_3 number;
begin
my_proc(in_2 => v_2, in_1 => v_1, in_3 => v_3); -- используем именованные аргументы
end;
/
Параметры процедуры могут иметь значения по умолчанию. В это случае, значение параметру передавать необязательно. Если же параметр будет передан - он перепишет значение по умолчанию.
Пример:
create or replace procedure my_proc(
in_1 IN varchar2,
in_2 IN varchar2 default 'world!') as
begin
dbms_output.put_line(in_1 || ' ' || in_2);
end my_proc;
/
set SERVEROUTPUT ON
exec my_proc('Hello'); -- Hello world!
При вызове процедуры мы указали только один параметр.
Функция имеет похожие свойства с процедурой, но дополнительно может возвращать значения (как метод в программировании).
Синтаксиси создания функции также схож с созданием процедуры, но добавляется оператор return
.
Рассмотрим пример, создав функцию преобразования типа boolean к типу varchar2:
-- создаем функцию
create or replace function boolean_to_char(in_boolean IN boolean) return varchar2
is
out_string varchar2(5);
begin
if (in_boolean) then out_string := 'true';
elsif (not in_boolean) then out_string := 'false';
else out_string := 'null';
end if;
return(out_string);
end boolean_to_char;
/
-- вызываем функцию и передаем туда параметры
set SERVEROUTPUT ON
begin
dbms_output.put_line(boolean_to_char(TRUE)); -- true
dbms_output.put_line(boolean_to_char(FALSE)); -- false
dbms_output.put_line(boolean_to_char(NULL)); -- null
end;
/
В данном примере, при создании функции, используется два оператора return
, один показывает возвращаемый тип функции, другой же использован для непосредственного возврата значения, которое будет приведено к типу возвращаемого значения.
Триггер - наименованый блок PL/SQL (наряду с процедурой и функцией), который хранится как объект БД. Но он не может быть вызван вручную и соответствено принять какие то параметры. Данный блок срабатывает только при заранее определенных событиях, а именно до или после операций INSERT, UPDATE или DELETER.
Синтаксиси создания триггера:
create [or replace] trigger <name>
before|after -- момент времени срабатывания
insert [of column] -- определяет, какой DML оператор вызывает активацию триггера (можно указать конкретное поле)
on <table>
[for each row] -- определяет, активируется ли триггер на каждую строку или один раз до или после оператора
[where (condition)] -- ограничения
[declate] -- блок создания переменных можно опустить
begin
<body>
end <name>;
/
Рассмотрим на примере.
Для начала создадим две таблицы - developers
и developers_audit
:
create table developers (id int, name varchar2(50), age int);
create sequence DEVELOPERS_SEQ;
create table developers_audit (user_name varchar2(50), last_date date);
Теперь создадим два триггера:
триггер dev_dml_check
каждый раз, при использовании dml-операций с таблицой developers
, будет оставлять запись таблице аудита developers_audit
:
create or replace trigger dev_dml_check after
insert or delete or update on developers
begin
insert into developers_audit(user_name, last_date) values(USER, SYSDATE);
end dev_dml_check;
/
триггерdev_id_gen
каждый раз, при вставке значений в таблицу developers
, будет генерировать идентификатор записи.
create or replace trigger dev_id_gen before
insert on developers
for each row
begin
select DEVELOPERS_SEQ.nextval into :new.id from dual;
end dev_id_gen;
/
При создании строковых триггеров можно использовать специальные операторы - :old
и :new
, которые называются псевдозаписями.
Благодоря им, внутри триггера можно обращаться к обрабатываемой в данный момент времени строке.
Ниже представлена таблица, в которой продемонстрированы значения псевдозаписей в конкретный момент времени:
Активизирующий оператор | :old | :new |
---|---|---|
insert | Значение не определено - null | Значения, которые будут введены после выполнения опреатора |
update | Исходные значения, содержащиеся в строке перед обновлением | Новые значения, которые будут введены после выполнения |
delete | Исходные значения, содержащиеся в строке перед удалением | Значение не определено - null |
Рассмотрим на примере.
Создадим триггер, который будет записывать в специальную таблицу аудита старые и новые значения после обновления таблицы developers
:
-- таблица для аудита
create table developers_update_audit(last_date date, old_value varchar2(50), new_value varchar2(50));
-- создаем триггер
create or replace trigger dev_update_check after
update on developers
for each row
begin
insert into developers_update_audit(last_date, old_value, new_value) values (SYSDATE, :new.name, :old.name);
end dev_update_check;
/
Важно отметить, что при использовании псевдосимволов с оператором where
, двоеточие не ставится!
create or replace trigger dev_update_check after
update on developers
for each row
where (new.age > 18)
...
В триггерах можно применять логические операторы - предикаты. При выполнении условия они возвращают true
, в противном случае - false
.
Их всего несколько:
Предикат | Условие |
---|---|
inserting | Оператор INSERT активировал триггер |
updating | Оператор UPDATE активировал триггер |
updating('column') | Оператор UPDATE, для конкретного столбца, активировал триггер |
deleting | Оператор DELETE активировал триггер |
Рассмотрим на примере:
create or replace trigger dev_trigger before
insert OR
update OF age, name OR
delete
on developers
begin
case
when inserting then
dbms_output.put_line('inserting');
when updating('name') then
dbms_output.put_line('updating name');
when updating('age') then
dbms_output.put_line('updating age');
when deleting then
dbms_output.put_line('deleting');
end case;
end;
/
Теперь, при dml-операциях с таблицей developers
, на консоль будут выводиться соответствующие записи.
insert into test_developers (name, age) values ('Kate', 24); -- inserting
update test_developers set age = 25 where name = 'Kate'; -- updating age
delete from test_developers where name = 'Kate'; -- deleting