--触发器
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触发器,游标的更多相关文章

  1. oracle(sql)基础篇系列(五)——PLSQL、游标、存储过程、触发器

      PL/SQL PL/SQL 简介 每一种数据库都有这样的一种语言,PL/SQL 是在Oracle里面的一种编程语言,在Oracle内部使用的编程语言.我们知道SQL语言是没有分支和循环的,而PL语 ...

  2. oracle(sql)基础篇系列(五)——PLSQL、游标、存储过程、触发器

    PL/SQL PL/SQL 简介 每一种数据库都有这样的一种语言,PL/SQL 是在Oracle里面的一种编程语言,在Oracle内部使用的编程语言.我们知道SQL语言是没有分支和循环的,而PL语言是 ...

  3. SQL SERVER触发器游标小记

    今天接到个需求用触发器来实现通过条件对其他表的更新.好久没摸SQL SERVER,电脑里也没SQL SERVER安装包,同事遂发来个安装包,一看吓一跳,3.6G!!!!经过漫长等待后,开始作业.需求如 ...

  4. sql 触发器 游标

    在数据库中,删除一条记录的同时想要删除另一个表里的数据,这时我们可以选择使用触发器.触发器主要是通过事件进行触发被自动调用执行的,而存储过程可以通过存储过程的名称被调用.触发器是当对某一个表进行操作. ...

  5. 2018.5.30 Oracle数据库PLSQL编程---游标的使用

    显示游标的步骤 /* 显示游标处理步骤 1.声明游标 语法结构:cursor 游标名称 is SQL 语句; 2.打开游标 语法结构:open游标名称; 3.提取数据 语法结构:fetch 4.关闭游 ...

  6. Oracle plsql 触发器 查询/启用/停止

    在PLSQL中查询某个表的触发器脚本 select * from user_triggers where table_name='xxx' oracle触发器的启用和停用 1.禁用 table_nam ...

  7. PLSQL触发器

    触发器权限 数据库创建用户时想要在本用户下使用触发器,需要给用户触发器的权限 使用DBA用户执行  GRANT CREATE TRIGGER TO user_name; 如果想在当前用户下创建其他用户 ...

  8. .Net程序员学用Oracle系列(27):PLSQL 之游标、异常和事务

    1.游标 1.1.游标属性 1.2.隐式游标 1.3.游标处理及案例 2.异常 2.1.异常类别 2.2.异常函数 2.3.异常处理及案例 3.事务 3.1.开始事务.结束事务 3.2.自治事务 3. ...

  9. SQL记录-PLSQL触发器

    PL/SQL触发器 触发器是存储程序,它会自动执行或发射当一些事件发生.触发器,事实上,写入响应于以下任一事件将被执行: 数据库操作(DML)语句(DELETE,INSERT,UPDATE或) 数据库 ...

随机推荐

  1. 解决redis-cli command not found问题

    在使用其他服务器连接Redis服务器时,一般使用的语句是 [redis-cli -h IP -p port] 但是早上连接时报错:redis-cli command not found 在redis服 ...

  2. python第二课——数据类型1

    day02(上午)主要讲了进制问题,小编之前已经发过了 day02(下午): 1.数据类型: 分类: 1).整数型:int浮点型(小数):float布尔型(True/False):bool 2).字符 ...

  3. 【目录】利用Python进行数据分析(第2版)

    第一章 准备工作 1.1 What Is This Book About(这本书是关于什么的) 1.2 Why Python for Data Analysis?(为什么使用Python做数据分析) ...

  4. swift的enum基础

    其它语言的枚举: 符号化的整型常量的集合: swift的枚举: 可以是任何基础类型和无类型: If you are familiar with C, you will know that C enum ...

  5. 智能家居中的物联网网关的可信计算平台模块(TPM)设计

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/BlueCloudMatrix/article/details/24184461 摘要: 随着智能家居 ...

  6. BZOJ3052:[WC2013]糖果公园(树上莫队)

    Description Input Output Sample Input 4 3 51 9 27 6 5 12 33 13 41 2 3 21 1 21 4 20 2 11 1 21 4 2 Sam ...

  7. Day6 jQuery

    元素的操作 dom对象和jQuery对象 dom对象:原生js获取节点 jQuery对象:通过jQuery获取节点对象 //dom对象 var oP = document.getElementById ...

  8. HihoCoder - 1336 二维数状数组(单点更新 区间查询)

    You are given an N × N matrix. At the beginning every element is 0. Write a program supporting 2 ope ...

  9. 【html】文字排版

    Web开发过程中文字排版,默认的情况下,行末的长单词会撑开容器. 我们想要的是(像word一样.能够自动换行.既不撑大容器.也不强制拆开行末单词.并且不会隐藏行末单词的多余字母) ①不能撑开容器 ②完 ...

  10. laravel 的用户认证

    1.简介 Laravel 中实现用户认证非常简单.实际上,几乎所有东西都已经为你配置好了.配置文件位于config/auth.php,其中包含了用于调整认证服务行为的.文档友好的选项配置. 在底层代码 ...