博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
oracle自关联表的子删父变功能实现
阅读量:5101 次
发布时间:2019-06-13

本文共 3089 字,大约阅读时间需要 10 分钟。

--需求

  一张自关联的父子表,实现删除子记录时判断父记录下是否还有子记录,如果没有子记录,则更新父记录。
--建表
create table test_sj (id number(8) not null,p_id number(8),remark varchar2(200));
alter table test_sj add constraint PK_test_sj primary key (id);
alter table test_sj add constraint FK_test_sj foreign key (p_id) references test_sj (id);
--插数据
truncate table test_sj;
insert into test_sj values (0,null,'0');
insert into test_sj values (1,0,'0');
insert into test_sj values (2,0,'0');
insert into test_sj values (11,1,'1');
insert into test_sj values (12,1,'1');
insert into test_sj values (21,2,'2');
commit;
--触发器
create or replace trigger tri_test_sj_ad after delete on test_sj for each row
declare
  -- 定义变量
pragma autonomous_transaction;
l_cnt number;
begin
    select count(id) into l_cnt from test_sj where p_id=:old.p_id and id <> :old.id;
    if l_cnt=0 then
      update test_sj set remark='你没有儿子了' where id=:old.p_id;
      commit;
    end if;
    raise_application_error(-20001,'你来了吗?'||l_cnt);
end tri_test_sj_ad;
/
show err;
alter trigger tri_test_sj_ad disable;

create or replace trigger tri_test_sj_bd before delete on test_sj for each row

declare
  -- 定义变量
pragma autonomous_transaction;        --设为自治事务,从而避免ORA-14552(无法在一个查询或DML中执行DDL、COMMIT、ROLLBACK)、ORA-14551(无法在一个查询中执行DML操作)等错误
l_cnt number;
begin
    select count(id) into l_cnt from test_sj where p_id=:old.p_id and id <> :old.id;
    if l_cnt=0 then
      update test_sj set remark='你没有儿子了' where id=:old.p_id;
      commit;
    end if;
--    raise_application_error(-20001,'你来了吗?'||l_cnt);
end tri_test_sj_bd;
/
show err;
alter trigger tri_test_sj_bd disable;

--触发条件

delete from test_sj where id in (11);     -- 一次删除父的部分子时正常
delete from test_sj where id in (11,12);  -- 一次删除父的所有子时存在问题,问题在于:行级触发器每次只能传进一行记录,判断时总有一行处于“存在状态”,可以用语句级触发器试试,或者在应用程序里写个循环,为每层循环开启一个事务。
delete from test_sj where id in (21);     -- 一次删除父的唯一子时正常
--查询
select * from test_sj;

--语句级触发器

1.用包头来定义数据结构
CREATE OR REPLACE Package Pkg_test_sj_ids
As
 type p_ids is table of test_sj.id%type index by binary_integer;
 v_ids  p_ids;
 v_pids p_ids;
 v_NumEntries binary_integer := 0;
End Pkg_test_sj_ids;
/
show err;
2.行级触发器
Create Or Replace Trigger Tri_test_sj_ad_r
 After Delete On test_sj for each row
Declare
Begin
 --[记录数据]--
  Pkg_test_sj_ids.v_NumEntries := Pkg_test_sj_ids.v_NumEntries + 1;
  Pkg_test_sj_ids.v_ids(Pkg_test_sj_ids.v_NumEntries) := :old.id;
  Pkg_test_sj_ids.v_pids(Pkg_test_sj_ids.v_NumEntries) := :old.p_id; 
End Tri_test_sj_ad_r;
/
show err;
3.语句级触发器
Create Or Replace Trigger Tri_test_sj_ad_all
 After Delete On test_sj
Declare
  l_id   test_sj.id%type;
  l_pid  test_sj.p_id%type;
  l_cnt  number;
Begin
 for v_LoopIndex in  1..Pkg_test_sj_ids.v_NumEntries loop
  --[获取变量]--
  l_id  := Pkg_test_sj_ids.v_ids(v_LoopIndex);
  l_pid := Pkg_test_sj_ids.v_pids(v_LoopIndex); 
    select count(id) into l_cnt from test_sj where p_id=l_id and id <> l_pid;
    if l_cnt=0 then
      update test_sj set remark='你没有儿子了' where id=l_pid;
--      commit;
    end if; 
  end loop;
 Pkg_test_sj_ids.v_NumEntries := 0;
End Tri_test_sj_ad_all;
/
show err;

--测试

delete from test_sj where id in (11,12);  -- ok
delete from test_sj where id in (21);     -- ok

转载于:https://www.cnblogs.com/BradMiller/archive/2011/06/04/2072639.html

你可能感兴趣的文章
(转)正则表达之零宽断言(零宽度正预测先行断言)
查看>>
spring mvc 提供的几个常用的扩展点
查看>>
Spring对字段和集合的注入---依赖注入
查看>>
Java 学习 day09
查看>>
P4345 [SHOI2015]超能粒子炮·改
查看>>
暂且解决INSTALL_FAILED_SHARED_USER_INCOMPATIBLE错误
查看>>
Java获取网络IP
查看>>
远程调试
查看>>
「日常训练」Queue(Codeforces Round 303 Div.2 D)
查看>>
There has been an error processing your request[magento1.6]
查看>>
python带cookie登录
查看>>
想念你 2012-10-24 23:27
查看>>
MVC解决Json DataGrid返回的日期格式是/Date(20130450000365)
查看>>
ojective-C学习笔记(7)Foundation框架
查看>>
CDH5.14.0 安装失败,无法接受agent发出的检测信号
查看>>
CSS Reset的相关概念及实例
查看>>
数据库
查看>>
iOS开发UI篇—UIScrollView控件实现图片缩放功能
查看>>
如何制作富文本框
查看>>
第十节:Web爬虫之数据存储与MySQL8.0数据库安装和数据插入
查看>>