Cursor、Exception、Procedure、Function、Package、Trigger(day06)
回顾:
1.record类型
定义record类型,声明变量,保存s_dept表中id = 31部门信息
declare
/* 定义record类型 */
type deptrecord is record(
id number,
name s_dept.name%type,
r_id number
);
/* 声明变量 */
var_dept deptrecord;
var_id number:=&id;
begin
select * into var_dept from s_dept where id=var_id;
dbms_output.put_line(var_dept.id||','||
var_dept.name||','||
var_dept.r_id);
end;
2.动态SQL
使用动态SQL语句,删除 testdsql 表中指定id 信息
declare
sqlstr varchar2(100);
var_id number:=1;
begin
-- sqlstr:='delete from testdsql_zsm_00 where id='
-- ||var_id;
sqlstr:='delete from testdsql_zsm_00 where id=:b0';
dbms_output.put_line(sqlstr);
execute immediate sqlstr using var_id;
commit;
end;
1.游标:
1.1概念:
游标是映射在结果集中一行数据的位置指针或位置实体。
1.2作用:
处理多行结果集!
用户可以通过游标访问多行结果集中的任何一行数据,即可以对该行数据做操作,比如,把数据提取出来
1.3使用游标步骤:
1) 声明游标
在声明区声明游标名
cursor 游标名 is select语句;
var_emp empcursor%rowtype;//声明游标变量
2)打开游标
在执行区打开游标
open 游标名;
3)提取数据
执行区提取数据
fetch 游标名 into 游标变量;
4)关闭游标
当提取和处理数据结束后,应该及时关闭游标释放系统资源
close 游标名;
1.4使用游标 读取s_emp 表中的全部数据
declare
/* 声明游标 */
cursor empcursor is select * from s_emp;
/* 声明变量 */
var_emp empcursor%rowtype;
begin
/* 打开游标 */
open empcursor;
/* 提取数据 */
fetch empcursor into var_emp;
dbms_output.put_line(var_emp.id||','||
var_emp.first_name||','||
var_emp.salary);
fetch empcursor into var_emp;
dbms_output.put_line(var_emp.id||','||
var_emp.first_name||','||
var_emp.salary);
fetch empcursor into var_emp;
dbms_output.put_line(var_emp.id||','||
var_emp.first_name||','||
var_emp.salary);
/* 关闭游标 */
close empcursor;
end;
1.5游标属性
found 提取到数据,为真;没有提取到,则为假 在open之前,返回非法游标,fetch之前返回null
notfound 没提取到数据,为真;提取到,则为假 .. .. .. ..
isopen 游标是否是打开状态,打开返回真,失败返回假
rowcount 游标的偏移量 没有打开返回非法游标
1.6使用简单循环 配合 notfound 属性 遍历游标
declare
/* 声明游标 */
cursor empcursor is select * from s_emp;
/* 声明变量 */
var_emp empcursor%rowtype;
begin
/* 打开游标 */
open empcursor;
/* 循环提取数据 */
loop
fetch empcursor into var_emp;
exit when empcursor%notfound;
dbms_output.put_line(var_emp.id||','||
var_emp.first_name||','||
var_emp.salary);
end loop;
/* 关闭游标 */
close empcursor;
end;
1.7使用while循环 配合found属性 遍历游标
declare
/* 声明游标 */
cursor empcursor is select * from s_emp;
/* 声明变量 */
var_emp empcursor%rowtype;
begin
/* 打开游标 */
open empcursor;
/* 循环提取数据 */
fetch empcursor into var_emp;
while empcursor%found loop
dbms_output.put_line(var_emp.id||','||
var_emp.first_name||','||
var_emp.salary);
fetch empcursor into var_emp;
end loop;
/* 关闭游标 */
close empcursor;
end;
1.8使用for循环遍历游标
for循环(智能循环) (自动打开游标、提取数据、关闭游标)
declare
cursor empcursor is select * from s_emp;
begin
for var_emp in empcursor loop
dbms_output.put_line(var_emp.id||','||
var_emp.first_name||','||
var_emp.salary);
end loop;
end;
1.9带参游标
参数的数据类型不能包含长度或精度的修饰,但是可以使用%type
声明:
cursor 游标名(形参列表) is select语句 where .... ;
传参: 在打开游标时传实参
open 游标名(实参列表);
declare
cursor empcursor(var_id number)
is select * from s_emp where id>var_id;
begin
for var_emp in empcursor(10) loop
dbms_output.put_line(var_emp.id||','||
var_emp.first_name||','||
var_emp.salary);
end loop;
end;
1.10参考游标 ref cursor
动态SQL + 游标
参考游标的使用步骤:
sqlstr := 'select * from s_emp';
1) 定义一个参考游标类型
type 参考游标类型名 is ref cursor;
2) 声明参考游标类型变量
var_empcursor 参考游标类型名;
3) 把动态sql语句和参考游标变量结合
open var_empcursor for sqlstr;
...... 案例:使用参考游标 遍历s_emp表中的全部数据
declare
sqlstr varchar2(100);
type emprefcursor is ref cursor;
var_empcursor emprefcursor;
var_emp s_emp%rowtype;
begin
sqlstr:='select * from s_emp';
open var_empcursor for sqlstr;
loop
fetch var_empcursor into var_emp;
exit when var_empcursor%notfound;
dbms_output.put_line(var_emp.id||','||
var_emp.first_name||','||
var_emp.salary);
end loop;
close var_empcursor;
end; 带有占位符的sql语句
declare
sqlstr varchar2(100);
type emprefcursor is ref cursor;
var_empcursor emprefcursor;
var_emp s_emp%rowtype;
begin
sqlstr:='select * from s_emp where id>:b0';
-- using后可以使用变量,也可以使用值。一般用变量
open var_empcursor for sqlstr using 10;
loop
fetch var_empcursor into var_emp;
exit when var_empcursor%notfound;
dbms_output.put_line(var_emp.id||','||
var_emp.first_name||','||
var_emp.salary);
end loop;
close var_empcursor;
end;
2.PLSQL中的异常
2.1 系统预定义异常
Oracle 系统自身为用户提供可以在PLSQL中使用的预定义异常,用于检查用户代码失败的一般原因。
系统预定义异常由系统定义和引发,用户只需根据名字捕获和处理异常
案例:
declare
var_name varchar2(25);
var_id number:=&id;
begin
select first_name into var_name from s_emp
where id = var_id;
select first_name into var_name from s_emp
where first_name like 'M%';
dbms_output.put_line(var_name);
exception
when no_data_found then
dbms_output.put_line('no emp');
when others then
dbms_output.put_line(sqlcode||'.....'||sqlerrm);
end;
常用的异常:
no_data_found : select ..into 语句没有返回行
too_many_rows: select..into 语句返回多于一行的结果集
invalid_cursor: 非法游标
cursor_already_open: 游标已打开
dup_val_on_index: 唯一索引对应的列上有重复值
zero_divide: 除数为0
案例:处理多个异常
declare
var_name varchar2(25);
var_id number:=&id;
begin
select first_name into var_name from s_emp
where id = var_id;
select first_name into var_name from s_emp
where first_name like 'M%';
dbms_output.put_line(var_name);
exception
when no_data_found then
dbms_output.put_line('no emp');
when too_many_rows then
dbms_output.put_line(' too many rows');
when others then
dbms_output.put_line(sqlcode||'.....'||sqlerrm);
end;
2.2自定义异常:
2.2.1 定义异常的步骤:
1)定义异常
异常名 exception ;
2)根据条件引发异常
if 引发异常条件 then
raise 异常名;
end if;
3)捕获异常和处理异常
when 异常名 then
处理异常
2.2.2 案例:更新员工表中指定员工的工资,员工不存在时提示异常
declare
var_id s_emp.id%type:=&id;
/* 定义异常 */
no_result exception;
begin
update s_emp set salary=salary+500 where id=var_id;
if sql%notfound then
raise no_result;
end if;
commit;
exception
when no_result then
dbms_output.put_line('no result');
end;
隐式游标:在执行一个SQL语句时,Oracle会自动创建一个隐式游标。这个游标是内存中为处理该条SQL语句的工作区。
隐士游标只要用于处理数据操作语句(insert、delete、update)的执行结果
3.存储过程 procedure
3.1匿名块和有名块
匿名块:
匿名块不保存在与数据库中;每次使用都要 进行编译;不能在其他块调用
有名块:
可以存储在数据库中;可以在任何需要的地方调用
有名块包括:procedure function package trigger
3.2存储过程的创建
语法:
create [ or replace ] procedure 过程名 [ (参数列表) ]
is|as
--临时变量
begin
exception
end;
3.3无参过程的创建和调用
1)创建:输出两数中的较大值
create or replace procedure getmax_zsm_00
is
var_a number:=10;
var_b number:=100;
begin
if var_a > var_b then
dbms_output.put_line(var_a);
else
dbms_output.put_line(var_b);
end if;
end;
2)创建无参的存储过程
begin
getmax_zsm_00;
end;
3.4 带参的存储过程
3.4.1 使用的注意事项
1)参数的数据类型不能包含长度或精度的修饰
2)参数可以有多种模式,并且可以有默认值
参数名 {in | out |in out} 类型 {:= | default}值
参数模式:
in 输入参数 负责向过程传入值 系统默认
out 输出参数 负责传出值 实参必须是变量 不必赋值 在过程内必须赋值
in out 输入输出参数 既负责传入又负责传出 实参是赋值后的变量在过程内可以赋值
只有in模式的参数才可以有默认值
3.4.2案例:
案例:创建一个带参的存储过程,传入两个数字,输出最大值
create or replace procedure getmax_zsm_00(
var_a in number:=10,var_b number)
is
begin
if var_a > var_b then
dbms_output.put_line(var_a);
else
dbms_output.put_line(var_b);
end if;
end;
3.4.3带参的存储过程的调用
declare
var_x number:=123;
var_y number:=12;
begin
getmax_zsm_00(1,10);
getmax_zsm_00(var_x,100);
getmax_zsm_00(var_x,var_y);
-- getmax_zsm_00(1);
end;
3.4.4 参数赋值方式
1) 按照位置赋值
2)按照名字赋值 参数名=> 值
declare
var_x number:=123;
var_y number:=12;
begin
getmax_zsm_00(1,10);
getmax_zsm_00(var_x,100);
getmax_zsm_00(var_b=>10,var_a=>200);
getmax_zsm_00(var_b=>1);
end;
3.4.5
3.4.5 练习:创建一个存储过程,传入两个数字,输出最大值,同时把两数之和保存在第二个变量,并测试
create or replace procedure getmax_zsm_00(
var_a in number,var_b in out number)
is
begin
if var_a > var_b then
dbms_output.put_line(var_a);
else
dbms_output.put_line(var_b);
end if;
var_b:=var_a + var_b;
end; -- 调用
declare
var_x number:=100;
begin
getmax_zsm_00(10,var_x);
dbms_output.put_line(var_x);
end;
3.5 查看存储过程
desc 过程名;
desc user_source;
4.函数 Function
4.1 plsql 中的函数和过程的区别
1)关键字不同,过程是procedure 函数是 function
2) 过程没有返回类型和返回值,函数有返回类型和返回值
3)调用方式不同 ,过程在PLSQL中是直接调用,函数在PLSQL中需要组成表达式调用(使用变量接收返回值、作为函数或过程的参数)
4.2语法
create or replace function 函数名[参数列表] return 数据类型
is | as
-- 临时变量
begin
-- 必须有return语句
end;
4.3 创建一个函数 ,传入两个数字,返回最小值
create or replace function getmin_zsm_00(
var_a number,var_b number) return number
is
begin
if var_a < var_b then
return var_a;
else
return var_b;
end if;
end; declare
var_x number:=100;
var_y number:=1;
var_result number;
begin
var_result:=getmin_zsm_00(var_x,var_y);
dbms_output.put_line(var_result);
dbms_output.put_line(getmin_zsm_00(123,10));
end;
5.包 package
5.1概念
把一组逻辑上相关的过程、函数、变量、类型等组织到一起的一种逻辑结构
5.2 系统提供的包
dbms_output: 输入输出包
dbms_random: 随机包
dbms_job: 定时任务调度包
查看包中的数据:
desc 包名;
desc dbms_random;
function value(low number,high number)
return number
包名.成员
select dbms_random.value(1,100) from dual; 5.3 自定义包
1)定义包 package -- 类似于C中.h文件
create [or replace] package 包名
is
-- 函数、过程的声明,类型的定义,变量的声明等
end[ 包名]; -- 定义一个包,包含一个过程和一个函数
create or replace package mypackage_zsm_00
is
procedure getmax(var_a number,var_b number);
function getmin(var_a number,var_b number)
return number;
end; 2) 定义包的主体(包的实现)
create [or replace] package body 包名
is
-- 函数、过程的实现
end[ 包名]; create or replace package body mypackage_zsm_00
is
procedure getmax(var_a number,var_b number)
is
begin
if var_a > var_b then
dbms_output.put_line(var_a);
else
dbms_output.put_line(var_b);
end if;
end; function getmin(var_a number,var_b number)
return number
is
begin
if var_a < var_b then
return var_a;
else
return var_b;
end if;
end;
end; -- 测试
declare
var_x number:=11;
var_y number:=1234;
var_res number;
begin
mypackage_zsm_00.getmax(var_x,var_y);
var_res:=mypackage_zsm_00.getmin(var_x,var_y);
dbms_output.put_line(var_res);
end;
6.触发器 trigger
6.1概念
触发器是一种特殊的‘存储过程’,它定义了一些和数据库相关事件(如insert、delete、update等)执行时应该执行的 ‘功能代码块’,通常用来管理
复杂的完整性约束、或监控对表的修改,对数据审计功能
6.2 语法
create [or replace] trigger 触发器名
{before|after} {insert|update|delete}
on 表名 [for each row]
declare
begin
exception
end; 6.3 语句级触发器
emp_zsm_00 create or replace trigger tri_emp_zsm_00
before update on emp_zsm_00
declare
begin
dbms_output.put_line('table updated');
end; update emp_zsm_00 set salary=salary + 100
where id=1;
update emp_zsm_00 set salary=salary + 100
where id<1;
update emp_zsm_00 set salary=salary + 100
where id>1; 6.4 行级触发器
create or replace trigger tri_emp_zsm_00
before update on emp_zsm_00 for each row
declare
begin
dbms_output.put_line('table updated');
end; update emp_zsm_00 set salary=salary + 100
where id=1;
update emp_zsm_00 set salary=salary + 100
where id<1;
update emp_zsm_00 set salary=salary + 100
where id>1; 标识符:
:old 原值标识符
:new 新值标识符 表名%rowtype类型 insert :new
update :old :new
delete :old create or replace trigger tri_emp_zsm_00
before update on emp_zsm_00 for each row
declare
begin
dbms_output.put_line('table updated');
dbms_output.put_line('old:'||:old.id||','||:old.salary);
dbms_output.put_line('new:'||:new.id||','||:new.salary);
end; update emp_zsm_00 set salary=salary + 100
where id=1;
update emp_zsm_00 set salary=salary + 100
where id<1;
update emp_zsm_00 set salary=salary + 100
where id>1; 注意:触发器中不能包含任何有关事务的操作
事务 谁发起 谁结束 6.5 使用触发器产生主键的值
-- 创建一个表
create table testtrigger_zsm_00(
id number primary key,name varchar2(20));
-- 创建一个序列
create sequence trigger_id_zsm_00;
-- 创建触发器
create or replace trigger tri_pk_zsm_00
before insert on testtrigger_zsm_00 for each row
begin
select trigger_id_zsm_00.nextval into :new.id
from dual;
end; -- 插入一条语句
insert into testtrigger_zsm_00(name) values('test1');
练习:
1.使用游标 遍历s_dept表中的全部数据
2.创建一个存储过程,传入数字n(大于1的整数),计算1..n的累加和,保存在第二个参数,并测试。
Cursor、Exception、Procedure、Function、Package、Trigger(day06)的更多相关文章
- jsp内置对象之response、out、config、exception、pageContext。
本文是对Jsp内置对象的response.out.config.exception.pageContext知识点的详细总结. response对象 Response内置对象和request内置对象是相 ...
- 原生JS:Function对象(apply、call、bind)详解
Function对象(apply.call.bind) 原创文章,转摘请注明出处:苏福:http://www.cnblogs.com/susufufu/p/5850180.html 本文参考MDN做的 ...
- 004-For与Function进阶实战、Lazy的使用
004-For与Function进阶实战.Lazy的使用 For进阶 非常常见的形式 可以加入条件表达式进行数据过滤 Function进阶 函数是有值的(默认的话为Unit),所以可以直接将结果赋值给 ...
- The use of function Merge (update、insert、delete)
1.The use of function merge(update.insert.delete) Example: #1.Initialize the data create table #test ...
- Oracle: 禁忌给一般用户授权create any procedure、execute any procedure
给一般用户授 create any procedure.execture any procedure 这2个权限是很不安全的事. 因为授权后,通过一些处理,该用户可以取得dba权限,请一定注意. 下面 ...
- js中使用function定义类、实例化,函数的调用方法
function Test002(name, age){ name, age, this.printInfo = function(){ //定义的公有方法 console.log(name, age ...
- Java8 函数式接口 @FunctionalInterface以及常用Consumer<T>、Supplier<T>、Function<T, R>、Predicate<T>总结
首先看看什么是Lambda 表达式 Lambda是一个匿名函数,我们可以把Lambda表达式理解为一段可以传递的代码(将代码像数据一样传递):最简单的Lambda表达式可由逗号分隔的参数列表.-> ...
- Function.prototype.bind、call与apply
学习Function.prototype.bind.call与apply时,看到一篇博客,学到一些内容,但由于博客时间太久,根据官方文档对内容进行一些修正:下文为修正过内容 前言 前段时间面试遇见一题 ...
- 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入
使用react全家桶制作博客后台管理系统 前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...
- jdk8系列三、jdk8之stream原理及流创建、排序、转换等处理
一.为什么需要 Stream Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念.它也不同于 StAX ...
随机推荐
- HDU 4542
T_T终于让我过了,坑啊,竟然时限是200ms... 我是预处理出不整除了个数的,因为这个较容易一点.利用算术基本定理,f=p1^a1*p2^a2...... 所以,整除它的个数就是(a1+1)*(a ...
- Oracle学习(12):存储过程,函数和触发器
存储过程和存储函数 l存储在数据库中供全部用户程序调用的子程序叫存储过程.存储函数. 注意:存储过程与存储函数声明变量时,用的是as 而不是declare 存储过程与存储函数差别 存储过程不带有返 ...
- 升级到VS2013常见问题
问题1: Building an MFC project for a non-Unicode character set is deprecated 解决方法: 用于多字节字符编码 (MBCS) 的 ...
- .NET通用基本权限系统框架源代码
DEMO下载地址: http://download.csdn.net/detail/shecixiong/5372895 一.开发技术:B/S(.NET C# ) 1.Windows XP以上 (支援 ...
- Python入门 六、像个 Pythonista
pickle import pickle test_data = ['Save me!',123.456,True] f = file('test.data','w') pickle.dump(tes ...
- E20170826-hm
squash vt. 挤进; 将(某人[某物])压扁; 使沉默; 平定(叛乱等); meld vt. (使) 融合,合并,结合; n. 混合,合并; amend vt. 修订; 改良,修改; a ...
- hdu5249
这个是去年astar的题~ 标准做法主席树,然而渣渣并不会(我确实叫zhazha...), 所以,他先离线,离散化,然后树状数组+二分水过了.... 离线的目的主要是为了离散化,剩下的就和用一个树状数 ...
- thinkphp的session用法
Session方法用于Session 设置.获取.删除和管理操作. Session 用于Session 设置.获取.删除和管理操作 用法 session($name, $value='') 参数 na ...
- prim解决最小生成树问题
#include <iostream> #include <algorithm> #include <stdio.h> #include <math.h> ...
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) C. Destroying Array -- 逆向思维
原题中需要求解的是按照它给定的操作次序,即每次删掉一个数字求删掉后每个区间段的和的最大值是多少. 正面求解需要维护新形成的区间段,以及每段和,需要一些数据结构比如 map 和 set. map< ...