如何编写一个程序,表明一个字段的值不能高于另一个字段的值,就数字而言。说。员工的工资不能高于经理的工资。
之前我从未做过一次答案 0 :(得分:2)
在SQL中没有以声明方式强制执行此类业务规则。所以必须用代码完成。有许多问题,其中最重要的是确定需要强制执行规则的所有方案。
以下是方案:
以下是使这一切变得更难的事情:
因此,出于所有这些原因,执行此类业务规则的唯一方法是使用API;构建一个存储过程,永远不要让任何进程对表进行裸DML访问。
以下chunk o'代码在更新员工薪水时强制执行规则。兴趣点包括:
使用COMMIT和ROLLBACK来释放锁。在实际的实现中,这可能会以不同的方式处理(即通过调用程序)。
创建或替换过程change_emp_sal (p.eeno在emp.empno%类型中 ,emp.sal%type中的p_new_sal) 是 type emp_nt是emp%rowtype的表; l_emp emp%rowtype; l_mgr emp%rowtype; l_subords emp_nt; l_idx pls_integer; x_mgr_not_paid_enough例外; pragma exception_init(x_mgr_not_paid_enough,-20000); x_sub_paid_too_much例外; pragma exception_init(x_sub_paid_too_much,-20001); 开始 - 锁定员工记录 select * into l_emp 来自emp 其中empno = p_eno 更新sal;
-- lock their manager's record (if they have one)
if l_emp.mgr is not null
then
select * into l_mgr
from emp
where empno = l_emp.mgr
for update;
end if;
-- lock their subordinates' records
select * bulk collect into l_subords
from emp
where mgr = p_eno
for update;
-- compare against manager's salary
if l_mgr.sal is not null
and l_mgr.sal < ( p_new_sal * 1.1 )
then
raise x_mgr_not_paid_enough;
end if;
-- compare against subordinates' salaries
for i in 1..l_subords.count()
loop
if l_subords(i).sal > ( p_new_sal * 0.9 )
then
l_idx := i;
raise x_sub_paid_too_much;
end if;
end loop;
-- no exceptions raised so we can go ahead
update emp
set sal = p_new_sal
where empno = p_eno;
-- commit to free the locks
commit;
例外 当x_mgr_not_paid_enough然后 dbms_output.put_line('错误!管理器只赚取'|| l_mgr.sal); 回滚; 提高; 当x_sub_paid_too_much然后 dbms_output.put_line('Error!subordinate earns'|| l_subords(l_idx).sal); 回滚; 提高; 结束change_emp_sal; /
以下是Deptarment 50的四名员工:
SQL> select e.empno, e.ename, e.sal, m.ename as mgr_name, m.empno as mgr_no
2 from emp e join emp m on (e.mgr = m.empno)
3 where e.deptno = 50
4 order by sal asc
5 /
EMPNO ENAME SAL MGR_NAME MGR_NO
---------- ---------- ---------- ---------- ----------
8060 VERREYNNE 2850 FEUERSTEIN 8061
8085 TRICHLER 3500 FEUERSTEIN 8061
8100 PODER 3750 FEUERSTEIN 8061
8061 FEUERSTEIN 4750 SCHNEIDER 7839
SQL>
让我们试着给比利一个大加注,这应该会失败......
SQL> exec change_emp_sal (8060, 4500)
Error! manager only earns 4750
BEGIN change_emp_sal (8060, 4500); END;
*
ERROR at line 1:
ORA-20000:
ORA-06512: at "APC.CHANGE_EMP_SAL", line 67
ORA-06512: at line 1
SQL>
好的,让我们给比利一个较小的加注,这应该成功......
SQL> exec change_emp_sal (8060, 4000)
PL/SQL procedure successfully completed.
SQL>
现在让我们试着让史蒂文大幅减薪,这应该会失败......
SQL> exec change_emp_sal (8061, 3500)
Error! subordinate earns 3500
BEGIN change_emp_sal (8061, 3500); END;
*
ERROR at line 1:
ORA-20001:
ORA-06512: at "APC.CHANGE_EMP_SAL", line 71
ORA-06512: at line 1
SQL>
所以,让我们给史蒂文一个象征性的减薪,这应该成功......
SQL> exec change_emp_sal (8061, 4500)
PL/SQL procedure successfully completed.
SQL>
这是新的薪酬结构......
SQL> select e.empno, e.ename, e.sal, m.ename as mgr_name, m.empno as mgr_no
2 from emp e join emp m on (e.mgr = m.empno)
3 where e.deptno = 50
4 order by sal asc
5 /
EMPNO ENAME SAL MGR_NAME MGR_NO
---------- ---------- ---------- ---------- ----------
8085 TRICHLER 3500 FEUERSTEIN 8061
8100 PODER 3750 FEUERSTEIN 8061
8060 VERREYNNE 4000 FEUERSTEIN 8061
8061 FEUERSTEIN 4500 SCHNEIDER 7839
SQL>
所以它的确有效。它只处理五个场景中的两个。重构代码以满足其他三个代码留给读者练习。