Oracle存储过程怎么写

Oracle 存储过程(Stored Procedure)是存储在数据库中的一组预编译 SQL 和 PL/SQL 代码块,用于封装复杂的业务逻辑。

以下是完整的编写指南,包含基本结构参数类型常用逻辑 以及完整示例

1. 基本语法结构

一个标准的存储过程由三部分组成:声明部分执行部分异常处理部分

sql 复制代码
CREATE OR REPLACE PROCEDURE 过程名 (
    参数1 IN 数据类型,      -- 输入参数
    参数2 OUT 数据类型,     -- 输出参数
    参数3 IN OUT 数据类型   -- 输入输出参数
) IS
    -- 【声明部分】定义局部变量、游标、常量等
    v_variable_name  VARCHAR2(100);
    v_count          NUMBER := 0;
BEGIN
    -- 【执行部分】编写具体的 SQL 和业务逻辑
    SELECT count(*) INTO v_count FROM 表名 WHERE 条件;
    
    IF v_count > 0 THEN
        -- 业务逻辑...
        参数2 := '成功'; -- 给输出参数赋值
    ELSE
        参数2 := '失败';
    END IF;

EXCEPTION
    -- 【异常处理部分】捕获并处理错误
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE('未找到数据');
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('发生错误: ' || SQLERRM);
END 过程名;

2. 三种参数模式

模式 关键字 说明 使用场景
输入 IN 默认模式。调用时传入值,过程内只读。 查询条件、配置值。
输出 OUT 调用时需传入变量接收返回值,过程内可赋值。 返回统计结果、状态码、生成的主键ID。
输入输出 IN OUT 传入初始值,过程处理后修改该值并返回。 累加计算、字符串拼接处理。

3. 实战示例:用户信息处理

假设有一个表 USERS (ID, NAME, AGE, CITY)。我们要写一个存储过程:

  1. 根据 ID 查询用户。
  2. 如果用户年龄大于 18 岁且城市包含"市",则去掉城市后缀(类似你之前的 JS 逻辑)。
  3. 返回处理后的城市和状态消息。
sql 复制代码
CREATE OR REPLACE PROCEDURE PROC_UPDATE_USER_CITY (
    p_user_id   IN  NUMBER,           -- 输入:用户ID
    p_city_out  OUT VARCHAR2,         -- 输出:处理后的城市
    p_msg       OUT VARCHAR2          -- 输出:执行消息
) IS
    v_age       NUMBER;
    v_city      VARCHAR2(100);
    v_name      VARCHAR2(100);
BEGIN
    -- 1. 查询数据
    SELECT age, city, name 
    INTO v_age, v_city, v_name
    FROM USERS 
    WHERE id = p_user_id;

    -- 2. 业务逻辑判断
    IF v_age > 18 THEN
        -- 模拟去除城市后缀逻辑
        IF INSTR(v_city, '市') > 0 AND v_city NOT LIKE '%自治州%' THEN
            v_city := REPLACE(v_city, '市', '');
        END IF;
        
        p_msg := '用户 ' || v_name || ' 处理成功,新城市为:' || v_city;
    ELSE
        p_msg := '用户未成年,不处理城市信息。';
    END IF;

    -- 3. 赋值给输出参数
    p_city_out := v_city;

EXCEPTION
    WHEN NO_DATA_FOUND THEN
        p_msg := '错误:未找到 ID 为 ' || p_user_id || ' 的用户';
        p_city_out := NULL;
    WHEN OTHERS THEN
        p_msg := '系统异常:' || SQLERRM;
        p_city_out := NULL;
        -- 可选:记录日志到日志表
        -- INSERT INTO error_log VALUES (SYSDATE, SQLERRM);
END PROC_UPDATE_USER_CITY;

4. 如何调用存储过程

方法 A:在 SQL Developer / PLSQL Developer 中测试
sql 复制代码
DECLARE
    v_result_city VARCHAR2(100);
    v_message     VARCHAR2(200);
BEGIN
    -- 调用过程
    PROC_UPDATE_USER_CITY(
        p_user_id   => 1001,          -- 传入具体值
        p_city_out  => v_result_city, -- 传入变量接收
        p_msg       => v_message
    );
    
    -- 打印结果
    DBMS_OUTPUT.PUT_LINE(v_message);
    DBMS_OUTPUT.PUT_LINE('处理后城市:' || v_result_city);
END;

注意:使用前需开启输出显示 SET SERVEROUTPUT ON;

方法 B:在 Java / Python / Kettle 中调用
  • Java (JDBC): 使用 CallableStatement
  • Kettle: 使用 "Call DB Procedure" 组件,选择刚才创建的过程名,映射输入输出参数即可。

5. 常用技巧与注意事项

  1. CREATE OR REPLACE :

    • 始终加上 OR REPLACE,这样如果过程已存在,会直接覆盖更新,而不会报错。
  2. 变量赋值 :

    • 使用 := 进行赋值(如 v_count := 1;)。
    • 使用 SELECT ... INTO ... 将查询结果赋给变量。
  3. 动态 SQL :

    • 如果表名或列名需要动态变化,使用 EXECUTE IMMEDIATE
    sql 复制代码
    EXECUTE IMMEDIATE 'UPDATE ' || v_table_name || ' SET status=1 WHERE id=:1' USING p_id;
  4. 事务控制 :

    • 存储过程内部通常不写 COMMITROLLBACK,除非明确设计为独立事务。最好由调用者(外部程序)决定何时提交事务,以保持灵活性。
  5. 调试 :

    • 使用 DBMS_OUTPUT.PUT_LINE('变量值:' || v_var); 打印调试信息。

6. 常见错误排查

  • ORA-06550 / PLS-00201: 标识符必须声明(检查变量名拼写,或是否有权限访问该表)。
  • ORA-01403 : 未找到数据(SELECT INTO 没查到数据,需在 EXCEPTION 中捕获 NO_DATA_FOUND)。
  • ORA-01422 : 返回多于请求的行数(SELECT INTO 查出了多行,但变量只能存一行,需改用游标 CURSOR)。

如果你需要将之前 Kettle 中的 JavaScript 清洗逻辑迁移到 Oracle 存储过程中,我可以帮你直接转换那段代码。

相关推荐
OnlyEasyCode36 分钟前
Navicat 任务自动备份指定数据库
数据库
if else40 分钟前
Redis 哨兵集群部署方案
数据库·redis
yejqvow1244 分钟前
Pandas 高效实现组内跨行时间戳匹配与布尔标记
jvm·数据库·python
了不起的云计算V1 小时前
从DeepSeek V4适配看国产算力的三个拐点
数据库·人工智能
qq_189807031 小时前
html标签如何提升可访问性_aria-label与title区别【指南】
jvm·数据库·python
norq juox1 小时前
MySQL 导出数据
数据库·mysql·adb
qq_349317482 小时前
mysql如何设置定时自动备份脚本_编写shell脚本与cron任务
jvm·数据库·python
952362 小时前
Spring IoC&DI
java·数据库·spring
尚雷55802 小时前
从电商订单支付更新,吃透 Oracle 数据修改的底层设计哲学与全组件协同原理
数据库·oracle
2401_832365522 小时前
Chart.js 4 中基于数据实际范围的线性渐变填充方案
jvm·数据库·python