雇员SCOTT的工资被改为3090
说明:在存储过程的调用中没有传递参数,而是采用了默认值7788和10,即默认雇员号为7788,增加的工资为10。
【训练3】 使用OUT类型的参数返回存储过程的结果。 步骤1:登录SCOTT账户。
步骤2:在SQL*Plus输入区中输入并编译以下存储过程: Sql代码
CREATE OR REPLACE PROCEDURE EMP_COUNT(P_TOTAL OUT NUMBER) AS BEGIN
SELECT COUNT(*) INTO P_TOTAL from EMP; END;
CREATE OR REPLACE PROCEDURE EMP_COUNT(P_TOTAL OUT NUMBER) AS BEGIN
SELECT COUNT(*) INTO P_TOTAL from EMP; END; 执行结果为: Sql代码 过程已创建。 过程已创建。
步骤3:输入以下程序并执行: Sql代码 DECLARE
V_EMPCOUNT NUMBER; BEGIN
EMP_COUNT(V_EMPCOUNT);
DBMS_OUTPUT.PUT_LINE('雇员总人数为:'||V_EMPCOUNT); END; DECLARE
V_EMPCOUNT NUMBER; BEGIN
EMP_COUNT(V_EMPCOUNT);
DBMS_OUTPUT.PUT_LINE('雇员总人数为:'||V_EMPCOUNT); END; 显示结果为:
Sql代码
雇员总人数为:14
PL/SQL 过程已成功完成。 雇员总人数为:14
PL/SQL 过程已成功完成。
说明:在存储过程中定义了OUT类型的参数P_TOTAL,在主程序调用该存储过程时,传递了参数V_EMPCOUNT。在存储过程中的SELECT...INTO...语句中对P_TOTAL进行赋值,赋值结果由V_EMPCOUNT变量带回给主程序并显示。
以上程序要覆盖同名的EMP_COUNT存储过程,如果不使用OR REPLACE选项,就会出现以下错误: Sql代码
ERROR 位于第 1 行:
ORA-00955: 名称已由现有对象使用。 ERROR 位于第 1 行:
ORA-00955: 名称已由现有对象使用。
【练习2】创建存储过程,使用OUT类型参数获得雇员经理名。 【训练4】 使用IN OUT类型的参数,给电话号码增加区码。 步骤1:登录SCOTT账户。
步骤2:在SQL*Plus输入区中输入并编译以下存储过程: Sql代码
CREATE OR REPLACE PROCEDURE ADD_REGION(P_HPONE_NUM IN OUT VARCHAR2) AS BEGIN
P_HPONE_NUM:='0755-'||P_HPONE_NUM; END;
CREATE OR REPLACE PROCEDURE ADD_REGION(P_HPONE_NUM IN OUT VARCHAR2) AS BEGIN
P_HPONE_NUM:='0755-'||P_HPONE_NUM; END; 执行结果为: Sql代码 过程已创建。 过程已创建。
步骤3:输入以下程序并执行: Sql代码
SET SERVEROUTPUT ON DECLARE
V_PHONE_NUM VARCHAR2(15); BEGIN
V_PHONE_NUM:='26731092'; ADD_REGION(V_PHONE_NUM);
DBMS_OUTPUT.PUT_LINE('新的电话号码:'||V_PHONE_NUM); END;
SET SERVEROUTPUT ON DECLARE
V_PHONE_NUM VARCHAR2(15); BEGIN
V_PHONE_NUM:='26731092'; ADD_REGION(V_PHONE_NUM);
DBMS_OUTPUT.PUT_LINE('新的电话号码:'||V_PHONE_NUM); END; 显示结果为: Sql代码
新的电话号码:0755-26731092 PL/SQL 过程已成功完成。 新的电话号码:0755-26731092 PL/SQL 过程已成功完成。
说明:变量V_HPONE_NUM既用来向存储过程传递旧电话号码,也用来向主程序返回新号码。新的号码在原来基础上增加了区号0755和-。 创建和删除存储函数
创建函数,需要有CREATE PROCEDURE或CREATE ANY PROCEDURE的系统权限。该权限可由系统管理员授予。创建存储函数的语法和创建存储过程的类似,即 CREATE [OR REPLACE] FUNCTION 函数名[(参数[IN] 数据类型...)] RETURN 数据类型 {AS|IS} [说明部分] BEGIN 可执行部分 RETURN (表达式)
[EXCEPTION 错误处理部分] END [函数名];
其中,参数是可选的,但只能是IN类型(IN关键字可以省略)。
在定义部分的RETURN 数据类型,用来表示函数的数据类型,也就是返回值的类型,此部分不可省略。
在可执行部分的RETURN(表达式),用来生成函数的返回值,其表达式的类型应该和定义部分说明的函数返回值的数据类型一致。在函数的执行部分可以有多个RETURN语句,但只有一个RETURN语句会被执行,一旦执行了RETURN语句,则函数结束并返回调用环境。 一个存储函数在不需要时可以删除,但删除的人应是函数的创建者或者是拥有DROP ANY PROCEDURE系统权限的人。其语法如下: DROP FUNCTION 函数名;
重新编译一个存储函数时,编译的人应是函数的创建者或者拥有ALTER ANY PROCEDURE系统权限的人。重新编译一个存储函数的语法如下: ALTER PROCEDURE 函数名 COMPILE;
函数的调用者应是函数的创建者或拥有EXECUTE ANY PROCEDURE系统权限的人,或是被函数的拥有者授予了函数执行权限的账户。函数的引用和存储过程不同,函数要出现在程序体中,可以参加表达式的运算或单独出现在表达式中,其形式如下: 变量名:=函数名(...)
【训练1】 创建一个通过雇员编号返回雇员名称的函数GET_EMP_NAME。 步骤1:登录SCOTT账户。
步骤2:在SQL*Plus输入区中输入以下存储函数并编译: Sql代码
CREATE OR REPLACE FUNCTION GET_EMP_NAME(P_EMPNO NUMBER DEFAULT 7788)
RETURN VARCHAR2 AS
V_ENAME VARCHAR2(10); BEGIN
ELECT ENAME INTO V_ENAME from EMP WHERE EMPNO=P_EMPNO; RETURN(V_ENAME); EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('没有该编号雇员!'); RETURN (NULL);
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('有重复雇员编号!'); RETURN (NULL); WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('发生其他错误!'); RETURN (NULL); END;
CREATE OR REPLACE FUNCTION GET_EMP_NAME(P_EMPNO NUMBER DEFAULT 7788) RETURN VARCHAR2 AS
V_ENAME VARCHAR2(10); BEGIN
ELECT ENAME INTO V_ENAME from EMP WHERE EMPNO=P_EMPNO; RETURN(V_ENAME); EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('没有该编号雇员!'); RETURN (NULL);
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('有重复雇员编号!'); RETURN (NULL); WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('发生其他错误!'); RETURN (NULL); END;
步骤3:调用该存储函数,输入并执行以下程序: Sql代码 BEGIN
DBMS_OUTPUT.PUT_LINE('雇员7369的名称是:'|| GET_EMP_NAME(7369)); DBMS_OUTPUT.PUT_LINE(''|| GET_EMP_NAME(7839)); END; BEGIN
DBMS_OUTPUT.PUT_LINE('雇员7369的名称是:'|| GET_EMP_NAME(7369)); DBMS_OUTPUT.PUT_LINE('雇员7839的名称是:'|| GET_EMP_NAME(7839)); END;
雇
员
7839
的
名
称
是
: