注意:在SQL*Plus中输入存储过程,按“执行”按钮是进行编译,不是执行存储过程。 如果在存储过程中引用了其他用户的对象,比如表,则必须有其他用户授予的对象访问权限。一个存储过程一旦编译成功,就可以由其他用户或程序来引用。但存储过程或函数的所有者必须授予其他用户执行该过程的权限。
存储过程没有参数,在调用时,直接写过程名即可。 【训练2】 在PL/SQL程序中调用存储过程。 步骤1:登录SCOTT账户。
步骤2:授权STUDENT账户使用该存储过程,即在SQL*Plus输入区中,输入以下的命令: Sql代码
GRANT EXECUTE ON EMP_COUNT TO STUDENT GRANT EXECUTE ON EMP_COUNT TO STUDENT Sql代码 授权成功。 授权成功。
步骤3:登录STUDENT账户,在SQL*Plus输入区中输入以下程序: Sql代码
SET SERVEROUTPUT ON BEGIN
SCOTT.EMP_COUNT; END;
SET SERVEROUTPUT ON BEGIN
SCOTT.EMP_COUNT; END;
步骤4:执行以上程序,结果为: Sql代码
雇员总人数为:14
PL/SQL 过程已成功完成。 雇员总人数为:14
PL/SQL 过程已成功完成。
说明:在本例中,存储过程是由SCOTT账户创建的,STUDEN账户获得SCOTT账户的授权后,才能调用该存储过程。
注意:在程序中调用存储过程,使用了第二种语法。
【训练3】 编写显示雇员信息的存储过程EMP_LIST,并引用EMP_COUNT存储过程。 步骤1:在SQL*Plus输入区中输入并编译以下存储过程: Sql代码
CREATE OR REPLACE PROCEDURE EMP_LIST AS
CURSOR emp_cursor IS SELECT empno,ename from emp; BEGIN
FOR Emp_record IN emp_cursor LOOP
DBMS_OUTPUT.PUT_LINE(Emp_record.empno||Emp_record.ename); END LOOP; EMP_COUNT; END;
CREATE OR REPLACE PROCEDURE EMP_LIST AS
CURSOR emp_cursor IS SELECT empno,ename from emp; BEGIN
FOR Emp_record IN emp_cursor LOOP
DBMS_OUTPUT.PUT_LINE(Emp_record.empno||Emp_record.ename); END LOOP; EMP_COUNT; END; 执行结果: Sql代码 过程已创建。 过程已创建。
步骤2:调用存储过程,在输入区中输入以下语句并执行: Sql代码
EXECUTE EMP_LIST EXECUTE EMP_LIST 显示结果为: Sql代码 7369SMITH 7499ALLEN 7521WARD 7566JONES 执行结果: 雇员总人数为:14
PL/SQL 过程已成功完成。 7369SMITH 7499ALLEN 7521WARD 7566JONES 执行结果: 雇员总人数为:14
PL/SQL 过程已成功完成。
说明:以上的EMP_LIST存储过程中定义并使用了游标,用来循环显示所有雇员的信息。然后调用已经成功编译的存储过程EMP_COUNT,用来附加显示雇员总人数。通过EXECUTE命令来执行EMP_LIST存储过程。
【练习1】编写显示部门信息的存储过程DEPT_LIST,要求统计出部门个数。 参数传递
参数的作用是向存储过程传递数据,或从存储过程获得返回结果。正确的使用参数可以大大增加存储过程的灵活性和通用性。 参数的类型有三种,如下所示。 Sql代码
IN 定义一个输入参数变量,用于传递参数给存储过程 OUT 定义一个输出参数变量,用于从存储过程获取数据 IN OUT 定义一个输入、输出参数变量,兹有以上两者的功能 IN 定义一个输入参数变量,用于传递参数给存储过程 OUT 定义一个输出参数变量,用于从存储过程获取数据 IN OUT 定义一个输入、输出参数变量,兹有以上两者的功能 参数的定义形式和作用如下:
参数名 IN 数据类型 DEFAULT 值;
定 义一个输入参数变量,用于传递参数给存储过程。在调用存储过程时,主程序的实际参数可以是常量、有值变量或表达式等。DEFAULT 关键字为可选项,用来设定参数的默认值。如果在调用存储过程时不指明参数,则参数变量取默认值。在存储过程中,输入变量接收主程序传递的值,但不能对其进 行赋值。 参数名 OUT 数据类型;
定义一个输出参数变量,用于从存储过程获取数据,即变量从存储过程中返回值给主程序。 在调用存储过程时,主程序的实际参数只能是一个变量,而不能是常量或表达式。在存储过程中,参数变量只能被赋值而不能将其用于赋值,在存储过程中必须给输出变量至少赋值一次。
参数名 IN OUT 数据类型 DEFAULT 值;
定 义一个输入、输出参数变量,兹有以上两者的功能。在调用存储过程时,主程序的实际参
数只能是一个变量,而不能是常量或表达式。DEFAULT 关键字为可选项,用来设定参数的默认值。在存储过程中,变量接收主程序传递的值,同时可以参加赋值运算,也可以对其进行赋值。在存储过程中必须给变量至少 赋值一次。 如果省略IN、OUT或IN OUT,则默认模式是IN。
【训练1】 编写给雇员增加工资的存储过程CHANGE_SALARY,通过IN类型的参数传递要增加工资的雇员编号和增加的工资额。 步骤1:登录SCOTT账户。
步骤2:在SQL*Plus输入区中输入以下存储过程并执行: Sql代码
CREATE OR REPLACE PROCEDURE CHANGE_SALARY(P_EMPNO IN NUMBER DEFAULT 7788,P_RAISE NUMBER DEFAULT 10) AS
V_ENAME VARCHAR2(10); V_SAL NUMBER(5); BEGIN
SELECT ENAME,SAL INTO V_ENAME,V_SAL from EMP WHERE EMPNO=P_EMPNO;
UPDATE EMP SET SAL=SAL+P_RAISE WHERE EMPNO=P_EMPNO; DBMS_OUTPUT.PUT_LINE('雇员'||V_ENAME||'的工资被改为'||TO_CHAR(V_SAL+P_RAISE)); COMMIT; EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('发生错误,修改失败!'); ROLLBACK; END;
CREATE OR REPLACE PROCEDURE CHANGE_SALARY(P_EMPNO IN NUMBER DEFAULT 7788,P_RAISE NUMBER DEFAULT 10) AS
V_ENAME VARCHAR2(10); V_SAL NUMBER(5); BEGIN SELECT
ENAME,SAL
INTO
V_ENAME,V_SAL
from
EMP
WHERE
EMPNO=P_EMPNO;
UPDATE EMP SET SAL=SAL+P_RAISE WHERE EMPNO=P_EMPNO; DBMS_OUTPUT.PUT_LINE('
雇
员
'||V_ENAME||'
的
工
资
被
改
为
'||TO_CHAR(V_SAL+P_RAISE)); COMMIT; EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('发生错误,修改失败!'); ROLLBACK; END; 执行结果为: Sql代码 过程已创建。 过程已创建。
步骤3:调用存储过程,在输入区中输入以下语句并执行: Sql代码
EXECUTE CHANGE_SALARY(7788,80) EXECUTE CHANGE_SALARY(7788,80) 显示结果为: Sql代码
雇员SCOTT的工资被改为3080 雇员SCOTT的工资被改为3080
说明:从执行结果可以看到,雇员SCOTT的工资已由原来的3000改为3080。
参数的值由调用者传递,传递的参数的个数、类型和顺序应该和定义的一致。如果顺序不一致,可以采用以下调用方法。如上例,执行语句可以改为:
EXECUTE CHANGE_SALARY(P_RAISE=>80,P_EMPNO=>7788);
可以看出传递参数的顺序发生了变化,并且明确指出了参数名和要传递的值,=>运算符左侧是参数名,右侧是参数表达式,这种赋值方法的意义较清楚。
【练习1】创建插入雇员的存储过程INSERT_EMP,并将雇员编号等作为参数。 在设计存储过程的时候,也可以为参数设定默认值,这样调用者就可以不传递或少传递参数了。
【训练2】 调用存储过程CHANGE_SALARY,不传递参数,使用默认参数值。 在SQL*Plus输入区中输入以下命令并执行: Sql代码
EXECUTE CHANGE_SALARY EXECUTE CHANGE_SALARY 显示结果为: Sql代码
雇员SCOTT的工资被改为3090