Oracle游标和触发器


---------------------------------------------------游标-------------------------------------------------------------

/*
   1.游标分为:
       1.显示游标(用于处理select语句返回的多行数据)
       2.隐含游标(用户处理select...into 和 dml语句)
       
   2.创建游标(分为4步)
       1.定义游标:cursor 游标名 is select语句
       2.打开游标:open 游标名;
       3.提取数据:fetch 游标名 into 接收游标数据变量1,接收游标数据变量2,.。。。;
                   或者
                   fetch 游标名 bulk collect into 接收游标结果的集合变量1,接收游标结果的集合变量2,.。。
       4.关闭游标 
*/

 --游标
    --用游标循环打印部门编号为10的人员信息编号和名称
    declare
    cursor cursor_emp is select * from emp where deptno=10;
    --声明一个变量用来接收游标取出的数据
      t_emprow emp%rowtype;
    begin
      --打开游标
      open cursor_emp;
      loop
        --取出游标的数据,放入行变量中
        fetch cursor_emp into t_emprow;
        --当游标取不到数据的时候,退出循环
        exit when cursor_emp%notfound;
        --打印
        dbms_output.put_line('员工编号'||t_emprow.empno||'员工姓名'||t_emprow.ename);
       end loop;
        --关闭游标
        close cursor_emp;
    end;
        
        --用table结构提取游标的数据(循环打印dept表里的数据)
        declare
        --定义一个table数据类型
        type table_dept is table of dept%rowtype index by binary_integer;
        --声明一个table类型具体变量
        t_dept table_dept;
        --声明游标
        cursor cursor_dept is select * from dept;
        begin
          --打开游标
          open cursor_dept;
          --取出游标的数据
          fetch cursor_dept bulk collect into t_dept;
          --关闭游标
          close cursor_dept;
          for i in t_dept.first..t_dept.last loop
            dbms_output.put_line('部门名称'||t_dept(i).dname||'位置是:'||t_dept(i).loc);
          end loop;
          end;
            
            --打印指定部门编号的人员信息
            select * from emp
            
       declare
         --声明一个游标
         cursor cursor_emp(v_deptno number)
         is select * from emp where deptno=v_deptno;
         t_emprow emp%rowtype;
       begin
              --打开游标
          open cursor_emp(&deptno);
           loop
            fetch cursor_emp into t_emprow;
             exit when cursor_emp%notfound;
             dbms_output.put_line('员工姓名'||t_emprow.ename||'雇佣日期'||to_char(t_emprow.hiredate,'yyyy-mm-dd'));
           end loop;
          close cursor_emp;
        end;
               
            --游标for循环
     declare
      cursor cursor_dept is select * from dept;
     begin
      for i in cursor_dept loop
        dbms_output.put_line(i.dname||'===='||i.loc);
      end loop;
     end;
     
     
     --游标for循环查询emp表前五条记录
declare
  cursor emp_cursor is select * from emp;
  type my_table_type is table of emp_cursor%rowtype index by binary_integer;
  my_table  my_table_type;
  i number;
begin
  open emp_cursor;
   for i in 1..5 loop 
     fetch emp_cursor into my_table(i);
   end loop;
  close emp_cursor;
  for i in 1..5 loop
  dbms_output.put_line(my_table(i).empno||'  '||my_table(i).ename||'  '||my_table(i).job||'  '||my_table(i).mgr||'  '||my_table(i).hiredate||'  '||my_table(i).sal||'  '||my_table(i).comm||'  '||my_table(i).deptno);
  end loop;
end;


--------------------------------------------------触发器---------------------------------------------------------------

--语句级的触发器

--周一或周五不能修改emp表
create or replace trigger tri_emp
--before/after 事件发生前或后触发
before update on emp  --不能修改,如果是增删改用or隔开就好(befor update or delete or insert on emp)
begin
  if to_char(sysdate,'day') in ('星期一','星期日')then
   raise_application_error(-20001,'星期一或日不能修改enp表');
  end if;
end;

update emp set ename='ALLEN' where empno=7499;
  
select *from emp

--失效触发器
alter trigger tri_emp disable;
--启用触发器
alter trigger tri_emp enable;
--删除触发器
drop trigger tri_emp

--不能增删改
create or replace trigger tri_emp1
before update or delete or insert on emp
begin 
  if to_char(sysdate,'day') in ('星期日') then
  if updating then
  raise_application_error(-20001,'星期日不能修改enp表');
  elsif deleting then
  raise_application_error(-20001,'星期日不能删除enp表');
  else
  raise_application_error(-20001,'星期日不能添加enp表');
  end if;
  end if;
end;

delete from emp where empno=7499;
--失效触发器
alter trigger tri_emp1 disable;

--行级触发器

--部门为30的人工资,奖金不能降低,而且不能删除
create or replace trigger tri_emp2
  before update or delete on emp
  --for each row 相当于声明:new,:old ,没有for each orw 则不能使用
  for each row when(old.deptno=30)
begin
  if updating('sal') then
    if :new.sal<:old.sal then
      raise_application_error(-20000,'工资不能降低');
    end if;
  elsif updating('comm') then
     if :new.comm<:old.comm then
       raise_application_error(-20000,'奖金不能降低');
  end if;
  elsif deleting then
        raise_application_error(-20000,'不能删除');
  end if;
end;

update emp set sal=15000 where deptno=30;
select *from emp
delete from emp

--失效触发器
alter trigger tri_emp2 disable;

--after语句触发器(常用于,级联添加,级联删除)

--在修改dept表中deptno后,顺便把它级联人员表中部门编号更新
create or replace trigger tri_emp3
  after update on dept
  for each row
begin
  update emp set deptno=:new.deptno where deptno=:old.deptno;
end; 

update dept set deptno=60 where deptno=20

select * from dept
select * from emp
--失效触发器
alter trigger tri_emp3 disable;

--触发器调用存储过程

--删除dept表中记录,将原有的记录保存到一个回收表delDept表中

create table delDept(
  deptno number(10),
  dname varchar(200),
  loc varchar(200)
)

create or replace procedure insertDelDept(v_deptno number,v_dname varchar2,v_loc varchar2)
is
begin
  insert into deldept(deptno,dname,loc) values(v_deptno,v_dname,v_loc);
end;

create or replace trigger tri_delDept
after delete on dept
for each row
 begin
   --insert into deldept values(:old.deptno,:old.dname,:old.loc);
   insertDelDept(:old.deptno,:old.dname,:old.loc);
end;

select * from dept

delete from dept where deptno=44

select * from delDept

--系统触发器
create table loginlog(
  loguser varchar2(200),
  loginip varchar(200),
  logindate date
)
select *from loginlog

create or replace trigger logintest_tri
after logon database
begin
  insert into loginlog values(ora_login_user,ora_client_ip_address,sysdate);
end;

猜你喜欢

转载自blog.csdn.net/javaasd/article/details/105736876
今日推荐