Oracle 存储过程使用总结
参考 https://blog.csdn.net/weixin_41968788/article/details/83659164/
创建
注意:一定不要漏掉了语句末尾的分号
- DBMS_OUTPUT.PUT_LINE() 的输出结果可在PLSQL的【输出栏】中查看
-- 创建并替换存储过程
CREATE OR REPLACE PROCEDURE simple_procedure
-- 定义参数
(
name IN VARCHAR,
birth_year IN NUMBER
)
AS
-- 声明变量
current_year NUMBER(4) := 2022;
age NUMBER(2);
remark VARCHAR(255);
BEGIN
current_year := to_number(to_char(sysdate, 'yyyy'));
age := current_year - birth_year;
remark := name || '今年' || age || '岁';
-- 条件语句
IF age < 18 THEN
remark := remark || ':未成年人';
ELSIF age < 60 THEN
remark := remark || ':青年人';
ELSE
remark := remark || ':老年人';
END IF;
DBMS_OUTPUT.PUT_LINE(remark);
-- 捕获异常
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
调用存储过程
调用存储过程的方式有两种:call 和 exec
exec是sqlplus的命令,只能在sqlplus中使用。和 set serveroutput on 一起用。
call是sql命令,任何工具都可以使用。
-- 调用存储过程
call simple_procedure();
条件语句
注意:多个条件分支时,关键词就是 elsif ,而不是 elseif
-- 1个条件分支
if ... then
...
end if;
-- 2个条件分支
if ... then
...
else
...
end if;
-- 多个条件分支
if ... then
...
elsif ... then
...
else
...
end if;
异常捕获
Oracle提供了三种异常处理方式:
- 预定义异常 用于处理常见的Oracle错误
- 非预定义异常 用于处理预定义异常所不能处理的Oracle错误
- 自定义异常 用于处理于Oracle错误无关的其他情况
语法
-- 捕获异常
EXCEPTION
WHEN EXCEPTION_NAME THEN
...
WHEN OTHERS THEN
...
预定的21种异常类型
对预定义异常情况的处理,只需在PL/SQL块的异常处理部分,直接引用相应的异常情况名,并对其完成相应的异常错误处理即可。
错误号 | 命名的系统异常 | 产生原因 |
---|---|---|
ORA-6530 | access_into_null | 试图为null 对象的属性赋值 |
case_not_found | case中若未包含相应的when,并且没有设置 | |
ORA-6531 | collection_is_null | 集合元素未初始化 |
ORA-6511 | curser_already_open | 试图打开一个已处于打开状态的游标 |
ORA-0001 | dup_val_on_index | 违反了唯一性限制 |
ORA-1001 | invalid_cursor | 试图使用一个无效的游标 |
ORA-1722 | invalid_number | 转换一个数字失败 |
ORA-1403 | no_data_found | 使用 select into 未返回行,或应用索引表未初始化的 |
ORA-1422 | too_many_rows | 执行 select into 时,结果集超过一行 |
ORA-1476 | zero_divide | 试图被零除 |
ORA-6533 | subscript_beyond_count | 元素下标超过嵌套表或varray的最大值 |
ORA-6533 | subscript_outside_limit | 使用嵌套表或 varray 时,将下标指定为负数 |
ORA-6502 | value_error | 赋值时,变量长度不足以容纳实际数据 |
ORA-1017 | login_denied | 无效的用户名/口令 |
ORA-1012 | not_logged_on | 没有连接到ORACLE |
ORA-6501 | program_error | 内部错误 |
ORA-6504 | rowtype_mismatch | 主游标变量与 pl/sql 游标变量的返回类型不兼容 |
self_is_null | 使用对象类型时,在 null 对象上调用对象方法 | |
ORA-6500 | storage_error | 内存不够引发的内部错误 |
sys_invalid_id | 无效的 rowid 字符串 | |
ORA-0051 | timeout_on_resource | 在等待资源时发生超时 |
ORA-0061 | Transaction-backed-out | 由于发生死锁事务被撤消 |
非预定义异常
使用非预定义异常包括三步:
- 在定义部分定义异常名,
- 在异常和Oracle错误之间建立关联,
- 在异常处理部分捕捉并处理异常。
当定义Oracle错误和异常之间的关联关系时,需要使用伪过程EXCEPTION_INIT。
- 首先的定义部分定义异常,
- 使用 progma exception_init(exception_name, exception_number) 在异常和oracle错误之间建立关联,这时要求用户知道可能出现的错误号(异常函数sqlcode、sqlerrm和 raise_application_error);参考oracle错误号表
- 最终在异常处理部分捕捉并处理异常。
以ORA-02291错误(违反完整约束条件 (.) - 未找到父项关键字)为例,为此先创建两张表
-- 部门表
CREATE TABLE DEPT (
dept_no VARCHAR2(5) NOT NULL,
dept_name VARCHAR2(255) NOT NULL,
PRIMARY KEY(dept_no)
);
-- 员工表
CREATE TABLE EMP (
emp_no VARCHAR2(8) NOT NULL,
emp_name VARCHAR2(20) NOT NULL,
dept_no VARCHAR2(5) NOT NULL,
PRIMARY KEY(emp_no),
FOREIGN KEY(dept_no) REFERENCES DEPT(dept_no)
);
来吧,来捕获 ORA-02291 错误
DECLARE
e_integrity EXCEPTION; -- 1、定义部分
PRAGMA EXCEPTION_INIT (e_integrity, -2291); -- 2、建立关联关系
BEGIN
INSERT INTO emp (emp_no, emp_name, dept_no) values(&empno, &empname, &deptno);
EXCEPTION
WHEN e_integrity THEN -- 3、捕捉处理
DBMS_OUTPUT.PUT_LINE('该部门不存在');
END;
再来捕获 ORA-02292: 违反完整约束条件 (.) - 已找到子记录日志
-- 首先插入两个数据
insert into DEPT(dept_no, dept_name) values ('D0001', '开发部');
insert into EMP(emp_no, emp_name, dept_no) values('E0001', '张三', 'D0001');
DECLARE
e_integrity EXCEPTION; -- 1、定义部分
PRAGMA EXCEPTION_INIT (e_integrity, -2292); -- 2、建立关联关系
BEGIN
DELETE FROM DEPT WHERE dept_no='D0001';
EXCEPTION
WHEN e_integrity THEN -- 3、捕捉处理
DBMS_OUTPUT.PUT_LINE('该部门下还有员工');
END;
自定义异常
预定义异常和非预定义异常都与Oracle错误有关,并且当出现Oracle错误时会隐含触发相应异常;
而自定义异常与Oracle错误没有任何关联,它是由开发人员为特定情况所定义的异常。
我的理解:处理非预定义异常,就是给已有的错误号起个名;自定义异常则是自定义错误号并起名。
当使用自定义异常时,
- 需要在定义部分(DECLARE)定义异常,
- 再执行部分(BEGIN)触发异常(使用RAISE语句),
- 在异常处理部分(EXCEPTION)捕捉并处理异常。
以 simple_procedure 为例
-- 创建并替换存储过程
CREATE OR REPLACE PROCEDURE simple_procedure
-- 定义参数
(
name IN VARCHAR,
birth_year IN NUMBER
)
AS
-- 声明变量
current_year NUMBER(4) := 2022;
age NUMBER(2);
remark VARCHAR(255);
-- 定义变量:错误号
V_sqlcode NUMBER;
V_sqlerr VARCHAR(512);
-- 定义异常
Null_name EXCEPTION;
Null_birth_year EXCEPTION;
Invalid_birth_year EXCEPTION;
PRAGMA EXCEPTION_INIT(Null_name,-20991);
PRAGMA EXCEPTION_INIT(Null_birth_year,-20992);
PRAGMA EXCEPTION_INIT(Invalid_birth_year, -20993);
BEGIN
IF name IS NULL THEN
RAISE_APPLICATION_ERROR(-20991, '姓名不能为空');
END IF;
IF birth_year IS NULL THEN
RAISE_APPLICATION_ERROR(-20992, '出生年份不能为空');
ELSIF birth_year < 1900 THEN
RAISE_APPLICATION_ERROR(-20993, '出生年份不能早于1900年');
END IF;
current_year := to_number(to_char(sysdate, 'yyyy'));
age := current_year - birth_year;
remark := name || '今年' || age || '岁';
-- 条件语句
IF age < 18 THEN
remark := remark || ':未成年人';
ELSIF age < 60 THEN
remark := remark || ':青年人';
ELSE
remark := remark || ':老年人';
END IF;
DBMS_OUTPUT.PUT_LINE(remark);
-- 捕获异常
EXCEPTION
WHEN Null_name THEN
V_sqlcode :=SQLCODE;
V_sqlerr :=SQLERRM;
DBMS_OUTPUT.PUT_LINE('错误号:' || V_sqlcode || ',错误信息:' || V_sqlerr);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
RAISE_APPLICATION_ERROR(errCode, errMsg); 函数的作用是抛出异常
示例
create or replace procedure P_DATABASE_USED_DISK_SPACE_RECORD AS
/******************************************************************************
* 目的:统计数据库表和索引所用磁盘空间大小
******************************************************************************/
COUNT_ NUMBER(19);
V_ERRORCODE VARCHAR2(20);
V_ERRORMESSAGE VARCHAR2(900);
V_ERRORLINE VARCHAR2(1000);
STEP NUMBER(19);
BEGIN
-- 记录数据库表所占磁盘空间大小
INSERT INTO T_DATABASE_RECORD
SELECT
SEGMENT_NAME AS OBJECT_NAME,
BYTES / 1024 / 1024/ 1024 AS DISK_SPACE,
TO_CHAR(SYSDATE,'YYYY-MM-DD') AS RECORD_DATE,
'TABLE' AS TYPE
FROM USER_SEGMENTS V
WHERE V.SEGMENT_TYPE='TABLE'
ORDER BY V.BYTES DESC;
-- 记录数据库表索引所占磁盘空间大小
INSERT INTO T_DATABASE_RECORD
SELECT
SEGMENT_NAME AS OBJECT_NAME,
SUM(BYTES) /1024/1024/1024 AS DISK_SPACE,
TO_CHAR(SYSDATE,'YYYY-MM-DD') AS RECORD_DATE,
'INDEX' AS TYPE
FROM USER_SEGMENTS
WHERE SEGMENT_TYPE ='INDEX'
GROUP BY SEGMENT_NAME;
COUNT_ := SQL%ROWCOUNT;
INSERT INTO I_JOB_LOG
SELECT INTERFACE_SEQUENCES.NEXTVAL,
'P_DATABASE_RECORD',
1, COUNT_, 'Y',
'success',
SYSDATE
FROM DUAL;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
V_ERRORCODE := SQLCODE;
V_ERRORMESSAGE := SUBSTR(SQLERRM, 1, 160);
V_ERRORLINE := DBMS_UTILITY.FORMAT_ERROR_BACKTRACE;
--记录错误信息
INSERT INTO I_JOB_LOG
SELECT INTERFACE_SEQUENCES.NEXTVAL,
'P_DATABASE_RECORD',
STEP, 0, 'N',
'失败ErrorCode' || V_ERRORCODE || 'ErrorMessage:' ||
V_ERRORMESSAGE || ' ' V_ERRORLINE,
SYSDATE
FROM DUAL;
COMMIT;
end P_DATABASE_RECORD;
Oracle 存储过程使用总结的更多相关文章
- oracle 存储过程
来自:http://www.jb51.net/article/31805.htm Oracle存储过程基本语法 存储过程 1 CREATE OR REPLACE PROCEDURE 存储过程名 2 I ...
- Oracle存储过程语法
原文链接:http://www.jb51.net/article/31805.htm Oracle存储过程基本语法 存储过程 1 CREATE OR REPLACE PROCEDURE 存储过程名 ...
- ORACLE存储过程调用Web Service
1. 概述 最近在ESB项目中,客户在各个系统之间的服务调用大多都是在oracle存储过程中进行的,本文就oracle存储过程调用web service来进行说明.其他主流数据库,比如mysql和sq ...
- Oracle存储过程基本语法介绍
Oracle存储过程基本语法 存储过程 1 CREATE OR REPLACE PROCEDURE 存储过程名 2 IS 3 BEGIN 4 NULL; 5 END; 行1: CREATE OR RE ...
- MyBatis调用Oracle存储过程
MyBatis调用Oracle存储过程 1.无输入和输出参数的存储过程 2.带有输入和输出参数的存储过程 3.返回游标的存储过程 mybatis中的配置文件代码 <resultMap type= ...
- Oracle存储过程(转)
Oracle存储过程基本语法 存储过程 1 CREATE OR REPLACE PROCEDURE 存储过程名 2 IS 3 BEGIN 4 NULL; 5 END; 行1: CREATE OR RE ...
- Oracle存储过程中异常Exception的捕捉和处理
Oracle存储过程中异常的捕捉和处理 CREATE OR REPLACE Procedure Proc_error_process ( v_IN in Varchar2, v_OUT Out Var ...
- Oracle存储过程动态创建临时表/存储过程执行权限问题--AUTHID CURRENT_USER
关于Oracle存储过程执行权限问题的解决 http://blog.sina.com.cn/s/blog_6ceed3280101hvlo.html (2014-04-02 04:06:28) 转载▼ ...
- ORACLE存储过程学习
存储过程 1 CREATE OR REPLACE PROCEDURE 存储过程名 2 IS 3 BEGIN 4 NULL; 5 END; 行1: CREATE OR REPLACE PROCEDURE ...
- C# 获取 oracle 存储过程的 返回值1
/// <summary> /// 返回对应表的模拟自增字段值 /// </summary> /// <param name="tablename"& ...
随机推荐
- 羽夏看Win系统内核——调试篇
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...
- automake的使用2
前言 如果你的入口文件main.c和依赖的文件不是在同一个目录中的,使用Autotools来管理项目的时候会稍微复杂一下. 在不同的目录下,项目会生成*.a文件的静态连接(静态连接相当于将多个.o目标 ...
- python爬虫 Selenium库学习
一.自动化测试工具,支持多种浏览器,解决JS渲染问题 二.安装 pip3 install Selenium 三.操作介绍(因为是学习别人的课程为了尊重知识产权,部分代码就不显示了) 1驱动浏览器 br ...
- Spring MVC的异常处理 ?
可以将异常抛给Spring框架,由Spring框架来处理:我们只需要配置简单的异常处理器,在异常处理器中添视图页面即可.
- MySQL 中有哪些不同的表格?
共有 5 种类型的表格: 1.MyISAM 2.Heap 3.Merge 4.INNODB 5.ISAM
- IOC 的优点是什么?
IOC 或 依赖注入把应用的代码量降到最低.它使应用容易测试,单元测试不再需 要单例和 JNDI 查找机制.最小的代价和最小的侵入性使松散耦合得以实现.IOC 容器支持加载服务时的饿汉式初始化和懒加载 ...
- 使用 Spring 通过什么方式访问 Hibernate?
在 Spring 中有两种方式访问 Hibernate:控制反转 Hibernate Template 和 Callback.继承 HibernateDAOSupport 提供一个 AOP 拦截器.
- 『现学现忘』Docker基础 — 36、CMD指令和ENTRYPOINT指令的区别
目录 1.CMD指令和ENTRYPOINT指令说明 2.CMD指令只有最后一条生效的原因 3.CMD指令演示 4.ENTRYPOINT指令演示 5.总结 CMD指令和ENTRYPOINT指令作用都是指 ...
- Spark入门之环境搭建
本教程是虚拟机搭建Spark环境和用idea编写脚本 一.前提准备 需要已经有搭建好的虚拟机环境,具体见教程大数据学习之路又之从小白到用sqoop导出数据 - 我试试这个昵称好使不 - 博客园 (cn ...
- Android去掉标题头
在AndroidManifest.xml文件中定义 <application android:theme="@android:style/Theme.NoTitleBar"& ...