Oracle PL/SQL异常、存储过程和触发器
一、异常
1、处理异常
(1)除数不为0
declare
b number;
begin
b:=1/0;
exception
when zero_divide then
dbms_output.put_line('除数不能为0');
end;
DBMS输出:除数不能为0。
(2)找不到参数
declare
vename varchar2(20);
begin
select ename into vename from emp where deptno=200; --此处会报no date found异常
exception
when no_date_found then
dbms_output.put_line('未找到任何数据');
end;
DBMS输出:未找到任何数据。
2、自定义异常
declare
--声明变量
vreturn varchar2(20);
vename emp.ename%type;
vsal emp.sal%type; --声明异常
sal_isnull exception;
sal_iszero exception;
sal_islow exception; begin
vename:=&ename;
select sal into vsal from emp where vename=&ename; --定义抛出异常条件
if vsal is null then
vreturn:=vename;
raise sal_isnull; elsif vsal is null
vreturn:=vename;
raise sal_iszero; elsif vsal<1850 then
vreturn:=vename;
raise sal_islow;
end if; --自己处理异常
exception
when sal_isnull then
dbms_output.put_line(vreturn||'工资为空异常'); when sal_iszero then
dbms_output.put_line(vreturn||'工资为0'); when sal_islow then
dbms_output.put_line(vreturn||'工资低于标准工资');
end;
控制台输入:'MARTIN' DBMS输出:工资低于标准工资
二、存储过程
迄今为止,所创建的PL/SQL程序都是匿名的,其缺点是在每次执行的时候都要被重新编译,并且没有存储在数据库中,因此不能被其他PL/SQL块使用。Oracle允许在数据库的内部创建并存储编译过的PL/SQL程序,以便随时调用。该类程序包括过程、函数、包和触发器。我们可以将商业逻辑、企业规划等写成过程或函数保存到数据库中、通过名称进行调用,以便更好地共享和使用。
存储过程(Stored Procedure )是一组为了完成特定功能的SQL 语句集,经编译后存储在数据库中。用户通过指定存储过程的名字并给出参数(该存储过程亦可带有参数)来执行它。存储过程是由流控制和SQL 语句书写的过程,这个过程经编译和优化后存储在数据库服务器中,应用程序使用时只要调用即可。
适用一下情况:
- 需要长期保存在数据库中
- 需要被多个用户重复调用
- 业务逻辑相同,参数不同
- 大批量的数据插入、修改和删除等操作
与函数的区别:
1、函数只能返回一个值,且必须设置返回值,在存储过程可以返回多个值。
2、最大的区别:函数要放入sql语句或者某个表达式进行调用,而存储过程可以独立执行且不能被sql语句调用,直接通过call或者declare直接执行。
3、函数限制比较多,比如不能用临时表,只能用表变量.还有一些函数都不可用等等.而存储过程的限制相对就比较少。
4、一般来说,存储过程实现的功能要复杂一点,而函数的实现的功能针对性比较强。
5、对于存储过程来说可以返回参数,而函数只能返回值或者表对象。
6、存储过程一般是作为一个独立的部分来执行(EXEC执行),而函数可以作为查询语句的一个部分来调用(SELECT调用),由于函数可以返回一个表对象,因此它可以在查询语句中位于FROM关键字的后面。
7、当存储过程和函数被执行的时候,SQL Manager会到procedure cache中去取相应的查询语句,如果在procedure cache里没有相应的查询语句,SQL Manager就会对存储过程和函数进行编译。
Procedure cache中保存的是执行计划 (execution plan) ,当编译好之后就执行procedure cache中的execution plan,之后SQL SERVER会根据每个execution plan的实际情况来考虑是否要在cache中保存这个plan,评判的标准一个是这个execution plan可能被使用的频率;其次是生成这个plan的代价,也就是编译的耗时。保存在cache中的plan在下次执行时就不用再编译了。
如下图所示:
优点:
1、存储过程只在创造事进行编译,以后每次执行存储过程都不需要重新编译,而一般SQL语句每执行一次就编译一次,所以使用存储过程可以提高数据库的执行速度。
2、当对数据库进行附在小左时(如对锁哥表进行update,insert,query,delete),可以将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。
3、存储过程可以重复使用,可减少数据库开发人员的工作量。
4、安全性高,可设定只要某用户才具有对制定存储过程的使用权。
5、减少网络交互的成本。
缺点:
1、不可移植性,每种数据库的内部变成语法都不大相同,当系统需要兼容多种数据库时,最好不要用存储过程。
2、学习成本高,DBA一般都擅长写存储过程,但不是每个程序员都能写好存储过程,否则后期系统维护会产生问题。
3、业务逻辑多出存在,采用存储过程后意味着你的系统有一些业务逻辑不是应用程序里处理,这种架构会增加一些系统位数和调试成本。
4、存储过程和常用应用程序语言不一样,它支持的函数及语法有可能不满足需求,有些逻辑只能通过应用程序处理。
5、如果存储过程中有复杂运算的话,会增加依稀额数据库服务端的处理成本,对于集中式数据库可能会导致可扩展性问题。
6、为了提高性能,数据库会把存储过程代码编译成中间运行代码(类似于java的class文件),当存储过程引用的对象(表、视图等等)结构改变后,存储过程需要重新编译才能生效,在24*7高并发应用场景,一般都在线变更结构,所以在变更的瞬间要同时编译存储过程,这可能导致数据库瞬间压力上升引起故障。
1、创建过程
格式:
--创建过程
create or replace procedure 过程名
(可含参数(in 输入参数,out输出参数),可无参) as
begin
语句块;
end;
--创建过程
create or replace procedure pd_deptnocount
(vdeptno in number,vcount out number) as --返回值是vcount
begin
select count(empno) into vcount from emp
where deptno vdeptno
group by deptno;
end;
2、调用过程(匿名语句块)
declare
vdeptno number;
vcount number;
begin
vdeptno:=&deptno;
pd_deptnocount(vdeptno,vcount);
dbms_output.put_line(vdeptno||'部门共有员工'||vcount);
end;
执行:在控制台输入20,DBMS输出:20部门共有员工5
3、游标的存储过程
a、在一个包内定义一个游标类型。
b、创建存储过程,打开游标抓取的对象。
c、调用时,先创建包类游标,执行存储对象把游标设置好,通过loop执行游标,关闭游标。
--1、在包体声明游标类型
create or replace package mypackage
as
type mycustype is ref cursor; --声明游标的类型 ref:符复合类型
end; --2、编写存储过程
--打开游标,将select查询的内容封装到游标里面
create or replace procedure pd_selectename
(mycus out mypackage.mycustype) as
begin
open mycus for select * from emp;
end; --3、调用过程
declare
--定义游标 游标名 游标类型
mycus mypackage.mycustype;
vrow emp%rowtype;
begin
pd_selectename(mycus);
--不需要打开游标,上面已经打开了
loop
fetch mycus into vrow; --抓取一整行
exit when mycus%notfound;
dbms_output.put_line(vrow.ename);
end loop;
close mycus;
end;
分步执行1、2和3,最终执行结果:
例:输入表名,返回最大行数(多少条数据)。
create or replace procedure pd_countTable --创建
(tablename in varchar2,tablerow out number)
as
mysql varchar2(500);
begin
mysal:='select count(*) from '||tablename;
execute immediate mysql into tablerow;
end; --调用
declare
countAll number;
tablename varchar2(20);
begin
tablename:=&tablename;
pd_countTable(tablename,countrow);
dbms_output.put_line(countrow);
end;
执行:在控制台输入‘emp’,DBMS输出:15(有15行数据)
三、触发器
触发器的定义就是说某个条件成立的时候,触发器里面所定义的语句就会被自动的执行。
它的执行由事件触发。触发器经常用于加强数据的完整性约束金额业务规则等。
触发器与存储过程唯一的区别是触发器不能执行execute语句调用,而是在用户执行Transact-SQL语句时自动触发执行。
语法:
create [or replace] trigger 触发器名 触发时间(after/before) 触发事件(update、delete、select)
on 表名
[for each row]
begin
pl/sql语句
end;
create or replace trigger trtest
after update of
sal on emp
for each row
begin
insert into t_logs(txt) values
(:old.ename||'原工资'||:old.sal||',修改后的工资为'||:new.sal);
end;
该在数据栏改动任意一个员工的工资3000->4000,会自动执行触发器,执行结果:
触发器类型:
a、语句级触发器
在指定的操作语句执行之前或之后执行一次,不管这条语句影响了多少行
b、行级触发器(有FOR EACH ROW的)
触发语句作用的每一条记录都被触发。在行级触发器中使用:old和:new伪记录变量,识别值的状态。
Oracle PL/SQL异常、存储过程和触发器的更多相关文章
- ORACLE PL/SQL编程:把触发器说透
本篇主要内容如下: 8.1 触发器类型 8.1.1 DML触发器 8.1.2 替代触发器 8.1.3 系统触发器 8.2 创建触发器 8.2.1 触发器触发次序 8.2.2 创建DML触发器 8.2. ...
- PL/SQL之存储过程和触发器实例
1.Oracle存储过程实例 /*不带任何参数存储过程(输出系统日期)*/ CREATE OR REPLACE PROCEDURE output_date IS BEGIN DBMS_OUTPUT.P ...
- ORACLE PL/SQL编程之八:把触发器说透
原文:ORACLE PL/SQL编程之八:把触发器说透 ORACLE PL/SQL编程之八: 把触发器说透 大家一定要评论呀,感谢!光发表就花了我将近一个下午. 本篇主要内容如下: 8.1 触发器类型 ...
- ORACLE PL/SQL:触发器
ORACLE PL/SQL 触发器 本篇主要内容如下: 8.1 触发器类型 8.1.1 DML触发器 8.1.2 替代触发器 8.1.3 系统触发器 8.2 创建触发器 8.2.1 触发器触发次序 8 ...
- ORACLE PL/SQL编程之触发器
8.1 触发器类型 8.1.1 DML触发器 8.1.2 替代触发器 8.1.3 系统触发器 8.2 创建触发器 8.2.1 触发器触发次序 8.2.2 创建DML触发器 8.2.3 创建替代(INS ...
- [推荐]ORACLE PL/SQL编程之五:异常错误处理(知已知彼、百战不殆)
原文:[推荐]ORACLE PL/SQL编程之五:异常错误处理(知已知彼.百战不殆) [推荐]ORACLE PL/SQL编程之五: 异常错误处理(知已知彼.百战不殆) 继上三篇:ORACLE PL/S ...
- Oracle PL/SQL中异常高级特性
在OraclePL/SQL语句块中exception的异常处理部分是非常重要的组成部分,它决定了在PL/SQL语句块内部可执行部分在发生异常错误时,程序是友好地提示:程序遇到某些错误而无法执行,还是抛 ...
- oracle学习笔记(十六) PL/SQL 异常和goto语句
PL/SQL 异常和goto语句 异常 预定义异常 oracle常见预定义异常: 错误号 异常错误信息名称 说明 ORA-0001 DUP_VAL_ON_INDEX 试图破坏一个唯一性限制 ORA-0 ...
- ORACLE PL/SQL编程详解
ORACLE PL/SQL编程详解 编程详解 SQL语言只是访问.操作数据库的语言,并不是一种具有流程控制的程序设计语言,而只有程序设计语言才能用于应用软件的开发.PL /SQL是一种高级数据库程序设 ...
随机推荐
- Redis,Memcache比较
简单比较: Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储.memcache只支持简单的K/V类型数据, 不过memcache可以缓存其他东西如图片, ...
- Latex: 使 tabular 居中
参考: How to center the table in Latex Latex: 使 tabular 居中 解决方法1: { \centering \begin{tabular} ... \en ...
- 4、iptables扩展匹配及网络防火墙功能
关于centos7 firewalld http://www.ibm.com/developerworks/cn/linux/1507_caojh/index.html 如何保存及重载规则: ...
- Leetcode121-Best Time to Buy and Sell Stock I - Easy
I Say you have an array for which the ith element is the price of a given stock on day i. If you wer ...
- CentOS6.5下搭建Samba服务实现与Windows系统之间共享文件资源
FTP文件传输服务确实可以让主机之间的文件传输变得简单方便,但是FTP协议的本质是传输文件,而非共享文件,因此要想通过客户端直接在服务器上修改文件内容还是一件比较麻烦的事情. 1987年,微软公司和英 ...
- 排序——选择排序(java描述)
百度百科的描述如下:选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后,再从剩余未排序元 ...
- Activity回传值报错:Failure delivering result ResultInfo{who=null,request=7,result = 0,data=null}
Activity A -----值-------> Activity B -----值-----> Activity A 场景:当A跳转到B,再从B直接点击返回按 ...
- 力扣(LeetCode)13. 罗马数字转整数
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 罗马数字 2 写做 II ,即为两个并 ...
- 由table理解display:table-cell
转载自:https://segmentfault.com/a/1190000007007885 table标签(display:table) 1) table可设置宽高.margin.border.p ...
- Python编码简要说明
●python2默认编码:ASCII编码 达到正确显示,程序需要编码转换: UTF-8 -- >decode解码 --> Unicode Unicode -- > encode编码 ...