PLSQL触发器,游标
- --触发器
- drop table emp_log
- create table emp_log(
- empno number,
- log_date date,
- new_salary number,
- action varchar2(20) --动作记录
- );
- create or replace trigger log_sal_adj
- after update of sal on emp --指定当update执行后,监控对emp表sal列的更改 before or adter
- for each row --每update一行执行一次触发器代码
- declare
- v_action varchar2(20); --定义一个保存更新行为的字符串变量
- begin
- if :old.sal >:new.sal THEN
- v_action :='减少工资';
- elsif :old.sal<:new.sal then
- v_action :='增加工资';
- end if;
- insert into emp_log
- (empno,log_date,new_salary,action)
- values
- (:new.empno,sysdate,:new.sal,v_action);
- end;
- select * from emp_log;
- select sal from emp where empno=7369;
- update emp set sal=8000 where empno=7369;
- --异常处理示例
- declare
- v_result number:=0;
- v_dividend number:=&a; --定义替换变量
- begin
- v_result:=round(1000/v_dividend,2);
- dbms_output.put_line('结果值为:'||v_result);
- exception
- when zero_divide then --如果是被0除错误
- dbms_output.put_line('出现被0除的错误了!');
- when others then --所有其他错误的异常处理句柄
- dbms_output.put_line(sqlcode); --输出错误代码
- dbms_output.put_line(sqlerrm); --输出错误消息
- end;
- --记录类型示例
- Declare
- type emp_rec_type is record(
- empno emp.empno%type,
- ename varchar2(50),
- job varchar2(20) );
- emp_info_rec emp_rec_type;
- emp_row_rec emp%Rowtype; --=>(eno emp.empno%type +enme emp.ename%type)
- begin
- emp_info_rec.empno:=8222;
- emp_info_rec.ename:='李三思';
- emp_info_rec.job :='销售人员';
- insert into emp (empno,ename,job)
- values (emp_info_rec.empno,emp_info_rec.ename,emp_info_rec.job);
- select * into emp_row_rec from emp where empno=8222;
- dbms_output.put_line('新插入的员工记录信息:'||CHR(10)||'工号:'||
- emp_row_rec.empno||CHR(10)||'姓名:'||
- emp_row_rec.ename||CHR(10)||'职位:'||
- emp_row_rec.job);
- end;
- --集合类型使用示例
- declare
- --定义保存员工工号的索引表,其类型为emp表中的empno字段相同的类型
- type NumTab is table of emp.empno%type index by binary_integer; --pls_integer
- type NameTab is table of emp.ename%type index by binary_integer;
- --定义集合类型的变量
- enums NumTab;
- names NameTab;
- /* 定义块 type语句定义了NumTab和NameTab这两个索引表,
- is table of指定索引的类型, index by指定索引的下标数据类型
- binary_integer是PL/SQL中的整数类型
- 匿名块print_first_n,它的作用范围仅限于匿名块内部
- 执行 select..bulk collect into将表中查询出来的多行记录写入到集合中
- */
- procedure print_first_n(n POSITIVE) is
- BEGIN
- IF enums.count =0 then
- DBMS_OUTPUT.put_line('当前集合为空!');
- else
- DBMS_OUTPUT.put_line('前'||n||'名员工:');
- for i in 1..n loop
- dbms_output.put_line('员工工号:'||enums(i)||': '||names(i));
- end loop;
- end if;
- END;
- begin
- select empno,ename bulk collect
- into enums,names from emp
- order by empno;
- print_first_n(3);
- print_first_n(6);
- end;
- select empno,ename from emp order by empno;
- --使用游标遍历结果集
- declare
- emprow emp%rowtype;
- cursor emp_cur
- is
- select * from emp where deptno=20;
- begin
- open emp_cur;
- loop
- fetch emp_cur
- into emprow;
- DBMS_OUTPUT.put_line('员工编号:'||emprow.empno||' '
- ||'员工名称:'||emprow.ename);
- exit when emp_cur%NOTFOUND;
- end loop;
- close emp_cur; --关闭游标
- end;
- 1 emprow是一个记录类型,保存fetch语句提取的记录值
- 2 cursor is 指向一个返回结果集的select语句
- 3 open语句打开游标,指向结果集内存区域
- 4 游标使用完之后,必须显示调用close关闭游标,释放资源
- 子程序不像匿名块仅仅是一次使用,子程序存储在数据字典中
- 可以被其它子程序重复调用
- --使用游标和索引表显示员工名称
- DECLARE
- --定义员工名称索引表
- TYPE emp_table IS TABLE OF VARCHAR2(10);
- emplist emp_table; --定义表类型的变量
- CURSOR empcursor IS
- SELECT ename FROM emp;
- BEGIN
- IF NOT empcursor%ISOPEN THEN
- OPEN empcursor;
- END IF;
- FETCH empcursor BULK COLLECT
- INTO emplist;
- FOR i IN 1 .. emplist.COUNT LOOP
- DBMS_OUTPUT.put_line('员工名称:' || emplist(i));
- END LOOP;
- CLOSE empcursor;
- END;
- --rowid使用示例
- declare
- v_empname rowid;
- v_other varchar2(18);
- begin
- select rowid into v_empname from emp where empno=&empno;
- dbms_output.put_line(v_empname);
- v_other:=rowidtochar(v_empname);
- dbms_output.put_line(v_other);
- end;
- select rowid from emp where empno=7369;
- --批量提取游标数据
- DECLARE
- type depttab_type is table of dept%rowtype;
- depttab depttab_type;
- cursor deptcur is select * from dept;
- begin
- open deptcur;
- fetch deptcur bulk collect into depttab;
- for i in 1 .. depttab.count
- loop
- dbms_output.put_line(depttab (i).deptno ||' '||depttab(i).dname||' '||depttab(i).loc);
- end loop;
- close deptcur;
- end;
- --操纵游标数据 loop循环
- declare
- dept_row dept%rowtype;
- cursor dept_cursor is select * from dept;
- begin
- open dept_cursor;
- loop
- fetch dept_cursor into dept_row;
- exit when dept_cursor%notfound;
- dbms_output.put_line('部门名称:'||dept_row.dname);
- end loop;
- close dept_cursor;
- end;
- --while循环
- declare
- dept_row dept%rowtype;
- cursor dept_cursor is select * from dept;
- begin
- open dept_cursor;
- fetch dept_cursor into dept_row;
- while dept_cursor%found loop
- dbms_output.put_line('部门名称:'||dept_row.dname);
- fetch dept_cursor into dept_row;
- end loop;
- close dept_cursor;
- end;
- 调用了2次fetch语句, 判断之前fetch一次获取%found属性值
- 后面的fetch语句在循环体内对每一次的循环求值
- /*游标for循环 尽管定义为一个显式游标,但PLSQL引擎进行特别处理
- 不需要open,close;*/
- declare
- cursor dept_cursor is select * from dept;
- begin
- for dept_row in dept_cursor loop
- dbms_output.put_line('部门名称:'||dept_row.dname);
- end loop;
- end;
- --游标FOR循环子查询语句
- begin
- for dept_row in (select * from dept) loop
- dbms_output.put_line('部门名称:'||dept_row.dname);
- end loop;
- end;
- --使用游标更新数据
- declare
- cursor emp_cursor(p_deptno in number)
- is select * from emp where deptno=p_deptno for update;
- --使用for update子句添加互斥锁
- begin
- for emp_row in emp_cursor(20)
- loop
- update emp set sal=sal*1.12
- where current of emp_cursor;
- end loop;
- commit;
- end;
- select sal,ename from emp where deptno=20;
- --使用游标删除数据
- declare
- cursor emp_cursor(p_empno in number)
- is select * from emp_copy where empno=p_empno for update;
- begin
- for emp_row in emp_cursor(7369)
- loop
- delete from emp_copy where current of emp_cursor;
- end loop;
- end;
- --游标变量
- declare
- type emp_type is ref cursor return emp%rowtype;
- emp_cur emp_type;
- emP_row emp%rowtype;
- begin
- open emp_cur for select * from emp;
- loop
- fetch emp_cur into emp_row;
- exit when emp_cur%notfound;
- dbms_output.put_line('员工名称:'|| emp_row.ename);
- end loop;
- end;
- 11.14
- --使用close 语句关闭游标变量
- --如果type语句中未指定return子句,则可以连续地打开多次,分别为其赋不同的select语句
- declare
- type emp_type is ref cursor return emp%rowtype;
- emp_cur emp_type;
- emp_row emp%rowtype;
- begin
- open emp_cur for select * from emp where deptno=20;
- fetch emp_cur into emp_row;
- while emp_cur%found loop
- dbms_output.put_line('员工名称:'||emp_row.ename);
- fetch emp_cur into emp_row;
- end loop;
- close emp_cur;
- end;
- 关闭一个还没有打开过的游标变量或已经关闭了的游标变量是非法的
- PLSQL引发invalid_cursor异常
- declare
- type emp_curtype is ref cursor;
- emp_cur1 emp_curtype;
- emp_cur2 emp_curtype;
- emp_row emp%rowtype;
- begin
- open emp_cur1 for select * from emp where deptno=20;
- fetch emp_cur1 into emp_row;
- dbms_output.put_line('员工名称:'||emp_row.ename||'部门编号:'
- ||emp_row.deptno);
- fetch emp_cur2 into emp_row;
- exception
- when invalid_cursor then
- emp_cur2:=emp_cur1;
- fetch emp_cur2 into emp_row;
- dbms_output.put_line('员工名称:' ||emp_row.ename||
- '部门编号:'||emp_row.deptno);
- --重新打开emp_cur2游标变量,利用相同的查询区域
- open emp_cur2 for select * from emp where deptno=40;
- fetch emp_cur1 into emp_row;
- --emp_cur1与emp_cur2共享相同的查询区域,因此结果相同
- dbms_output.put_line('员工名称:' ||emp_row.ename||
- '部门编号:'||emp_row.deptno);
- end;
- 使用open for语句打开emp_cur2时候,将相同的查询区域执行另一个查询语句
- 由于emp_cur1与emp_cur2都指向相同的查询区域,提取emp_cur1时候
- 实际相当于对emp_cur2提取
- --处理ROWTYPE_MISMATCH异常
- declare
- type emp_curtype is ref cursor;
- emp_cur emp_curtype;
- emp_row emp%rowtype;
- dept_row dept%rowtype;
- begin
- open emp_cur for select * from emp where deptno=20;
- fetch emp_cur into dept_row;
- exception
- when rowtype_mismatch then
- fetch emp_cur into emp_row;
- dbms_output.put_line('员工名称:'||emp_row.ename
- ||'部门编号:'||emp_row.deptno);
- end;
- --使用sys_refcursor类型 不需要type语句显式定义弱类型游标
- declare
- emp_cur sys_refcursor; --定义弱类型游标变量
- emp_row emp%rowtype;
- dept_row dept%rowtype;
- begin
- open emp_cur for select * from emp where deptno=20;
- fetch emp_cur into dept_row;
- exception
- when rowtype_mismatch then
- fetch emp_cur into emp_row;
- dbms_output.put_line('员工名称:'||emp_row.ename
- ||'部门编号:'||emp_row.deptno);
- end;
- --在包中使用游标变量
- create or replace package emp_data_action as
- type emp_type is ref cursor return emp%rowtype; --定义强类型游标
- procedure getempbydeptno(emp_cur in out emp_type,p_deptno number);
- end emp_data_action;
- create or replace package body emp_data_action as
- procedure getempbydeptno(emp_cur in out emp_type,p_deptno number)
- is emp_row emp%rowtype;
- begin
- open emp_cur for select * from emp where deptno=p_deptno;
- loop
- fetch emp_cur into emp_row;
- exit when emp_cur%notfound;
- dbms_output.put_line('员工名称:'||emp_row.ename
- ||'部门编号:'||emp_row.deptno);
- end loop;
- close emp_cur;
- end;
- end emp_data_action;
- declare
- emp_cursors emp_data_action.emp_type;
- begin
- emp_data_action.getempbydeptno(emp_cursors,20);
- end;
- 游标变量的限制
- 1.不能在包中声明游标变量
- 2 不能在创建表或创建视图的语句中把字段类型指定为REF CURSOR类型
- 数据库字段不能存放游标变量值
- 3 游标类型参数不支持远程过程调用
- 4 不能将ref cursor 类型作为集合的元素类型
- 5 不能在游标中使用游标for循环
- 一个事务必须满足ACID 即原子性,一致性,隔离性和持久性
- --使用保存点局部回滚
- declare
- dept_no number(2) :=90;
- begin
- savepoint A;
- insert into dept values(dept_no,'市场部','北京');
- savepoint B;
- insert into emp values(7997,'威尔','销售人员',null,trunc(sysdate),5000,300,dept_no);
- savepoint c;
- insert into dept values(dept_no,'后勤部','上海'); --插入相同编号的部门记录
- commit;
- exception
- when dup_val_on_index then
- dbms_output.put_line(sqlerrm);
- rollback to b;
- end;
- select * from dept;
- --控制触发顺序 FOLLOWS子句
- create or replace trigger one_trigger
- before insert on trigger_data for EACH ROW
- begin
- :new.trigger_id := :new.trigger_id+1;
- DBMS_OUTPUT.put_line('触发了one_trigger');
- end;
- create or replace trigger two_trigger
- before insert on trigger_data
- for each row follows one_trigger --让该触发器在one_trigger后面触发
- begin
- DBMS_OUTPUT.put_line('触发了two_trigger');
- if :new.trigger_id>1
- then
- :new.trigger_id := :new.trigger_id +2:
- end if;
- end;
- --系统触发器 scott
- create table created_log
- (
- obj_owner varchar2(30),
- obj_name varchar2(30),
- obj_type varchar2(20),
- obj_user varchar2(30),
- created_date DATE
- )
- --system
- create or replace trigger t_created_log
- after create on scott.SCHEMA --在Scott方案下创建对象后触发
- begin
- insert into scott.created_log(obj_owner,obj_name,obj_type,obj_user,
- created_date) values (sys.dictionary_obj_owner,sys.dictionary_obj_name,
- sys.dictionary_obj_type,sys.login_user,sysdate);
- end;
- --scott
- create table temp_table(field1 varchar2(20),field2 number(5));
- select * from created_log;
- 触发器属性列表 图6
- --ora_is_drop_column和ora_is_alter_column 禁止非法更改列
- create or replace trigger preserve_app_cols
- after alter on schema
- declare
- cursor curs_get_columns (cp_owner varchar2,cp_table varchar2)
- is select column_name from all_tab_columns
- where owner = cp_owner and table_name=cp_table;
- begin
- if ora_dict_obj_type ='TABLE'
- THEN
- FOR v_column_rec in curs_get_columns (ora_dict_obj_owner,ora_dict_obj_name)
- loop
- if ora_is_drop_column(v_column_rec.column_name)
- then
- if v_column_rec.column_name='EMPNO' THEN
- RAISE_APPLICATION_ERROR(-2003,'不能对empno字段进行修改');
- end if;
- end if;
- end loop;
- end if;
- end;
- alter table emp drop column empno
- select * from emp;
PLSQL触发器,游标的更多相关文章
- oracle(sql)基础篇系列(五)——PLSQL、游标、存储过程、触发器
PL/SQL PL/SQL 简介 每一种数据库都有这样的一种语言,PL/SQL 是在Oracle里面的一种编程语言,在Oracle内部使用的编程语言.我们知道SQL语言是没有分支和循环的,而PL语 ...
- oracle(sql)基础篇系列(五)——PLSQL、游标、存储过程、触发器
PL/SQL PL/SQL 简介 每一种数据库都有这样的一种语言,PL/SQL 是在Oracle里面的一种编程语言,在Oracle内部使用的编程语言.我们知道SQL语言是没有分支和循环的,而PL语言是 ...
- SQL SERVER触发器游标小记
今天接到个需求用触发器来实现通过条件对其他表的更新.好久没摸SQL SERVER,电脑里也没SQL SERVER安装包,同事遂发来个安装包,一看吓一跳,3.6G!!!!经过漫长等待后,开始作业.需求如 ...
- sql 触发器 游标
在数据库中,删除一条记录的同时想要删除另一个表里的数据,这时我们可以选择使用触发器.触发器主要是通过事件进行触发被自动调用执行的,而存储过程可以通过存储过程的名称被调用.触发器是当对某一个表进行操作. ...
- 2018.5.30 Oracle数据库PLSQL编程---游标的使用
显示游标的步骤 /* 显示游标处理步骤 1.声明游标 语法结构:cursor 游标名称 is SQL 语句; 2.打开游标 语法结构:open游标名称; 3.提取数据 语法结构:fetch 4.关闭游 ...
- Oracle plsql 触发器 查询/启用/停止
在PLSQL中查询某个表的触发器脚本 select * from user_triggers where table_name='xxx' oracle触发器的启用和停用 1.禁用 table_nam ...
- PLSQL触发器
触发器权限 数据库创建用户时想要在本用户下使用触发器,需要给用户触发器的权限 使用DBA用户执行 GRANT CREATE TRIGGER TO user_name; 如果想在当前用户下创建其他用户 ...
- .Net程序员学用Oracle系列(27):PLSQL 之游标、异常和事务
1.游标 1.1.游标属性 1.2.隐式游标 1.3.游标处理及案例 2.异常 2.1.异常类别 2.2.异常函数 2.3.异常处理及案例 3.事务 3.1.开始事务.结束事务 3.2.自治事务 3. ...
- SQL记录-PLSQL触发器
PL/SQL触发器 触发器是存储程序,它会自动执行或发射当一些事件发生.触发器,事实上,写入响应于以下任一事件将被执行: 数据库操作(DML)语句(DELETE,INSERT,UPDATE或) 数据库 ...
随机推荐
- jquery环形3D立体旋转特效
jquery环形3D立体旋转特效 作者/代码整理:站长素材 (转载请附加本文地址,带有“懒人原生”字样的谢绝转载)发布日期:2013-07-20 立体效果比较强的jquery特效,周围小图组 ...
- Spring常用jar包的功能
jar名称 描述 spring-framework.jar spring框架比较完整的功能,core+aop+ioc+transaction spring-core.jar 基本上的核心工具类,一些u ...
- P3694 邦邦的大合唱站队
题目背景 BanG Dream!里的所有偶像乐队要一起大合唱,不过在排队上出了一些问题. 题目描述 N个偶像排成一列,他们来自M个不同的乐队.每个团队至少有一个偶像. 现在要求重新安排队列,使来自同一 ...
- 随手练——Uva-11584 划分成回文串(区间DP)
思路:dp[i]代表到第i位的最小值,枚举它的前几位,求出最小值. 转移方程:dp[ i ] = min(dp[ i ], dp[ j - 1 ] + 1 ) ; 本来觉得,代码加深部分可以提前bre ...
- 调试cnn-Sentence-Classifier遇到的问题
运行train文件训练模型出现了以下错误: train文件在app文件目录下: raw_vectors.txt文件则在cnn-Sentence-Classifier目录下: 这是train代码调用re ...
- (转)使用 Nmon 监控 Linux 的系统性能
看到一个使用Nmon的文章,写的很基础,适合新手,转载之.下面是原文的信息: 作者:Hitesh Jethva 译者:sonofelice 校对:wxy 传送门:linux.cn/article-68 ...
- 使用Android的OpenGL编写视频播放器
Android自身有MediaPlayer播放器,为什么还要使用OpenGL?因为使用OpenGL可以实现更多的效果,比如对视频翻转一定角度,加任意特效,多视频合并播放等,类似“激萌”的APP应该就是 ...
- QoS policy-map class-map
QoS(Quality of ServiceQoS(Quality of Service,服务质量)指一个网络能够利用各种基础技术,为指定的网络通信提供更好的服务能力, 是网络的一种安全机制, 是用来 ...
- 把外置sd卡映射为内置sd卡地一个目录
教程:1.已root机器运行re浏览器2.在/sdcard卡上创建目录sd-ext3.找到/etc/rc.local,长按选编辑4.拉到文件最后,在最后一行exit 0前行添加: (sleep ...
- 《Effective C++》item25:考虑写出一个不抛异常的swap函数
std::swap()是个很有用的函数,它可以用来交换两个变量的值,包括用户自定义的类型,只要类型支持copying操作,尤其是在STL中使用的很多,例如: int main(int argc, _T ...