一:编写
定义:
CREATE [OR REPLACE]PROCEDURE procedure_name
[(argument_name [IN | OUT | IN OUT] argument_type)]
AS | IS
BEGIN
procedure_body;
END [procedure_name];
--小事例
--例:定义一个过程,以JOB为参数,查询该JOB的最高工资、最低工资、平均工资。
CREATE OR REPLACE PROCEDURE display_sal(v_job emp.job%TYPE) --该形参缺省为in类型,数据类型为emp.job%TYPE
v_avg_sal emp.sal%TYPE;
v_max_sal emp.sal%TYPE;
v_min_sal emp.sal%TYPE;
BEGIN
SELECT avg(sal) INTO v_avg_sal FROM emp WHERE job=v_job;
SELECT max(sal) INTO v_max_sal FROM emp WHERE Job=v_job;
SELECT min(sal) INTO v_min_sal FROM emp WHERE job=v_job;
DBMS_OUTPUT.PUT_LINE('DEPT '||v_job||' avg sal:'||v_avg_sal);
DBMS_OUTPUT.PUT_LINE('DEPT '||v_job||' max sal:'||v_max_sal);
DBMS_OUTPUT.PUT_LINE('DEPT '||v_job||' min sal:'||v_min_sal);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NOT FOUND RECORD!');
END display_sal;
scott@ORCL> set serveroutput on;
scott@ORCL> exec display_sal('SALESMAN');
DEPT SALESMAN avg sal:1400
DEPT SALESMAN max sal:1600
DEPT SALESMAN min sal:1250
PL/SQL procedure successfully completed.
--无参数
CREATE OR REPLACE PROCEDURE display_systime
BEGIN
DBMS_OUTPUT.PUT_LINE('CURRENT TIME IS '||sysdate);
END display_systime;
execute display_systime; --调用
--in参数
--例:定义一个添加记录的过程(全部为输入参数)
CREATE OR REPLACE PROCEDURE add_emp
v_no IN emp.empno%TYPE,
v_name IN emp.ename%TYPE,
v_dept IN emp.deptno%TYPE default 20 --此过程中指定了缺省的输入值,即部门号为
BEGIN
INSERT INTO emp (empno,ename,deptno) VALUES (v_no,v_name,v_dept);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
DBMS_OUTPUT.PUT_LINE('Record Is Exist!');
END add_emp;
execute add_emp(8000,'TEST2',20); --调用
--out参数
--例:定义一个输入员工编号,修改记录,再返回修改后的结果(姓名和工资)。
CREATE OR REPLACE PROCEDURE ed_emp
v_no IN emp.empno%TYPE, --定义了一个in类型,二个out类型的参数
v_name OUT emp.ename%TYPE,
v_sal OUT emp.sal%TYPE
BEGIN
UPDATE emp SET sal=sal+100 WHERE empno=v_no;
SELECT ename,sal INTO v_name,v_sal FROM emp WHERE empno=v_no;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NOT FOUND RECORD!');
END ed_emp;
scott@ORCL> VARIABLE t_name varchar2(20);
scott@ORCL> VARIABLE t_sal number;
scott@ORCL> call ed_emp(7788,:t_name,:t_sal);
Call completed.
scott@ORCL> print t_name t_sal;
T_NAME
--------------------------------
SCOTT
T_SAL
----------
3100
--in out参数
--例:IN OUT类型参数的使用
CREATE OR REPLACE PROCEDURE comp
(num1 IN OUT NUMBER,num2 IN OUT NUMBER)
v1 NUMBER;
v2 NUMBER;
BEGIN
v1:=num1+num2;
v2:=num1*num2;
num1:=v1;
num2:=v2;
scott@ORCL> var n1 number;
scott@ORCL> var n2 number;
scott@ORCL> exec :n1:=5;
scott@ORCL> exec :n2:=3;
scott@ORCL> exec comp(:n1,:n2);
scott@ORCL> print n1 n2;
----------
----------
15
存储过程参数的传递方式:
按位置传递:
实参按顺序将值传给形参
EXECUTE
ED_EMP
(
7900
,:
t_name
,:
t_sal
);
EXECUTE
ED_EMP
(
8000
,
'TEST2'
,
20
);
按名字传递
EXECUTE
ED_EMP
(
v_name
=>
'ABCDE'
,
v_dept
=>
10
,
v_no
=>
8003
);
混合传递
EXECUTE
ED_EMP
(
8005
,
v_dept
=>
20
,
v_name
=>
'TEST5'
);
二:创建方式
同函数的创建方式,将http://fuwenchao.blog.51cto.com/6008712/1363860
三:调用
1:EXECUTE
|
CALL procedure_name [(argument_list)]
四:查看
查看系统过程信息
DBA_OBJECTS
DBA_PROCEDURES
DBA_SOURCE
USER_SOURCE, ALL_SOURCE, DBA_SOURCE, USER_ERRORS,
ALL_PROCEDURES,USER_OBJECTS,ALL_OBJECTS,DBA_OBJECTS
--
使用desc procedure_name 查看存储过程的参数信息
scott@ORCL>desc ed_emp;
PROCEDURE ed_emp
Argument NameTypeIn/Out Default?
------------------------------ ----------------------- ------ --------
V_NO NUMBER(4)IN
V_NAME VARCHAR2(10) OUT
V_SAL NUMBER(7,2) OUT
--
从dba_objects获得存储过程的信息
idle>select owner,object_name,object_type,status from dba_objects whereobject_name='ED_EMP';
OWNER OBJECT_NAME OBJECT_TYPE STATUS
------------------------------ -------------------- --------------- -------
SCOTT ED_EMP PROCEDURE VALID
scott@ORCL>selectobject_name,procedure_name,interface,authid from user_procedures;
OBJECT_NAME PROCEDURE_NAME INT AUTHID
-------------------- ------------------------------ --- ------------
DISPLAY_SAL NO DEFINER
ED_EMP NO DEFINER
--
查看存储过程的源代码
scott@ORCL>select line,textfrom user_source wherename='ED_EMP';
LINE TEXT
---------- --------------------------------------------------------------------------------
1 PROCEDURE ed_emp
2 (
3 v_no IN emp.empno%TYPE,
4 v_name OUT emp.ename%TYPE,
5 v_sal OUT emp.sal%TYPE
6 )
7 AS
8 BEGIN
9 UPDATE emp SET sal=sal+100 WHERE empno=v_no;
10 SELECT ename,sal INTO v_name,v_sal FROM emp WHERE empno=v_no;
11 EXCEPTION
12 WHEN NO_DATA_FOUND THEN
13 DBMS_OUTPUT.PUT_LINE('NOT FOUND RECORD!');
14 END ed_emp;
--
查看错误信息
SHOW ERRORS
scott@ORCL>CREATEORREPLACEPROCEDURE comp
2 (num1 IN OUT NUMBER,num2 IN OUT NUMBER)
3 AS
4 v1 NUMBER;
5 v2 NUMMBER;
6 BEGIN
7 v1:=num1+num2;
8 v2:=num1*num2;
9 num1:=v1;
10 num2:=v2;
11 END;
12 /
Warning:Procedure created with compilation errors.
scott@ORCL> show errors;
Errors forPROCEDURE COMP:
LINE/COL ERROR
-------- -----------------------------------------------------------------
5/4 PL/SQL: Item ignored
5/4 PLS-00201: identifier 'NUMMBER' must be declared
8/3 PL/SQL: Statement ignored
8/3 PLS-00320: the declaration of the typeof this expression is
incomplete or malformed
10/3 PL/SQL: Statement ignored
10/9 PLS-00320: the declaration of the typeof this expression is
incomplete or malformed
五:授权
CREATE
ANY
PROCEDURE
DROP
ANY
PROCEDURE
GRANT system_privilege | role
TO user | role | PUBLIC [WITH ADMIN OPTION]
GRANT object_privilege | ALL ON schema.object
TO user | role | PUBLIC [WITH GRANT OPTION]
--例子:
CREATE OR REPLACE PUBLIC SYNONYM dbms_job FOR dbms_job
GRANT EXECUTE ON dbms_job TO PUBLIC WITH GRANT OPTION
六:删除
删除过程;DROPPROCEDURE procedure_name
scott@ORCL>dropprocedure comp;
Procedure dropped.
七:开发过程
开发存储过程、函数、包及触发器的步骤如下:
1
使用文字编辑处理软件编辑存储过程源码
使用文字编辑处理软件编辑存储过程源码,要用类似
WORD
文字处理软件进行编辑时,要将源码存为文本格式。
2
在
SQLPLUS
或用调试工具将存储过程程序进行解释
在
SQLPLUS
或用调试工具将存储过程程序进行解释;
在
SQL>
下调试,可用
START
或
GET
等
ORACLE
命令来启动解释。如:
SQL>START c:\stat1.sql
如果使用调式工具,可直接编辑和点击相应的按钮即可生成存储过程。
3
调试源码直到正确
我们不能保证所写的存储过程达到一次就正确。所以这里的调式是每个程序员必须进行的工作之一。在
SQLPLUS
下来调式主要用的方法是:
l
使用
SHOW ERROR
命令来提示源码的错误位置;
l
使用
user_errors
数据字典来查看各存储过程的错误位置。
--
如果使用PL/SQL Developer 或者TOAD 工具的话,调试还是很方便的。 如果是在Sqlplus里,我们可以使用:
SQL>show errors
来查看错误。不过在开发中估计也很少有人直接使用sqlplus来写存储过程。 效率低,调试又麻烦。 还是使用工具方便点。我一直使用的是Toad的。
如果想在某处退出存储过程,直接使用Return;就可以了。 与存储过程编写相关的数组和游标, 这两块说起来还是有很多东西。 在上面的示例中,也简单的举了几个有关游标与存储过程编写的例子。
总之,写代码都是都是费脑子的事,相比之下还是做管理DBA舒服点,虽然压力大很多,至少不用这么费心思去整理业务逻辑。
4
授权执行权给相关的用户或角色
如果调式正确的存储过程没有进行授权,那就只有建立者本人才可以运行。所以作为应用系统的一部分的存储过程也必须进行授权才能达到要求。在
SQL*PLUS
下可以用
GRANT
命令来进行存储过程的运行授权。
八:过程和函数比较
Oracle
存储过程
定义
和
优点
与
函数
区别
http://blog.csdn.net/tianlesoftware/archive/2010/01/27/5261364.aspx
Oracle
查看
表
存储过程
触发器
函数
等对象定义语句的方法
http://blog.csdn.net/tianlesoftware/archive/2010/06/19/5679293.aspx
使用过程与函数具有如下优点:
1
、共同使用的代码可以只需要被编写和测试一次,而被需要该代码的任何应用程序(如:
.NET
、
C++
、
JAVA
、
VB
程序,也可以是
DLL
库)调用。
2
、这种集中编写、集中维护更新、大家共享(或重用)的方法,简化了应用程序的开发和维护,提高了效率与性能。
3
、这种模块化的方法,使得可以将一个复杂的问题、大的程序逐步简化成几个简单的、小的程序部分,进行分别编写、调试。因此使程序的结构清晰、简单,也容易实现。
4
、可以在各个开发者之间提供处理数据、控制流程、提示信息等方面的一致性。
5
、节省内存空间。它们以一种压缩的形式被存储在外存中,当被调用时才被放入内存进行处理。并且,如果多个用户要执行相同的过程或函数时,就只需要在内存中加载一个该过程或函数。
6
、提高数据的安全性与完整性。通过把一些对数据的操作放到过程或函数中,就可以通过是否授予用户有执行该过程或的权限,来限制某些用户对数据进行这些操作。
过程与函数的相同功能有:
1、
都使用
IN
模式的参数传入数据、
OUT
模式的参数返回数据。
2、
输入参数都可以接受默认值,都可以传值或传引导。
3、
调用时的实际参数都可以使用位置表示法、名称表示法或组合方法。
4、
都有声明部分、执行部分和异常处理部分。
5、
其管理过程都有创建、编译、授权、删除、显示依赖关系等。
使用过程与函数的原则:
1
、如果需要返回多个值和不返回值,就使用过程;如果只需要返回一个值,就使用函数。
2
、过程一般用于执行一个指定的动作,函数一般用于计算和返回一个值。
3
、可以
SQL
语句内部(如表达式)调用函数来完成复杂的计算问题,但不能调用过程。所以这是函数的特色。
参考:
http://blog.csdn.net/tianlesoftware/article/details/6147230