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。

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

相关推荐
正在走向自律17 分钟前
金仓数据库KingbaseES基础语法详解与实践指南
数据库·国产数据库·ddl·dml·kingbasees·sql语法·电科金仓
alonewolf_9917 分钟前
MySQL全局优化详解与8.0新特性全面解读
数据库·mysql
ASS-ASH20 分钟前
快速处理虚拟机磁盘扩容问题
linux·数据库·vmware·虚拟机·磁盘扩容
爱写bug的野原新之助25 分钟前
数据库及navicat工具
数据库·网络爬虫·工具
数据知道29 分钟前
一文掌握 MongoDB 存储引擎 WiredTiger 的原理
数据库·mongodb·数据库架构
Full Stack Developme33 分钟前
Mycat 2 实现 MySQL 读写分离,并且实现 主从同步
android·数据库·mysql
我是人✓37 分钟前
Spring IOC入门
java·数据库·spring
Hello.Reader38 分钟前
PyFlink DataStream 程序骨架、常用 Source/Sink、状态(State)、与 Table/SQL 互转一篇搞定
数据库·sql·linq
三不原则44 分钟前
故障案例:模型推理响应慢,排查 Redis 缓存集群问题
数据库·redis·缓存
alonewolf_991 小时前
MySQL Explain详解与索引优化实战
数据库·mysql·adb