PL_SQL模块学习之十二、存储过程

存储过程

1.1 存储结构

存储过程是保存在数据库服务器上的程序单元,这些 程序单元的对数据库的重复操作很大。
结构:

CREATE OR REPLACE PROCEDURE PROTEST
IS
	声明区
BEGIN
	子程序区
ESCEPTION
	异常处理区
END PROTEST;

1.1.1 声明区

位于PROCEDUREBEGIN之间,定义变量

CREATE OR REPLACE PROCEDURE PROTEST
IS

--声明变量
	xxx number;
	yyy varchar2(20) :='oracle';
	
--声明REF变量
	type empcursor is ref cursor;
	
--异常对象
	read_disk_refused exception;
	
--内嵌函数或其他存储过程
	FUNCTION foo RETURN BOOLEAN IS
	BEGIN
	RETURN (XXX>1000)
	END IF;
	BEGIN
	......
	END;

1.1.2 子程序区

位于BEGINEND之间,至少存在一条PL/SQL语句,可以为NULL;

1.1.3 异常处理区

即处理子程序在执行中发生的异常

CREATE OR REPLACE PROCEDURE PRO(employee_age,IN number)
IS 
	age NUMBER;
	mydate DATE;
	dateexp EXCEPTION;
	BEGIN	
		mydate := 'TIME_STRING';
		age := employee_age;
		IF age >150
		THEN
			raise dateexp;#当age>150时就抛出异常
				EXCEPTION#在异常处理区EXCEPTION后进行处理
					WHEN dateexp THEN  #WHEN子句对应了异常类型
						handling dateexp;
					WHEN OTHERS THEN
						handling other exps;
	END;

1.2 示例

创建一个存储过程,用于更新SCOTT用户的EMP表中的员工薪水,低于平均工资的员工在原有基础上统一增加15%.

SQL> CREATE OR REPLACE PROCEDURE InCreSal
  2  IS
  3  avg_sal NUMBER;
  4  CURSOR var_cursor
  5  IS
  6  SELECT * FROM emp;
  7  BEGIN
  8  SELECT avg(sal) INTO avg_sal FROM emp_test;
  9  FOR var_cur IN var_cursor
 10  loop
 11  UPDATE emp_test SET sal = sal*1.15
 12  WHERE sal < avg_sal;
 13  dbms_output.put_line(var_cur.ename || 'updated');
 14  END LOOP;
 #此处若想更新到库,需添加commit;语句
 15  END;
 16  /

过程已创建。

1.3 信息和定义查询

通过数据字典user_objects查询过程名,过程状态等

SQL> select object_id,object_type,status,created from user_objects
  2  where object_name='INCRESAL';

 OBJECT_ID OBJECT_TYPE         STATUS          CREATED
---------- ------------------- --------------- --------------
     73526 PROCEDURE           VALID           12-3-20

通过Oracle提供的DBMS_METADATA包的过程get_dll获得该对象的创建过程

SQL> set pagesize 1000;
SQL> set long 1000;
SQL> select dbms_metadata.get_dDl('PROCEDURE','INCRESAL')FROM DUAL;
#使用DBMS_METADATA获得过程InCreSal定义
DBMS_METADATA.GET_DDL('PROCEDURE','INCRESAL')
--------------------------------------------------------------------------------

  CREATE OR REPLACE PROCEDURE "SCOTT"."INCRESAL"
IS
avg_sal NUMBER;
CURSOR var_cursor
IS
SELECT * FROM emp;
BEGIN
SELECT avg(sal) INTO avg_sal FROM emp_test;
FOR var_cur IN var_cursor
loop
UPDATE emp_test SET sal = sal*1.15
WHERE sal < avg_sal;
dbms_output.put_line(var_cur.ename || 'updated');
END LOOP;
END;

通过数据字典user_source获得对象定义

SQL> desc user_source;
 名称                                                              是否为空? 类型
 ----------------------------------------------------------------- -------- --------------------------------------------
 NAME                                                                       VARCHAR2(30)
 TYPE              #包括表,触发器,存储过程等                                                         VARCHAR2(12)
 LINE                                                                       NUMBER
 TEXT              #存储对象的大文本定义                                                       VARCHAR2(4000)

SQL> select text from user_source where name='INCRESAL';

TEXT
------------------------------------------------------------------------------------------------------------------------
PROCEDURE InCreSal
IS
avg_sal NUMBER;
CURSOR var_cursor
IS
SELECT * FROM emp;
BEGIN
SELECT avg(sal) INTO avg_sal FROM emp_test;
FOR var_cur IN var_cursor
loop
UPDATE emp_test SET sal = sal*1.15
WHERE sal < avg_sal;
dbms_output.put_line(var_cur.ename || 'updated');
END LOOP;
END;

已选择15行。

当删除表格emp_test使得过程无效时,如何恢复有效

SQL> drop table emp_test;

表已删除。

SQL> select object_id,object_type,status,created from user_objects
  2  where object_name='INCRESAL';

 OBJECT_ID OBJECT_TYPE         STATUS          CREATED
---------- ------------------- --------------- --------------
     73526 PROCEDURE           INVALID         12-3-20

SQL> create table emp_test as select * from emp;

表已创建。
#将表格恢复后一九无效
SQL> select object_id,object_type,status,created from user_objects
  2  where object_name='INCRESAL';

 OBJECT_ID OBJECT_TYPE         STATUS          CREATED
---------- ------------------- --------------- --------------
     73526 PROCEDURE           INVALID         12-3-20
#需要将过程重新编译
SQL> alter procedure InCreSal compile;

过程已更改。

SQL> select object_id,object_type,status,created from  user_objects
  2  where object_name='INCRESAL';

 OBJECT_ID OBJECT_TYPE         STATUS          CREATED
---------- ------------------- --------------- --------------
     73526 PROCEDURE           VALID           12-3-20

1.4 IN 和OUT 参数

使用IN和OUT参数完成数据库服务端与用户之间交互。

  • IN :给过程传值,可以是常量、字面值或表达式,该参数只读
  • OUT:给过程返回值,必须是变量,不可使用默认值,该参数只写
  • INOUT:给程序传值,同时是过程返回值,该参数只能是变量

示例:
创建过程search_name,定义输入参数为ID,经过计算返回员工名和相应工资。

SQL> list
  1  CREATE OR REPLACE PROCEDURE search_name
  2  (id IN NUMBER,name OUT varchar2,sal OUT number)
  3  AS
  4  BEGIN
  5  SELECT ename,sal INTO name,sal
  6  FROM emp
  7  WHERE empno=id;
  8  EXCEPTION
  9  WHEN OTHERS
 10  THEN
 11  dbms_output.put_line('Error!');
 12* end search_name;
SQL> /

过程已创建。

调用该过程时,需要定义实参代替输入值,通过定义和输出对应的变量来获得输出结果。

SQL> list
  1  declare
  2  name varchar2(20); #定义两个输出变量
  3  salary number(8,2);
  4  begin
  5     search_name(7844,name,salary);
  6      dbms_output.put_line('id 7844 ' || name ||' salary is '||salary);
  7* end;
SQL> /
id 7844 TURNER salary is 1500

PL/SQL 过程已成功完成。

1.5 存储过程权限

  • CREATE PROCEDURE
  • CREATE ALL PROCEDURE

通过user_sys_privs查看SCOTT用户的系统权限

SQL> select * from user_sys_privs;

USERNAME                       PRIVILEGE                                ADM
------------------------------ ---------------------------------------- ---
SCOTT                          UNLIMITED TABLESPACE                     NO
SCOTT                          CREATE TRIGGER                           NO
SCOTT                          CREATE ANY TRIGGER                       NO

在dba即sys用户通过grant create procedure to scott;授权后,SCOTT用户获得CREATE PROCEDURE权限

SQL> select * from user_sys_privs;

USERNAME                       PRIVILEGE                                ADM
------------------------------ ---------------------------------------- ---
SCOTT                          UNLIMITED TABLESPACE                     NO
SCOTT                          CREATE PROCEDURE                         NO
SCOTT                          CREATE TRIGGER                           NO
SCOTT                          CREATE ANY TRIGGER                       NO
发布了87 篇原创文章 · 获赞 23 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_32392597/article/details/104820307