使用 Oracle 中的过程强制执行业务规则
如何编写一个过程来显示一个字段的值不能高于另一个字段的值(就数字而言)。说。员工的工资不能高于经理的工资。我以前从未做过
How do you write a procedure which shows that one field's value cannot be higher than another field's value, in terms of numbers. Say. an employee'a salary can't be higher than his manager's salary. I've never done one before
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在 SQL 中没有声明性的方式来强制执行这样的业务规则。所以必须用代码来完成。有很多问题,其中最重要的是确定需要执行规则的所有场景。
以下是场景:
以下是让这一切变得更加困难的事情:
因此,出于所有这些原因,执行此类业务规则的唯一方法是使用 API;构建一个存储过程,并且永远不要让任何进程对表进行裸 DML 访问。
以下代码块仅在更新员工的工资时强制执行该规则。有趣的地方包括:
使用COMMIT和ROLLBACK来释放锁。在实际的实现中,这可能会以不同的方式处理(即通过调用程序)。
创建或替换过程change_emp_sal
( emp.empno%type 中的 p_eno
, emp.sal%type 中的 p_new_sal )
是
type emp_nt 是 emp%rowtype 的表;
l_emp emp%行类型;
l_mgr emp%行类型;
l_subords emp_nt;
l_idx pls_整数;
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);
开始
-- 锁定员工记录
选择*进入l_emp
来自雇员
其中 empno = p_eno
用于更新萨尔;
异常
当 x_mgr_not_paid_enough 时
dbms_output.put_line('错误!经理只赚'||l_mgr.sal);
回滚;
增加;
当 x_sub_paid_too_much 时
dbms_output.put_line('错误!下级赚'||l_subords(l_idx).sal);
回滚;
增加;
结束change_emp_sal;
//
这是 50 部门的四名员工:
让我们尝试给比利大幅加薪,这应该会失败...
好吧,让我们给比利小幅加薪,这应该会成功...
现在让我们尝试给史蒂文大幅减薪,这应该会失败...
所以让我们给史蒂文一个象征性的减薪,这应该会成功...
这是新的薪酬结构...
所以它是有效的,就目前而言。它仅处理五种情况中的两种。重构代码以满足其他三个要求作为读者的练习。
There is no declarative way to enforce business rules like this in SQL. So it has to be done with code. There are a number of gotchas, not the least of which is identifying all the scenarios where the rule needs to be enforced..
Here are the scenarios:
Here are the things which make all this harder:
So, for all those reasons, the only way to enforce such business rules is to use an API; build a stored procedure and never let any process have naked DML access to the table.
The following chunk o' code enforces the rule just when updating an employee's salary. Points of interest include:
the use of COMMIT and ROLLBACK to release the locks. In a real implementation this might be handled differently (i.e. by the calling program).
create or replace procedure change_emp_sal
( p_eno in emp.empno%type
, p_new_sal in emp.sal%type )
is
type emp_nt is table of emp%rowtype;
l_emp emp%rowtype;
l_mgr emp%rowtype;
l_subords emp_nt;
l_idx pls_integer;
x_mgr_not_paid_enough exception;
pragma exception_init(x_mgr_not_paid_enough, -20000);
x_sub_paid_too_much exception;
pragma exception_init(x_sub_paid_too_much, -20001);
begin
-- lock the employee record
select * into l_emp
from emp
where empno = p_eno
for update of sal;
exception
when x_mgr_not_paid_enough then
dbms_output.put_line ('Error! manager only earns '||l_mgr.sal);
rollback;
raise;
when x_sub_paid_too_much then
dbms_output.put_line ('Error! subordinate earns '||l_subords(l_idx).sal);
rollback;
raise;
end change_emp_sal;
/
Here are the four employees of Deptarment 50:
Let's try to give Billy a big raise, which should fail...
Okay, let's give Billy a smaller raise, which should succeed...
Now let's try to give Steven a swingeing pay cut, which should fail...
So let's give Steven a token pay cut, which should succeed ...
Here is the new pay structure...
So it works, as far as it goes. It only handles two of the five scenarios. Refactoring the code to satisfy the other three is left as an exercise for the reader.