15PLSQL--函数,存储过程

1 年前 · 来自专栏 oracle

4.子程序

定义:ORACLE 提供可以把 PL/SQL 程序存储在数据库中,并可以在任何地方来运行它。这样就叫存储过程或函数。

过程和函数统称为 PL/SQL 子程序,他们是被命名的 PL/SQL 块,均存储在数据库中,并

通过输入、输出参数或输入/输出参数与其调用者交换信息。过程和函数的唯一区别是函数总向调

用者返回数据,而过程则不返回数据。


4.1 创建函数

语法:

CREATE [OR REPLACE] FUNCTION function_name

[ (argment [ { IN | IN OUT }] Type,

argment [ { IN | OUT | IN OUT } ] Type ]

[ AUTHID DEFINER | CURRENT_USER ]


RETURN return_type --RETURN 子句

{ IS | AS } <类型.变量的说明>


BEGIN

FUNCTION_body

EXCEPTION

其它语句

END;


--create or replace function function_demo 声明函数名

--[ (argment [ { IN | IN OUT }] Type,创建形参,参数只带类型,不带宽度,有IN/OUT/IN OUT/ 声明OUT 参数,在调用过程中需要设置变量;

--RETURN return_type 返回结果类型 ,通过PLSQL程序块需要通过声明变量,将函数执行值赋值给变量

--IS/AS 声明变量过程

--BEGIN 函数执行主体

--EXCEPTION

--END;


--因为函数需要返回一个值, 所以 RETURN 包含返回结果的数据类型.

--OR REPLACE 为可选. 有了它, 可以或者创建一个新函数或者替换相同名字的函数, 而不会出现冲突

--IN 参数标记表示传递给函数的值在该函数执行中不改变;调用程序向过程内传值,过程内部不能给IN参数赋值

--OUT 标记表示一个值在函数中进行计算并通过该参数传递给调用语句;由过程内向过程外传递,由外向内传递无效,调用时用变量传递。

-- IN OUT 标记表示传递给函数的值可以变化并传递给调用语句. 若省略标记, 则参数隐含为 IN。


参数类型

A、无参过程,不加括号

B、参数数据类型不能跟宽度

C、可以是带缺省值的参数

D、参数的三种类型:IN、OUT、IN OUT

a、IN参数由过程外向过程内传递,过程内部不能给IN参数赋值

b、OUT参数由过程内向过程外传递,传入的值无效

c、IN OUT内外都有效

d、过程带有OUT参数的,实参必须是一个变量


--不带参数

CREATE OR REPLACE FUNCTION FUN_TEST01

RETURN date

is v_date date;

BEGIN

SELECT SYSDATE INTO v_date FROM DUAL;

DBMS_OUTPUT.PUT_LINE('今天,你好啊世界');

RETURN v_date;

END;


--查看报错信息:show errors;


--调用函数方法

方法一:

SELECT FUN_TEST01 FROM DUAL; --类似与系统函数


方法二:

DECLARE

v_date date;

BEGIN

v_date:=FUN_TEST01();

DBMS_OUTPUT.PUT_LINE(v_date);

END;

------------------获取某部门工资之和-----------

CREATE OR REPLACE FUNCTION fun_sal(dep_id emp.deptno%TYPE,count_emp out number)

RETURN NUMBER

IS sum_sal NUMBER;

BEGIN

SELECT SUM(sal),COUNT(empno) INTO sum_sal,count_emp FROM emp WHERE deptno=dep_id;

RETURN sum_sal;

EXCEPTION

WHEN NO_DATA_FOUND THEN

DBMS_OUTPUT.PUT_LINE('查询数据不存在');

WHEN OTHERS THEN

DBMS_OUTPUT.PUT_LINE(SQLCODE||' '||SQLERRM);

END;

--调用函数方法

DECLARE

count_emp number:=0;

BEGIN

DBMS_OUTPUT.PUT_LINE(fun_sal(20,count_emp));

DBMS_OUTPUT.PUT_LINE(count_emp);

END;

---------------------获取每个部门的工资之和-----------------

CREATE OR REPLACE FUNCTION fun_sal01(dep_id NUMBER,count_emp out NUMBER)

RETURN NUMBER

IS

CURSOR sal_cur IS SELECT * FROM emp WHERE deptno=dep_id;

sum_sal number;

BEGIN

sum_sal :=0;

count_emp :=0;

FOR C IN sal_cur LOOP

count_emp :=count_emp+1;

sum_sal :=sum_sal+c.sal;

END LOOP;

RETURN sum_sal;

EXCEPTION

WHEN NO_DATA_FOUND THEN

DBMS_OUTPUT.PUT_LINE('查询部门数据不存在');

WHEN OTHERS THEN

DBMS_OUTPUT.PUT_LINE(SQLCODE||' '||SQLERRM);

END;


--调用函数方法

DECLARE

count_emp number:=0;

BEGIN

DBMS_OUTPUT.PUT_LINE(fun_sal01(&deptno,count_emp));

DBMS_OUTPUT.PUT_LINE(count_emp);

END;

4.2创建存储过程

授权:GRANT EXECUTE ON 过程名 TO 用户;

--------------编辑一个过程函数,调用a,b的值-----------------------

CREATE OR REPLACE PROCEDURE swap_demo(a in out number,b in out number)

IS

c number:=0;

BEGIN

c:=a;

a:=b;

b:=c;

--DBMS_OUTPUT.PUT_LINE(a ||' '||b);

END;

--

DECLARE

a number :=&a;

b number :=&b;

BEGIN

dbms_output.put_line(a||' '||b);

swap_demo(a,b);

dbms_output.put_line(a||' '||b);

END;

------------------编写一个计算器的存储过程-----------------------------

CREATE OR REPLACE PROCEDURE calculate(a number,b number ,op char)

AS

result VARCHAR2(10);

BEGIN

result:=

CASE op

WHEN '+' THEN TO_CHAR(a+b)

WHEN '-' THEN TO_CHAR(a-b)

WHEN '*' THEN TO_CHAR(a*b)

WHEN '/' THEN TO_CHAR(a/b,'0.99')

ELSE '?'

END;

IF result = '?' THEN

DBMS_OUTPUT.PUT_LINE('计算器功能不符合');

ELSE

DBMS_OUTPUT.PUT_LINE(a||' '||op||' '||b||' = '||result);

END IF;

/*IF result='?' THEN

DBMS_OUTPUT.PUT_LINE('运算符无效!');

ELSE

DBMS_OUTPUT.PUT_LINE(a|| ' ' || op || ' ' || b ||' = ' || result);

END IF;*/

EXCEPTION

WHEN ZERO_DIVIDE THEN

DBMS_OUTPUT.PUT_LINE('除数不能为0');

END;



----------------体验 IN ,OUT,IN OUT 参数区别--------------------------------------

CREATe OR REPLACE PROCEDURE test(a in NUMBER,b OUT NUMBER, c IN OUT NUMBER)

IS

BEGIN

DBMS_OUTPUT.PUT_LINE('初始值:'||a||','||b||','||c);

b:=10;

c:=20;

DBMS_OUTPUT.PUT_LINE('改变后的值:'||a||','||b||','||c);

END;


--调用存储

DECLARE

A NUMBER:=50;

B NUMBER:=100;

C NUMBER:=200;

BEGIN

--调用过程前:

DBMS_OUTPUT.PUT_LINE('调用前:'||A||','||B||','||C);

test(A,B,C);

DBMS_OUTPUT.PUT_LINE('调用后:'||A||','||B||','||C);

END;

发布于 2021-12-25 22:04

文章被以下专栏收录

    oracle

    oracle

    在这里记录我的oracle学习记录