oracle - Oracle 触发器在插入和更新时检查值
问题描述
我正在尝试检查是否存在相互交叉的价值差距。让我用一个快速的场景来解释一下。
建议 1:AA 公司:距离差距 -> 100 - 200
建议 2:AA 公司:距离差距 -> 200 - 300 有效
建议 3:AA 公司:距离差距 -> 250 - 450 无效
建议 4:JL 公司:距离差距 - > 250 - 450 有效
Rec 3 无效,因为它在 REC 2 的距离值之间。建议 4 有效,因为公司不同
因此我写了一个触发器来防止它。
create or replace trigger ab_redemption_billing_mpr
after insert or update on redemption_billing_mpr
for each row
declare
v_is_distance_range_valid boolean;
begin
v_is_distance_range_valid := p_redemption_billing.is_distance_range_valid(:new.id,
:new.redemption_billing_company,
:new.distance_min,
:new.distance_max,
'redemption_billing_mpr');
if not v_is_distance_range_valid then
raise_application_error(-20001, 'This is a custom error');
end if;
end ab_redemption_billing_mpr;
功能:
function is_distance_range_valid(p_id in number,
p_company in varchar2,
p_distance_min in number,
p_distance_max in number,
p_table_name in varchar2) return boolean is
d_record_number number;
begin
execute immediate 'select count(*) from ' || p_table_name || ' r
where r.redemption_billing_company = :1
and (:2 between r.distance_min and r.distance_max or :3 between r.distance_min and r.distance_max)
and r.id = nvl(:4, id)'
into d_record_number
using p_company, p_distance_min, p_distance_max, p_id;
if (d_record_number > 0) then
return false;
else
return true;
end if;
end;
is_distance_range_valid()
就像我预期的那样工作。如果它返回 false,则意味着范围检查无效并且不插入或更新。
当我创建一个场景来捕获这个异常时,oracle 给出了
ORA-04091: 表名发生变化,触发器/函数可能看不到它
select count(*)
当我单击调试按钮时,它会指向线。
我不知道为什么我会收到这个错误。提前致谢。
解决方案
只需检查以下方法是否可以解决您的问题
创建一个日志表,其中包含查找 is_distance_range_valid 验证所需的列,并在您的触发器中插入此日志选项卡。主表上的触发器必须是插入前或更新触发器
在这个日志表上创建一个触发器,并在日志表触发器中进行验证并引发错误。日志表上的触发器必须是插入或更新后触发器。
此外,这仅在该行已经存在于主表中并且它不是当前插入或更新的一部分时才有效。如果需要验证当前插入或更新,那么我们需要使用 :new.column_name 进行验证
测试:-
create table t_trg( n number);
create table t_trg_log( n number);
create or replace trigger trg_t
before insert or update on t_trg
for each row
declare
l_cnt number;
begin
insert into t_trg_log values(:new.n);
end trg_t;
create or replace trigger trg_t_log
after insert or update on t_trg_log
for each row
declare
l_cnt number;
begin
select count(1) into l_cnt from t_trg
where n=:new.n;
if l_cnt > 0 then
raise_application_error(-20001, 'This is a custom error');
end if;
end trg_t_log;
我第一次插入它不会抛出错误
insert into t_trg values(7);
1 row inserted.
第二次执行时,我收到自定义错误
insert into t_trg values(7);
Error report -
ORA-20001: This is a custom error
ORA-06512: at "TRG_T_LOG", line 7
ORA-04088: error during execution of trigger 'TRG_T_LOG'
ORA-06512: at "TRG_T", line 4
ORA-04088: error during execution of trigger 'TRG_T'
更新:-使用复合触发器,在第一次完成插入时抛出错误,因为它还考虑了我们在执行 SELECT 时正在更新或插入的当前行
推荐阅读
- javascript - 用 HTML 编写标签并打印
- kubernetes - 在 kubespray 上运行带有标签的 playbook 时出错
- laravel - Laravel 在 Docker 容器中无法连接到数据库
- r - 根据R中的范围值合并两个数据框
- angular - Angular 中的 Google 表格 API
- botframework - 无法从 BotFramework 迁移新机器人
- javascript - 如何添加与光线投射的碰撞?
- python - 从元组中的字典创建数据框
- jenkins - 如何使用评论重新触发 Jenkins 多分支管道中的 GitHub PR 构建?
- reactjs - 使用 useSelector 和 useDispatch 优化 react-redux 存储