Oracle中游标和集合的定义查询及取值

在 Oracle 存储过程中,使用游标处理自定义数据行类型时,可以通过 定义记录类型(RECORD) 和 游标(CURSOR) 结合实现。
1. 定义自定义记录类型

使用 TYPE ... IS RECORD 定义自定义行数据类型:

sql 复制代码
DECLARE
  -- 定义自定义记录类型(包含所需字段)
  TYPE t_emp_record IS RECORD (
    emp_id   employees.employee_id%TYPE,
    emp_name VARCHAR2(100),
    salary   employees.salary%TYPE
  );
  
  v_emp t_emp_record;  -- 声明变量
BEGIN
  -- 逻辑代码
END;

2. 声明游标并关联查询

将游标的查询结果映射到自定义记录类型:

sql 复制代码
DECLARE
  -- 定义记录类型
  TYPE t_emp_record IS RECORD (
    emp_id   employees.employee_id%TYPE,
    emp_name VARCHAR2(100),
    salary   employees.salary%TYPE
  );
  
  -- 声明游标(显式指定返回类型)
  CURSOR cur_custom_emp IS
    SELECT employee_id, first_name || ' ' || last_name, salary
    FROM employees
    WHERE department_id = 10;  -- 示例查询条件
  
  v_emp t_emp_record;  -- 声明变量
BEGIN
  OPEN cur_custom_emp;
  LOOP
    FETCH cur_custom_emp INTO v_emp;
    EXIT WHEN cur_custom_emp%NOTFOUND;
    -- 处理数据(例如输出)
    DBMS_OUTPUT.PUT_LINE(
      'ID: ' || v_emp.emp_id || 
      ', Name: ' || v_emp.emp_name || 
      ', Salary: ' || v_emp.salary
    );
  END LOOP;
  CLOSE cur_custom_emp;
END;

3. 使用 %ROWTYPE 简化记录类型

如果查询字段与表结构一致,可直接用 %ROWTYPE

sql 复制代码
DECLARE
  CURSOR cur_emp IS
    SELECT employee_id, first_name, salary
    FROM employees;
  
  v_emp cur_emp%ROWTYPE;  -- 自动匹配游标字段
BEGIN
  OPEN cur_emp;
  LOOP
    FETCH cur_emp INTO v_emp;
    EXIT WHEN cur_emp%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(v_emp.first_name || '的工资是:' || v_emp.salary);
  END LOOP;
  CLOSE cur_emp;
END;

4. 将自定义记录类型作为参数传递

可以在存储过程或函数间传递自定义记录类型:

sql 复制代码
CREATE OR REPLACE PROCEDURE process_employee (
    p_emp IN t_emp_record  -- 假设 t_emp_record 已在包中定义
)
IS
BEGIN
  DBMS_OUTPUT.PUT_LINE('处理员工:' || p_emp.emp_name);
END;

5. 在包(Package)中定义公共记录类型

若需跨多个程序单元使用,可在包中定义:

sql 复制代码
CREATE OR REPLACE PACKAGE emp_pkg IS
  -- 定义公共记录类型
  TYPE t_emp_record IS RECORD (
    emp_id   employees.employee_id%TYPE,
    emp_name VARCHAR2(100),
    salary   employees.salary%TYPE
  );
  
  -- 声明游标
  CURSOR cur_emp RETURN t_emp_record;  -- 注意:此处仅定义游标规范
END emp_pkg;

CREATE OR REPLACE PACKAGE BODY emp_pkg IS
  -- 实现游标(关联查询)
  CURSOR cur_emp RETURN t_emp_record IS
    SELECT employee_id, first_name || ' ' || last_name, salary
    FROM employees;
END emp_pkg;

6. 使用 BULK COLLECT 批量提取数据

高效处理大量数据:

sql 复制代码
DECLARE
  -- t_emp_record上面方式进行定义
  TYPE t_emp_table IS TABLE OF t_emp_record;  -- 定义表类型
  v_emps t_emp_table;  -- 声明表变量
BEGIN
  -- 批量提取数据到表变量
  SELECT employee_id, first_name || ' ' || last_name, salary
  BULK COLLECT INTO v_emps
  FROM employees
  WHERE department_id = 10;

  -- 遍历表变量
  FOR i IN 1..v_emps.COUNT LOOP
    DBMS_OUTPUT.PUT_LINE(v_emps(i).emp_name);
  END LOOP;
END;

7. 动态游标与记录类型结合

使用 SYS_REFCURSOR 动态游标时,需显式匹配记录类型:

sql 复制代码
DECLARE
  TYPE t_emp_record IS RECORD (
    emp_id   NUMBER,
    emp_name VARCHAR2(100),
    salary   NUMBER
  );
  
  v_cur      SYS_REFCURSOR;  -- 动态游标
  v_emp      t_emp_record;   -- 自定义记录
  v_sql_stmt VARCHAR2(200) := 
    'SELECT employee_id, first_name || '' '' || last_name, salary 
     FROM employees 
     WHERE department_id = :dept_id';
BEGIN
  OPEN v_cur FOR v_sql_stmt USING 10;  -- 绑定参数
  LOOP
    FETCH v_cur INTO v_emp;
    EXIT WHEN v_cur%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(v_emp.emp_name);
  END LOOP;
  CLOSE v_cur;
END;

总结

**定义记录类型:**明确字段结构,可匹配游标查询。

**游标声明:**显式指定查询字段与记录类型匹配。

**数据提取:**使用 FETCH INTO 将游标数据存入记录变量。

**批量处理:**BULK COLLECT 提升大数据量性能。

**动态游标:**结合 SYS_REFCURSOR 和自定义类型处理动态 SQL。

通过以上方法,可以灵活控制游标返回的数据结构,并高效处理复杂业务逻辑。

相关推荐
松涛和鸣10 小时前
72、IMX6ULL驱动实战:设备树(DTS/DTB)+ GPIO子系统+Platform总线
linux·服务器·arm开发·数据库·单片机
likangbinlxa11 小时前
【Oracle11g SQL详解】UPDATE 和 DELETE 操作的正确使用
数据库·sql
r i c k11 小时前
数据库系统学习笔记
数据库·笔记·学习
野犬寒鸦11 小时前
从零起步学习JVM || 第一章:类加载器与双亲委派机制模型详解
java·jvm·数据库·后端·学习
IvorySQL12 小时前
PostgreSQL 分区表的 ALTER TABLE 语句执行机制解析
数据库·postgresql·开源
·云扬·12 小时前
MySQL 8.0 Redo Log 归档与禁用实战指南
android·数据库·mysql
IT邦德12 小时前
Oracle 26ai DataGuard 搭建(RAC到单机)
数据库·oracle
惊讶的猫13 小时前
redis分片集群
数据库·redis·缓存·分片集群·海量数据存储·高并发写
不爱缺氧i13 小时前
完全卸载MariaDB
数据库·mariadb
纤纡.13 小时前
Linux中SQL 从基础到进阶:五大分类详解与表结构操作(ALTER/DROP)全攻略
linux·数据库·sql