SQL может использовать только функции в проекции: ему нужно что-то, что возвращает значение. Так что вам придется написать некоторые функции. Это плохие новости. Хорошей новостью является то, что вы можете повторно использовать все инвестиции в хранимых процедурах.
Вот процедура, которая обеспечивает соблюдение абсолютно справедливого бизнес-правила: только менеджеры могут иметь высокую зарплату.
SQL> create or replace procedure salary_rule
2 ( p_sal in emp.sal%type
3 , p_job in emp.job%type)
4 is
5 x_sal exception;
6 begin
7 if p_sal > 4999 and p_job != 'MANAGER' then
8 raise x_sal;
9 end if;
10 exception
11 when x_sal then
12 raise_application_error(-20000, 'Only managers can earn that much!');
13 end salary_rule;
14 /
Procedure created.
SQL>
Поскольку это процедура, мы не можем использовать ее в операторе SELECT; нам нужно обернуть это в функцию. Эта функция просто вызывает хранимую процедуру. Возвращает входной параметр P_SAL. Другими словами, если заработная плата действительна (согласно правилам), она будет возвращена. В противном случае функция повторно отправит исключение хранимой процедуры.
SQL> create or replace function validate_salary
2 ( p_sal in emp.sal%type
3 , p_job in emp.job%type)
4 return emp.sal%type
5 is
6 begin
7 salary_rule(p_sal, p_job);
8 return p_sal;
9 end validate_salary;
10 /
Function created.
SQL>
Функция должна возвращать значение, которое мы хотим вставить в нашу таблицу. Он не может вернуть какую-то бессмысленную фразу, вроде "зарплата в порядке". Кроме того, если мы хотим проверить два столбца, нам нужна отдельная функция для каждого, даже если между ними существует связь, и мы используем одну и ту же хранимую процедуру для проверки обоих. Хорошо использовать для ключевого слова DETERMINISTIC.
Вот тест: сантехники не могут заработать 5000 спондуликов ....
SQL> insert into emp
2 (empno
3 , ename
4 , job
5 , deptno
6 , sal )
7 select
8 emp_seq.nextval
9 , 'HALL'
10 , 'PLUMBER'
11 , 60
12 , validate_salary(5000, 'PLUMBER')
13 from dual
14 /
, validate_salary(5000, 'PLUMBER')
*
ERROR at line 12:
ORA-20000: Only managers can earn that much!
ORA-06512: at "APC.SALARY_RULE", line 12
ORA-06512: at "APC.VALIDATE_SALARY", line 7
SQL>
... но менеджеры могут (потому что они этого заслуживают):
SQL> insert into emp
2 (empno
3 , ename
4 , job
5 , deptno
6 , sal )
7 select
8 emp_seq.nextval
9 , 'HALL'
10 , 'MANAGER'
11 , 60
12 , validate_salary(5000, 'MANAGER')
13 from dual
14 /
1 row created.
SQL>
Обратите внимание, что исключение с швыркой имеет решающее значение для этой работы. Мы не можем написать какую-то странную логику IF SALARY THALID THEN INSERT в нашем операторе SQL. Таким образом, если хранимая процедура не вызывает исключение, а вместо этого возвращает какой-то странный статус ошибки, функция переноса должна будет интерпретировать вывод и выбросить собственное исключение.