Oracle 02 事务

阅读: 评论:0

Oracle 02 事务

Oracle 02 事务

事务 作为单个逻辑工作单元执行的一系列操作  四大特性 ACID

文章目录


前言

Atomicity 原子性:要么都成功,要么都失败  || 两个人转账要么都成功要么都失败                Consistency 一致性:事务执行前后总量保持一致 ||两个人转账 钱的总额不变                    Isolation隔离性 各个事务并发执行独立                                                                                Durability 持久性    持久化操作,不可变 数据库重启不改变事务结果

 事务的生命周期:MySQL是自动提交(自动执行commit),oracle是手工提交

再oracle中,事务的开始的标识 就是第一条DML(增删改)语句,

结束的标识 :正常结束(commit显示提交;执行 exit;DDL自动执行commit,即 隐式提交)                                  回滚(显示rollback ; 隐式:宕机或断电)

保存点 savepoint:

     可以有多个savepoint ,保存点可以防止rollback后不会回滚所有的结果,语法为  savepoint  保存点的名字(保存点的定义)    rollback to savepoint  保存点的名字 (保存点的应用)   

事务的隔离级别:解决并发问题(脏读 不可重复读 幻读):隔离级别SQL99标准4种

读未提交  读已提交  可重复读  序列化  ;oracle只支持两种

 切换隔离级别使用  set transaction isolation level Serializable ;(必须在事务第一行执行),一般使用默认的隔离级别。 对于MySQL则是4种都支持。


declare 定义常量 变量 游标  例外(异常)  ;代码写在begin ..... end ;  中间

一、plsql新建

  begindbms_output.put_line('hello word ! ');end; 

显示

二、基础使用语法

不在职员工数(status > 3  ): 14613 ;   在职员工数(status < 3) :  19037;

考试成绩表中:

数据条数 21827 ;(一个人有多个科目要考,暂未删除离职人员考试成绩)

考试成绩表中 存在问题:

              0.已离职的人员考试成绩也存储在成绩表中

              1.录入考试信息时个别人员工号和姓名没有核对,导致h表中的workcode和c表中的工号(gh)相同,但是h表中的

               

                3. 在职人员工作调动到新部门,成绩表的 单位 仍然是之前的 部门,没有变动

1.解决 工号和姓名不匹配的问题

先将离职人员的信息筛选出来,在考试成绩表(uf_czlj1 c)中的备注(bz1)leavePerson

找到人力资源表(hrmresource  h),根据表中的  和  字段对照考试成绩表中的姓名工号,将考试成绩表中异常的信息(- 工号(h.workcode=c.gh)校验和姓名&#!))筛选出来


  select subcompanyid1 from hrmresource  where id = 28519
  
  select subcompanyid1 from hrmresource  where loginid= '20151926'
  
   
 select * from  hrmresource  where workcode= '20180823' OR workcode= '20181134'
 select *  from  hrmresource where LOGINID is null --not null 筛选 离职/在职 人员
  select count(*) from  hrmresource where LOGINID is null
 --  where workcode= '20180823' OR workcode= '20181134'
 select * from  uf_czlj1 where gh = '20181134' -- 成长路径考试
 
 
 update uf_czlj1  t1 set t1.dw = 11248    where gh = '20180950'           --  11248
  commit;
  select *  from uf_czlj1 t1 where t1.gh = hrmresource.loginid
  update uf_czlj1  t1 set t1.dw = (select subcompanyid1 from hrmresuorce where uf_czlj1.gh = hrmresource.loginid)   where uf_czlj1.gh = '20151926'  ;         --  subcompanyid1 11248
  commit;
  
  --(select subcompanyid1 from hrmresuorce where uf_czlj1.gh = hrmresource.loginid)  where  uf_czlj1.gh = hrmresource.loginid
   update uf_czlj1  
    set uf_czlj1.dw = (select subcompanyid1,gh,loginid from (select *  from uf_czlj1 c, hrmresource h ) zuhe where  zuhe.gh = '20151926' and   ) 
   --from (select *  from uf_czlj1 , hrmresource ) ch
   where uf_czlj1.gh = '20151926' ;
     commit;  
     
     --新建视图 将考试成绩表与人力资源信息表连接为一个视图,包含考试成绩表的 工号(gh)和人力资源信息表的 loginid , subcompanyid1 , 条件为subcompanyid1 = gh
     select *  from  hrmresource, uf_czlj1 where uf_czlj1.gh = hrmresource.loginid and hrmresource.loginid = '20151926'
     select * from  uf_czlj1 where uf_czlj1.gh = '20171527'  --loginid,subcompanyid1
    --根据传入的工号 自动更新  uf_czlj1.dw 单位
    update uf_czlj1  
      set  uf_czlj1.dw =
      (select  subcompanyid1  from  hrmresource, uf_czlj1 where uf_czlj1.gh = hrmresource.loginid and hrmresource.loginid = '20180948' and rownum = 1   )  
       where uf_czlj1.gh = '20180948'  ;
          commit;  
          
        declare --定义先名字 后类型  := 进行赋值
            psex  varchar2(5) := 'boy' ;
            pname hrmresource.lastname%type ; --使用引用类型使变量随表字段变化
       begin
            select lastname into pname from  hrmresource where loginid = '20180823';
             
            dbms_output.put_line(pname||'- -'||psex);
       end;   
          
       --记录型变量(相当于Java中的类) 将一整行 保存到一个 记录型变量中
      
       declare --定义先名字 后类型  
          kscj_infor uf_czlj1%rowtype ;
       begin
             select * into kscj_infor from  uf_czlj1 where uf_czlj1.id = '83812';
            dbms_output.put_line(kscj_infor.gh||'*******'||);
       end; 
       
       --if 语法 条件直接写 不写括号 成功执行 then 否则 else(elsif) 结尾用 end if;
       declare 
         pnum number :=1 ;
        begin
          if pnum=1 then  dbms_output.put_line('00001');
          elsif pnum=2 then dbms_output.put_line('00002');
          else dbms_output.put_line('00003');
          end if ;
        end;
       
       --循环结构
       --while for
       --1.while : 条件  loop ... end loop;
       --while :   loop ... end loop 
       --3.for : for i in 1..10  loop  end loop;
       begin 
         for x in 1..5
           loop
             dbms_output.put_line('0000 '||x);
           end loop;
       end;
       
       --while 计算 1 - 5 之和
       declare
        pnum number :=1;
        psum number :=0;
       
         begin 
           loop
             exit when pnum > 5 ; 
              psum:=psum+pnum ;
              pnum:=1+pnum ;
           end loop;
           dbms_output.put_line('sum is  '||psum);
       end;
       
       --游标 cursor 相当于Java中的集合  游标的4个属性 %isopen  %rowcount  %found  %notfound
       --定义 : cursor 光标名(参数列表)// is //select ....
       --打印全部姓名,工号  select xm,gh from  uf_czlj1
        declare 
          cursor cksxx is  select xm,gh from  uf_czlj1 where xm<1000;
          pxm %type ;
          pgh uf_czlj1.gh%type ;
       begin
         --打开光标
         open cksxx;
         --循环取出光标元素信息
         loop
           fetch cksxx into pxm ,pgh ; --fetch获取当前行游标元素,之后移动下一行
           exit when cksxx%notfound ;
           dbms_output.put_line(pxm||'<-----姓名-工号--->'||pgh);
         end loop;
         --关闭光标
         close cksxx;
       end;
       
      --删除 考试成绩表 uf_czlj1 中 离职人员的信息 
      --筛选出hrmresource表单中在职人员   --select *  from  hrmresource where LOGINID is not null
      --将 hrmresource 表中的 工号(workcode),字段存到游标中  
      
       --   获取 2020年以来离职的人员 工号
      select  *  from  hrmresource where status > 3 and  lastlogindate > '2021-01-01'  --count(*)
       -- 查询工号20181134是否存在
       select count(*) from uf_czlj1 where gh= '20180962'
     -- 存在,则删除 uf_czlj1 数据
    delete from uf_czlj1 where gh= '20180962';
    commit;
    
    
     declare 
          cursor chrm_workcode  is   select workcode from  hrmresource where status > 3 and  lastlogindate > '2021-01-01';
          pworkcode hrmresource.workcode%type ;
          pgh uf_czlj1.gh%type ;
          pcount integer ;
       begin
         --打开光标
         open cksxx;
         --循环取出光标元素信息
         loop
           fetch cksxx into pxm ,pgh ; --fetch获取当前行游标元素,之后移动下一行
           exit when cksxx%notfound ;
           dbms_output.put_line(pxm||'<-----姓名-工号--->'||pgh);
         end loop;
         --关闭光标
         close cksxx;
       end;
 

0.由于开始时姓名是浏览类型,导致重名的人员姓名信息错误的写入到了考试成绩表中,导致点击姓名(浏览类型字段)后弹出的人员信息不是本人。现在在表中新增加一个文本类型的姓名(xmwb)字段,通过表中的 工号(gh)查询 h表中的workcode对应的姓名(lastname),写入该文本姓名字段中

1.首先将离职的人员标注出来(c.bz1= leaveOffice)

declare cursor c_czljks  is select distinct gh from uf_czlj1 ; --5410p_c_gh uf_czlj1.gh%type ; --创建h表中的 status 游标,当输入c表的工号则查询h的status ,status > 3 ,说明此人离职,set c.bz1 = 'leaveOffice' 更新cursor c_hrm(cs_code uf_czlj1.gh%type) is select status from hrmresource h where h.workcode= cs_code  ;p_h_status hrmresource.status%type ; begin --打开游标 c_czljks   1.1open c_czljks  ;--循环 c_czljks      1.2loop--游标设置 c_czljks  1.3fetch c_czljks  into p_c_gh ;exit when  c_czljks%notfound ;--打开游标 c_hrm  2.1open c_hrm(p_c_gh)  ;--将c 表中的工号输入到 游标2 中--循环  c_hrm  2.2loop--游标设置 c_hrm 2.3fetch c_hrm  into p_h_status ;exit when  c_hrm%notfound ;--开始判断  if p_h_status > 3 then update uf_czlj1 c set c.bz1 = 'leaveOffice' where c.gh = p_c_gh ;commit ;else commit ;end if ;--关闭循环 c_hrm 2.4end loop ;--关闭光标 c_hrm  2.5close c_hrm ;--关闭循环 c_czljks  1.4end loop ;--关闭光标 c_czljks  1.5close c_czljks ;end;select count(*) from uf_czlj1 c where c.bz1 = 'leaveOffice' ; --3912

2.对照c表中的 xm 和 xmwb 字段,两个字段值不相同,就标注出来(bz1= erroName)

由于开始时姓名是浏览类型,导致重名的人员姓名信息错误的写入到了考试成绩表中,由于c表中的xm与h表中的id相对应 ,导致点击姓名(浏览类型字段)后弹出的人员信息不是本人。现在在表中新增加一个文本类型的姓名(xmwb)字段,通过表中的 工号(gh)查询 h表中的workcode对应的姓名(lastname),写入该文本姓名字段中

编写核心执行的SQL语句,即 如何将 工号(c.gh)对应的姓名(h.lastname)更新到c.xmwb

查找 c表中的一条数据用于测试(该工号(gh)对应的姓名为重名的其他人)

 -- 测试查询一条重名的数据 c表中的姓名对应h表的 id 为 29823select   *  from uf_czlj1 c where c.gh = '20171527' and c.id = '83527'  ;--查找这条数据在h表中对应的lastname id 实际为 26579select *from hrmresource h where workcode = '20171527';--更新c表中 id = '83527'  的 xmwb 将lastname(对应 gh为 '20171527' )写入该字段update uf_czlj1 c wb = (select  lastname from hrmresource h where h.workcode = '20171527' ) where c.id ='83527';commit ;--更新一条c表的数据( id = '83527')update uf_czlj1 c  = (select id from hrmresource h where h.workcode = '20171527' ) where c.id = '83527' ;commit ;--处理标记该条数据&# != h.id , ),将其备注(bz1)标记为 erroName-workcode(gh='20171527' 在c 表中有4条,一条是已处理正确的xm,3条不是)update uf_czlj1 c set c.bz1 = 'erroName-workcode' where  xm != (select id from hrmresource h where h.workcode = '20171527' ) ; commit ;

可以看到,测试案例中工号为 20171527 的员工xm字段有异常的都在bz1的字段中有被标注为 erroName-workcode 。

有了以上的测试SQL ,现在尝试更新整张c表,j将 c 表中的工号筛选出来存储到游标中,判断如果之后再对照c表中的 xm 和 xmwb 字段,两个字段值不同,就标注出来(bz1= haveSameName)  代码:

 --将c表中的工号存入 游标 c_czljks_code 中,之后循环遍历 工号游标,当h表中的id对应workcode 与 c表的gh 相同--但是 c表的xm与h表中的id 不同,说明c表中的xm是重名,则 c表 bz1='erroName-workcode' declare cursor c_czljks  is select distinct gh,xm from uf_czlj1 ;p_c_gh uf_czlj1.gh%type ;p_c_xm %type ;begin --打开游标open c_czljks  ;--循环loop--游标设置fetch c_czljks  into p_c_gh ,p_c_xm ;exit when  c_czljks%notfound ;-- 判断 p_gh(c.gh)对应的c.xm 与 筛选出来的h.id (select id from hrmresource h where h.workcode = p_gh)--如果 c.xm != h.id then c.bz1 = 'haveSameName ' if p_c_xm != (select id from hrmresource h where h.workcode= p_c_gh) thenupdate uf_czlj1 c set c.bz1 = 'haveSameName' where c.gh = p_c_gh; commit ;else commit ;end if ;--关闭循环end loop ;--关闭光标close c_czljks ;end;

报错

使用两个游标,简化if条件

declare cursor c_czljks  is select distinct gh,xm from uf_czlj1 ;p_c_gh uf_czlj1.gh%type ;p_c_xm %type ;--创建h表中的id游标,当输入c表的工号则查询h的id ,与对应c表的xm对比 用于判断c中的数据 是否重名cursor c_hrm(cs_code uf_czlj1.gh%type) is select id from hrmresource h where h.workcode= cs_code  ;p_h_id hrmresource.id%type ;begin --打开游标 c_czljks   1.1open c_czljks  ;--循环 c_czljks      1.2loop--游标设置 c_czljks  1.3fetch c_czljks  into p_c_gh ,p_c_xm ;exit when  c_czljks%notfound ;--打开游标 c_hrm  2.1open c_hrm(p_c_gh)  ;--将c 表中的工号输入到 游标2 中--循环  c_hrm  2.2loop--游标设置 c_hrm 2.3fetch c_hrm  into p_h_id ;exit when  c_hrm%notfound ;--开始判断 h.id != c.xm (h.workcode = c.gh 获取 c.id)if p_h_id != p_c_xm then update uf_czlj1 c set c.bz1 = 'haveSameName' where c.gh = p_c_gh  = p_c_xm ;commit ;else commit ; end if ;--关闭循环 c_hrm 2.4end loop ;--关闭光标 c_hrm  2.5close c_hrm ;--关闭循环 c_czljks  1.4end loop ;--关闭光标 c_czljks  1.5close c_czljks ;end;

效果如下(更新了4001条数据)

 3.以上是根据工号校验姓名(默认工号是正确的)但是出现姓名正确但是工号不对,即一个正确的姓名在c表中有好几个工号对应,相应的就需要根据姓名(xm)来校验工号(gh)。

但是我们要注意到,既然存在之前的按工号校验姓名,现在又需要根据姓名校验工号,两个校验方式不论哪个在前面,都不能保证最后的结果是准确的。如果也安装2.的方式来进行,那么就会有覆盖2.中正确的标记。 因此,需要引入一个新的参考用以圈定一个范围,确认出  一个姓名有多个工号相对应。

在2.中可知 c.xm对应的h.id ,因为 c表中有多个姓名,即使在2中校验xm是重名的,但是c.xm的值是一致的,因此,即使姓名是错误的重名,也可以筛选出C表中 一个姓名对应多个工号的数据。


前提: 先将c表中的xm对应在h表中的lastname(姓名)更新写入到c表的xmwb中;之后将c.bz1的值为  SameName 的数据中 xm字段按照c.gh = h.workcode 获取的h.id更新c.xm 。


但是由于姓名异常的也存在 因此需要进行筛选

编写核心执行的SQL语句,即 如何

3.之后寻找 xm对应的 workcode 与gh不同

4. 更新c表中的单位

2.读入数据

代码如下(示例):

declare cursor chrm_workcode  is select workcode from hrmresource h  where exists ( select 1 from uf_czlj1 c where c.gh= h.workcode and h.status > 3 and  lastlogindate > '2020-06-01');pworkcode hrmresource.workcode%type ;pxm %type ;pcount integer ;begin--打开光标open chrm_workcode;--循环取出光标元素信息loopfetch chrm_workcode into pworkcode ; --fetch获取当前行游标元素,之后移动下一行exit when chrm_workcode%notfound ;--select   from uf_czlj1 where uf_czlj1.gh = pworkcode  ;update uf_czlj1 set uf_czlj1.bz1 = 'leavePerson' where uf_czlj1.gh = pworkcode  ;commit;dbms_output.put_line( '<---工号->'||pworkcode );end loop;--关闭光标close chrm_workcode;end;select * from uf_czlj1 where uf_czlj1.gh = '20160059'select subcompanyid1 ,workcode ,lastname   from hrmresource where workcode = '20180948'select count(*)  from uf_czlj1 where uf_czlj1.bz1 = 'leavePerson'

 


总结

 

本文发布于:2024-02-04 07:19:40,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170701936353515.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:BUU刷题Day4
标签:事务   Oracle
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23