存储过程:
存储过程是事先经过编译并存储在数据库中的一段SQL语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的。
- 优点
-
- 运行速度:对于很简单的sql,存储过程没有什么优势。对于复杂的业务逻辑,因为在存储过程创建的时候,数据库已经对其进行了一次解析和优化。存储过程一旦执行,在内存中就会保留一份这个存储过程,这样下次再执行同样的存储过程时,可以从内存中直接调用,所以执行速度会比普通sql快。
-
- 减少网络传输:存储过程直接就在数据库服务器上跑,所有的数据访问都在数据库服务器内部进行,不需要传输数据到其它服务器,所以会减少一定的网络传输。但是在存储过程中没有多次数据交互,那么实际上网络传输量和直接sql是一样的。而且我们的应用服务器通常与数据库是在同一内网,大数据的访问的瓶颈会是硬盘的速度,而不是网速。
-
- 可维护性:的存储过程有些时候比程序更容易维护,这是因为可以实时更新DB端的存储过程。 有些bug,直接改存储过程里的业务逻辑,就搞定了。
-
- 增强安全性:提高代码安全,防止 SQL注入。这一点sql语句也可以做到。
-
- 可扩展性:应用程序和数据库操作分开,独立进行,而不是相互在一起。方便以后的扩展和DBA维护优化。
- 缺点
-
- SQL本身是一种结构化查询语言,但不是面向对象的的,本质上还是过程化的语言,面对复杂的业务逻辑,过程化的处理会很吃力。同时SQL擅长的是数据查询而非业务逻辑的处理,如果如果把业务逻辑全放在存储过程里面,违背了这一原则。
-
- 如果需要对输入存储过程的参数进行更改,或者要更改由其返回的数据,则您仍需要更新程序集中的代码以添加参数、更新调用,等等,这时候估计会比较繁琐了。
-
- 开发调试复杂,由于IDE的问题,存储过程的开发调试要比一般程序困难。
-
- 没办法应用缓存。虽然有全局临时表之类的方法可以做缓存,但同样加重了数据库的负担。如果缓存并发严重,经常要加锁,那效率实在堪忧。
-
- 不支持群集,数据库服务器无法水平扩展,或者数据库的切割(水平或垂直切割)。数据库切割之后,存储过程并不清楚数据存储在哪个数据库中。
简单的来说:
存储过程:就是一块PLSQL语句包装起来,起个名称
语法上:相当于plsql语句戴个帽子(记着:不是绿帽子哦)。
相对而言:单纯plsql可以认为是匿名程序。
提示:
- plsql是存储过程的基础。
- java是不能直接调用plsql的,但可以通过存储过程这些对象来调用。
语法:
create or replace procedure 名字(参数列表)
as/is --as与is都一样
begin
PLSQL子程序体
end 名字;
根据参数的类型,我们将其分为3类讲解:
- 不带参数的
- 带输入参数的
- 带输入输出参数的。
无参存储:
示例:
create or replace procedure p_hello--没有参数的情况下,不要加()
IS
BEGIN --plsql程序
dbms_output.put_line('hello world');
end p_hello;
调用方法:
如何调用执行,两种方法:
- 一种是是用exec(execute)命令来调用—用来测试存储
- 一种是用其他的程序(plsql)来调用
注意:
第一个问题:is和as是可以互用的,用哪个都没关系的
第二个问题:存储过程中没有declare关键字,declare用在语句块中
存储可以带参数可以不带参数?其实都有应用.
不带参数的存储一般用来处理内部数据的。不需要输入参数也不需要结果的,是可以使用。
带输入参数in:
示例:
--查询并打印某个员工(如7839号员工)的姓名和薪水--存储过程:要求,调用的时候传入员工编号,自动控制台打印。
create or replace procedure p_queryempsal(i_empno IN emp.empno%TYPE)--i_empno输入参数的名字,IN代表是输入值的参数,
IS
--声明变量
v_ename emp.ename%TYPE;
v_sal emp.sal%TYPE;
BEGIN
--赋值
SELECT ename ,sal INTO v_ename,v_sal FROM emp WHERE empno= i_empno;
--打印
dbms_output.put_line('姓名:'||v_ename||',薪水:'||v_sal);
end p_queryempsal;
带输入in和输出参数out—主要是其他程序用的:
示例:
----输入员工号查询某个员工(7839号(老大)员工)信息,要求,将薪水作为返回值输出,给调用的程序使用。
CREATE OR REPLACE PROCEDURE p_queryempsal_out( i_empno IN emp.empno%TYPE,o_sal OUT emp.sal%TYPE)
AS
BEGIN
--赋值:将薪水的值赋给输出的参数o_sal
SELECT sal INTO o_sal FROM emp WHERE empno=i_empno;
END;
调用(使用plsql程序调用):
DECLARE
--输入参数值
v_empno emp.empno%TYPE:=7839;
--声明一个变量来接收输出参数
v_sal emp.sal%TYPE;
BEGIN
p_queryempsal_out(v_empno,v_sal);--第二个参数是输出的参数,必须有变量来接收!!
--当上面的语句执行之后,v_sal就有值了。
dbms_output.put_line('员工编号为:'||v_empno||'的薪资为:'||v_sal);
END;
/
注意:调用的时候,参数要与定义的参数的顺序和类型一致.
小结:
存储过程作用:主要用来执行一段程序。
- 在开发程序中,为了一个特定的业务功能,会向数据库进行多次连接关闭(连接和关闭是很耗费资源)。这种就需要对数据库进行多次I/O读写,性能比较低。如果把这些业务放到PLSQL中,在应用程序中只需要调用PLSQL就可以做到连接关闭一次数据库就可以实现我们的业务,可以大大提高效率.
- ORACLE官方给的建议:能够让数据库操作的不要放在程序中。在数据库中实现基本上不会出现错误,在程序中操作可以会存在错误.(如果在数据库中操作数据,可以有一定的日志恢复等功能.)
三种存储
- 无参参数:
- 只要用来做数据处理的。存储内部写一些处理数据的逻辑。
- 带输入参数:
- 数据处理时,可以针对输入参数的值来进行判断处理。
- 带输入输出参数:
- 一般用来传入一个参数值,我想经过数据库复杂逻辑处理后,得到我想要的值然后输出给我。