欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

游标和触发器

程序员文章站 2022-06-04 08:08:54
...

游标和触发器

游标

游标:字面理解:游动的光标

pl/sql 块中:查询操作时select,执行DMl命令是,oracle会将结果缓存到一块内存中

游标:临时表(将结果集中的数据缓存在内存中)+指向该内存中的数据指针。

作用:可以单独对数据进行定位。逐行去操作数据

读数据过程分析:从数据文件(磁盘中存储)–》内存中–》显示

需求

根据每个员工的工资进行加薪

sql命令操作数据是,针对列集合进行操作,无法单独对行进行定位处理,使用游标解决

游标分类

1.显示游标:针对select命令,,返回多行结果

2.隐式游标:自动使用,执行:insert,uodate,delete,select…into命令是

游标的状态属性

%ISOPEN:布尔属性,true/false,判断游标是否打开

%FOUND:布尔属性,true/false,判断游标中是否取到数据

%BOTFOUND:布尔属性,true/false,判断游标中是否没有找到数据,没有找到ture找到false

%ROWCOUNT:整形;获取到游标中实际读取到的行数

隐式游标:sql+%属性

显示游标:名字+%属性

用作条件的一部分

显示游标

游标(cursor) :不是数据对象,无需create

基本步骤

1.声明游标

declare
    cursor 游标名(参数) is select 命令;

2.打开游标

open 游标名

将select查询得到的结果存入内存中,游标会定位到首行,准备操作

3.提取数据

提取
fetch 游标名 into 变量名1,变量名2.。。

逐行提取

执行业务操作

4.关闭游标

close 游标名称

释放内存

显示游标实例

实例1

查询员工表中,部门编号为20的信息,工资降序排列;

declare
   -- 1.声明游标
   cursor c1 is select empno,ename,sal from emp where deptno=20 order  by sal desc;
      v_no emp.empno%type;
      v_name emp.ename%type;
      v_sal emp.sal%type;
begin 
  -- 2.打开游标
  open c1;
  -- 3.提交数据
  loop
      fetch c1 into v_no,v_name,v_sal;
      exit when c1%notfound;-- 退出
        if v_sal <3000 then
          dbms_output.put_line('需要加:'||v_no||v_name||v_sal);
        else
          dbms_output.put_line(v_no||v_name||v_sal);
          end if;
        end loop;
        --4.关闭游标
        close c1;
        end;

带参数的游标

1.根据部门编号查询部门的工资信息,按工资降序排列

       declare
   -- 1.声明游标
   cursor c1(v_deptno number) is select empno,ename,sal from emp where deptno=v_deptno order by sal desc;
      v_no emp.empno%type;
      v_name emp.ename%type;
      v_sal emp.sal%type;
begin 
  -- 2.打开游标
  open c1(10);
  -- 3.提交数据
  loop
      fetch c1 into v_no,v_name,v_sal;
      exit when c1%notfound;-- 退出
        if v_sal <3000 then
          dbms_output.put_line('需要加:'||v_no||v_name||v_sal);
        else
          dbms_output.put_line(v_no||v_name||v_sal);
          end if;
        end loop;
        --4.关闭游标
        close c1;
        end;

游标类型的变量

把游标当类型来使用,声明游标类型的变量

--1.游标类型 名称 is 引用 cursor;
type cur_type is ref cursor;

--2.声明变量
--变量名 类型
cur1 cur_type;

实例

declare 
  type cur_type is ref cursor;  --声明游标类型
    cur1 cur_type; --声明变量
    v_no emp.empno%type;
    v_name emp.ename%type;
    v_sal emp.sal%type;
begin 
  -- 打开游标是执行查询命令
  open cur1 for select empno,ename,sal from emp where deptno=20 order by sal desc;
      loop
        fetch cur1 into v_no,V_name,v_sal;
        exit when cur1%notfound;
        dbms_output.put_line(v_no||v_name||v_sal);
        end loop;
        close cur1;
    end;

for循环简化游标操作

declare
   cursor c1 is select * from emp; --声明游标
begin
for 变量名(行数据)in 游标名
 for row1 in c1 loop
   dbms_output.put_line(row1.empno||row1.ename||row1.sal);
  end loop;
    end;
    
    
begin
   for row1 in (select * from emp) loop
     dbms_output.put_line(row1.empno||row1.wname||row1.sal);
     end loop;
     end;

实例

根据每个员工的工资水准进行加薪

1.8000 > 0.05

2.5000 >0.03

3.3000 >0.01

分析:

1.游标
2.获取每一个员工的工号、工资
2.逐行判断
4.更新,commit

begin
  for row1 in(select * from emp) loop
    if row1.sal>=8000 then
      --只更新当前员工的工资信息
      update emp set sal=sal*(1+0.05) where empno=row1.empno;
    elsif row1.sal>=5000 then
      update emp set sal=sal*(1+0.03) where empno=row1.empno;
    else
      update emp set sal=sal*(1+0.01) where empno=row1.empno;
      end if;
      commit;
      end loop;
      end;

隐式游标

begin 
    update emp set sal=sal+1 where empno=7396;
    --使用隐式游标:对前面执行的sql命令进行各种判断
    if SQL%FOUND then
      dbms_output.put_line('加薪成功');
    else
      dbms_output.put_line('加薪失败');
      end if;
      end;

触发器

触发器:自动执行的存储过程;当执行数据操作是(DML操作是,数据库时间(登录登出)等;会自动**触发器去执行。一种数据库对象(create)

触发器分类

1.触发DML器:执行insert,update,dete时会**触发器

2.代替触发器instead of,视图

3.数据库事件触发器:执行特定的数据库时间(登录登出

创建触发器

语法:

create or replace trigger 名字
--触发时间,在操作之前或之后触发
before | after
-- 触发事件 (操作) ;会引发(**) 触发器自动执行的操作
insert| update| delete
--触发对象,触发器依赖的数据库对象
on 表|视图【 for each row】
as
   --声明
 begin
   --业务代码:DML命令;不能是DDL,事务控制语句
   end

构成说明

触发时间:before|after在操作之前或之后触发

触发时间(操作):会引发(**)触发器支佛那个执行的操作

触发对象:触发器依赖的数据库对象

触发频率:

语句级触发器:执行insert,update,delete

行级触发器:每一行数据都会受到影响

注意事项

1.触发器中能写的:DML命令不能是DDL,数据控制语句

2.触发器中最多32k,如果业务代码多,将业务代码封装到过程中,触发器可以调用过程

DML 触发器实例

before触发器

实例:不允许在指定的入去修改某表中是数据

create or replace trigger tg_check
before update or delete
on emp
begin
    if to_char(Sysdate,'by')='星期二' then
      --raiase_application_error:引发自定义的错误,抛给客户端程序(java程序)
      --参数 1:错误号 -20000到-20999之间
      --参数2:错误信息,自定义
      --触发器,使用过程中使用
    raiase_application_error(-20001,'周二不适合修改数据');
    end if;
    end;      

行触发器:

触发器内部使用的临时表

:old:存放旧数据;执行update,delete是会用到;

update=delete+insert

:new :存放新数据;执行update,insert时会用到;update=delete+insert

实例不允许对员工进行降薪操作

分析

1.如果修改数据后的数据小于修改Ian的数据

2.修改后的数据

3.修改前的数据

create or replace trigger tg_sal
after --在操作执行后
update
on emp for each row
begin 
  if(:old.sal>:new.sal)then
  raise_application_error(-20002,'不允许降薪');
  end if ;
  end;

实例对不同的操作输出日志记录

触发器内部使用

INSERTING:判断是否执行插入操作 ; true/false

UPDATING:判断是否执行修改操作 true/false

DELETING:判断是否执行删除操作; true/false

create or replace trigger tg6
after insert or update or delete 
on emp
begin
  if INSERTING then 
    dbms_output.put_line('insert');
  elsif updating then 
    dbms_output.pit_line('修改');
    else
      dbms_output.put_line('delete');
      end if;
      end;

after触发器

实例:记录删除数据的日志

1.将删除的数据插入到日志表中

create or replace trigger tg2
after delete on emp for each row 
begin
--写过程
insert into tmp1(empno,ename) values(:old.empno,:old.ename);
end;

视图

虚拟表:查询命令

授权:

使用管理员

grant create view to scott;

创建视图

create view v11 
as 
select deptno,avg(sal) avgsal,max(sal) maxsal,min(sal) minsal 
from emp group by 
deptno;

--使用
select * from v11

替代触发器

数据库时间触发器

执行相应的数据库事件时会**的触发器(启动、加载、登录、登出)

系统事件

事件属性函数 功能
ora_client_ip_address 返回客户端的ip地址
ora_database_name 返回当前数据库名
ora_dict_obj_name 返回DDL操作所对应的数据库对象名
ora_dict_obj_owner 返回DDL操作所对应的对象的说有者名
ora_dict_obj_type 返回DDL操作对应的数据库对象的类型
ora_instance_num 返回列程号
ora_is_alter_column(column_name IN VARCHAR2) 检测特定列是否别修改
ora_is_drop_column(column_name IN VARCHAR2) 检测特定列是否被删除
ora_login_user 返回登录用户名
ora_sysevent 返回触发触发器的系统事件名

需要管理员(DBA)的权限

1用管理员登录创建实验表

2.登录触发器

3.登出触发器

-- 模拟创建了实验表
--模拟创建实验表
create table logs(
     loginname varchar2(100),--登录的用户名
     eventname varchar2(100),--事件名
     logindate date--事件
);
--logon登录事件
create or replace trigger tg_login
after logon on database
begin 
  lnser ino logs values(ora_login_user,ora_sysevent,sysdate)
  end;
  --logoff登出事件
  create or replace trigger tg_login
before logoff on database
begin 
  lnser ino logs values(ora_login_user,ora_sysevent,sysdate)
  end;

触发器禁止和启用

--禁止触发器
alter trigger tg_insertEmp3 disable;
alter trigger tg_insertEmp3 enable;
相关标签: oracle