PLSQL: 存储过程,用户自定义函数[oracle]

注意: raise notice是高斯的输出语句; DBMS_OUT_PUT.PUT_LINE是oracle的输出语句

存储过程 Stored Procedure

存储过程可以封装数据访问逻辑,使得应用程序可以通过调用存储过程来执行这些逻辑,而不是直接执行SQL语句。这有助于提高代码的可重用性、可维护性和安全性

命名规范

使用下划线分隔单词

使用前缀 sp_或 p_等

可读性: 使用有意义的名称

语法: 创建存储过程

复制代码
CREATE OR REPLACE PROCEDURE procedure_name [pramaters]
IS/AS  
    -- 变量声明
BEGIN
    -- 存储过程的主体
    -- 可以包含SQL语句和PL/SQL代码
exception
    --异常处理
END procedure_name;

CREATE OR REPLACE:创建或者替换,当存储过程修改的时候,编译后会覆盖掉原来的同名的存储过程

参数:

参数类型不需要写长度,参数名不要和存储过程当中定义的变量重名

IN:从外边(调用存储过程的地方)把值传到存储过程内部,默认的参数类型

in\] 参数名 参数类型 命名规范:p_(或者i_)开头 在存储过程中,对 IN 类型参数的值进行修改,新修改的值 只在存储过程内部有效 OUT:把存储过程当中计算(获取)到的值传到外边(调用存储过程的地方) OUT 参数名 参数类型 命名规范:o_ 开头 INOUT:可以通过 INOUT 参数把 值传到 存储过程中,也可以把值从存储过程传出来,不常使用 INOUT 参数名 参数类型 ![](https://i-blog.csdnimg.cn/direct/113c26a6b7fa4f02bdf70c40664de441.png) -- 存储过程在创建的时候,只是编译,不会执行,调用存储过程的时候才会执行 -- 调用存储过程,从数据库中将存储过程调用出来,并且会执行里面的代码 -- 无参存储过程 -- 案例1:编写存储过程,获取员工编号为7788的员工的姓名和工资,并打印出来 CREATE OR REPLACE PROCEDURE sp_output_emp IS DECLARE v_ename emp.ename%TYPE; v_sal emp.sal%TYPE; BEGIN SELECT ename, sal INTO v_ename, v_sal FROM emp WHERE empno=7788; RAISE NOTICE '7788的姓名是:%,工资是:%', v_ename, v_sal; EXCEPTION WHEN OTHERS THEN RAISE NOTICE '发生异常!'; RAISE NOTICE '异常代码:%', SQLSTATE; RAISE NOTICE '异常信息:%', SQLERRM; END; -- 简单调用 CALL sp_output_emp(); -- 调用存储过程的名字( ); CALL sp_output_emp1(5566); ![](https://i-blog.csdnimg.cn/direct/c3e4ca498c694c70b146d4fd2e55c63d.png) 有参存储过程(in) -- 案例2:对案例1进行修改,增加传入参数,查询指定传入员工编号的员工姓名和工资,并打印 CREATE OR REPLACE PROCEDURE sp_output_emp1 (i_empno int) IS DECLARE v_ename emp.ename%TYPE; v_sal emp.sal%TYPE; BEGIN SELECT ename, sal INTO v_ename, v_sal FROM emp WHERE empno=i_empno; RAISE NOTICE '7788的姓名是:%,工资是:%', v_ename, v_sal; EXCEPTION WHEN OTHERS THEN RAISE NOTICE '发生异常!'; RAISE NOTICE '异常代码:%', SQLSTATE; RAISE NOTICE '异常信息:%', SQLERRM; END; 调用存储参数: 如上和无参调用完全想同 有参存储过程(in 和 out) 例3:在案例2的基础上继续进行修改,增加传出参数,将查询出来的员工姓名和工资,向外传递 CREATE OR REPLACE PROCEDURE sp_output_emp2(IN i_empno int,OUT o_ename emp.ename%TYPE, OUT o_sal emp.sal%type) IS DECLARE v_ename emp.ename%TYPE; v_sal emp.sal%TYPE; BEGIN SELECT ename, sal INTO v_ename, v_sal FROM emp WHERE empno=i_empno; o_sal := v_sal; o_ename := v_ename; i_empno := 99666; --RAISE NOTICE '7788的姓名是:%,工资是:%', v_ename, v_sal; EXCEPTION WHEN OTHERS THEN RAISE NOTICE '发生异常!'; RAISE NOTICE '异常代码:%', SQLSTATE; RAISE NOTICE '异常信息:%', SQLERRM; END; ![](https://i-blog.csdnimg.cn/direct/46d071ad79db4605af5d2b02e2fb0085.png) 使用匿名块调用存储过程时需要输出语句的原因在于,存储过程的输出参数(OUT参数)不会自动显示其值,它们是"静默"的,即不会像函数返回值那样直接返回。因此,为了查看存储过程的执行结果,需要在调用存储过程的匿名块中使用输出语句来显示这些值。 如果 `RAISE NOTICE '7788的姓名是:%, 工资是:%', v_ename, v_sal;` 没有被注释掉,那么在使用匿名块调用存储过程时,不需要额外的输出语句来显示这些信息。因为 `RAISE NOTICE` 语句会直接将信息输出到数据库的日志或控制台。 有参存储过程(in out) CREATE OR REPLACE PROCEDURE update_value ( in out p_value NUMBER ) AS BEGIN -- 对传入的值进行操作,例如增加10 p_value := p_value + 10; END; / 调用存储过程 ![](https://i-blog.csdnimg.cn/direct/beff4bbe4c85455db4fda24c282554b2.png) 输出: 10 ![](https://i-blog.csdnimg.cn/direct/2ddb6efda2544fc286adada8b22bf765.png) 输出: 15 **注意: raise notice是高斯的输出语句; DBMS_OUT_PUT.PUT_LINE是oracle的输出语句** 有参存储过程(out) ![](https://i-blog.csdnimg.cn/direct/44b5a12b24dd4059b85966704f7ad11a.png) ### 函数function **函数的分类** ![](https://i-blog.csdnimg.cn/direct/4428ed011750437e88e5ca0a712f216c.png) ### 用户自定义函数 它允许用户根据需要定义新的操作和计算, 通常使用PL/SQL编写,可以用于执行各种任务 语法 CREATE OR REPLACE FUNCTION function_name (parameter_list) RETURN return_datatype IS/AS -- 变量声明 BEGIN -- 函数体 RETURN return_value; EXCEPTION WHEN OTHERS THEN --异常处理 END; parameter_list 的格式 : 参数类型 参数1 数据类型; 参数类型 参数2 数据类型...... 注意: oracle中自定义函数不需要declare * **function_name**:函数的名称,由用户自定义。常用函数名前缀: fun_ * **parameter_list** :函数的参数列表,参数可以有`IN`、`OUT`、`IN OUT`等模式。一般只用 in, 默认in * **return_datatype**:函数返回值的数据类型。 * **IS/AS**:开始函数体的关键字。 * **BEGIN ... END**:函数的主体,包含执行的PL/SQL代码。 ![](https://i-blog.csdnimg.cn/direct/f5919db652004afbbd16a7d38ae3a000.png) **返回值** 函数通过`RETURN`语句返回一个值。如果函数声明为返回某个数据类型,那么必须通过`RETURN`语句返回相应类型的值。 **调用方式** ![](https://i-blog.csdnimg.cn/direct/32dee97b521145e79b41d75c40a4fba3.png) ![](https://i-blog.csdnimg.cn/direct/e77496805886421fabb1b9304270f205.png) **自定义函数和存储过程的区别** 1.自定义函数性能较差, 使用场景比存储过程少 2.自定义函数必须有返回值,存储过程没有,存储过程通过out参数向外传递数据 3.自定义函数的参数一般只使用in类型, 不使用out类型 4.自定义函数可以用一个值调用, 存储过程不可以 5.自定义函数在return处结束 6.自定义函数可以在sql中调用, 存储过程不可以 示例: 根据员工编号 获取姓名 CREATE OR REPLACE FUNCTION fun_get_ename(p_empno emp.empno%type) RETURN varchar2 AS v_ename varchar(30); --员工姓名 BEGIN SELECT ename INTO v_ename FROM emp WHERE empno=p_empno; RAISE NOTICE 'v_ename:%', v_ename; RETURN v_ename; EXCEPTION WHEN OTHERS THEN RAISE NOTICE '发生异常了'; RAISE NOTICE 'SQLSTATE:%', SQLSTATE; RAISE NOTICE 'SQLERRM:%', SQLERRM; END; **输出语句** oracle : DBMS_OUTPUT.PUT_LINE, 变量使用 和字符串使用 \|\| 拼接, 注意单引号需要使用转义字符 **'** 高斯: RAISE NOTICE, 变量使用站位符%(示例是高斯输出) **函数调用示例** 1.使用PLSQL调用 DECLARE v_name varchar(30); BEGIN v_name := fun_get_ename(7788); RAISE NOTICE '7788的姓名是:%', fun_get_ename(7788); END; 2.在SQL中调用 SELECT emp.\*, fun_get_ename(empno) FROM emp; **输出语句和return** * 输出语句的作用: 在函数执行过程中向客户端发送通知消息,这对于调试和日志记录非常有用。示例输出语句的作用是将变量`v_ename`的值打印出来,以便调试和查看 * `RETURN`用于返回函数的结果,是函数调用时返回给调用者的值。 **return和out参数** return : 用于从函数中返回一个值。函数必须通过 `RETURN` 语句返回一个值,且返回值的数据类型在函数定义时指定 ![](https://i-blog.csdnimg.cn/direct/2e005e96fe404bc3a9743455c47ac34e.png) out 参数:用于从函数中返回额外的值。`OUT` 参数允许函数返回多个值 * 函数可以有多个 `OUT` 参数。 * 只能在 PL/SQL 块中调用 ![](https://i-blog.csdnimg.cn/direct/86ceb818a0d3458698dcf7ca258343ec.png) 示例 ![](https://i-blog.csdnimg.cn/direct/a81626a0357342239f6d813c9cf0d649.png) 调用示例 ![](https://i-blog.csdnimg.cn/direct/480b83514e95468a931eb6ce461d3512.png) `IF v_status THEN` 是合法的,因为 `v_status` 是一个布尔变量,`IF` 语句会根据它的值(`TRUE` 或 `FALSE`)来决定执行哪个分支 ### 管理存储过程/自定义函数 #### **修改存储过程/自定义函数** 可以直接替换现有的存储过程/自定义函数 ![](https://i-blog.csdnimg.cn/direct/c6d4f0ca1b7b44f186e5d535dd4e9de8.png) #### **查看对象** ![](https://i-blog.csdnimg.cn/direct/5257f559f1b6476d9af271f0b6b77546.png) #### **查看源代码** ![](https://i-blog.csdnimg.cn/direct/4ddf11d90f694393b51e57992f80b36b.png) ![](https://i-blog.csdnimg.cn/direct/b3ea2441a36f4defa3d9947b1206ce02.png) #### **删除存储过程/自定义函数** ![](https://i-blog.csdnimg.cn/direct/d332d92646fc4f4189d0ffead747c976.png) ![](https://i-blog.csdnimg.cn/direct/232e0475919c44869089870ce2c530fb.png) ![](https://i-blog.csdnimg.cn/direct/f1cb1e7aa5f84f77901f13ebfefdcbb5.png) 自定义函数也是 **检查依赖关系(oracle)** ![](https://i-blog.csdnimg.cn/direct/0ce5cda2336347349e00ae5eab526a4f.png) `USER_DEPENDENCIES` 视图显示了当前用户下对象的依赖关系 检查其他用户的依赖关系,可以使用 `ALL_DEPENDENCIES` 视图(可以显示对象所有者: owner) 有DBA权限,可以使用 `DBA_DEPENDENCIES` 视图检查整个数据库中的依赖关系 使用时, 'UPDATE_VALUE'替换为需要检查依赖关系的对象名称 如果查询结果为空,说明没有其他对象依赖于该存储过程。 **删除存储过程的权限** * 存储过程的所有者。 * 具有 `DROP ANY PROCEDURE` 权限的用户。 ![](https://i-blog.csdnimg.cn/direct/e413a76e6414425bafa30a518274b3ac.png) 如果返回结果不为空,这意味着当前用户具有删除任何用户创建的存储过程和函数的权限 `DROP ANY PROCEDURE` 权限主要与存储过程相关,但它也涵盖了对函数的删除权限。 因为在Oracle的权限体系中,函数(FUNCTION)和存储过程(PROCEDURE)在很多情况下被视为类似的对象,尤其是在权限管理方面。

相关推荐
明月看潮生1 小时前
青少年编程与数学 02-011 MySQL数据库应用 03课题、客户端工具
数据库·mysql·青少年编程·编程与数学
4647的码农历程1 小时前
MySQL -- 复合查询
数据库·mysql·oracle
云空5 小时前
《解锁Netlify:静态网站托管》:此文为AI自动生成
linux·服务器·网络·数据库
数据知道6 小时前
数据库:一文掌握 PostgreSQL 的各种指令(PostgreSQL指令备忘)
数据库·sql·postgresql
初学者52136 小时前
ORA-28000: the account is locked 登录被锁定
oracle
AlfredZhao8 小时前
ORACLE数据挖掘之 MSET-SPRT
oracle·ml·odm·mining
Dnui_King8 小时前
Redis 持久化机制:AOF 与 RDB 详解
数据库·redis
jay丿8 小时前
Django 发送邮件功能详解
数据库·django·sqlite
shix .8 小时前
王者荣耀道具页面爬虫(json格式数据)
数据库·爬虫·json
A__tao9 小时前
在线 SQL 转 Flask-SQLAlchemy
数据库·sql·flask