在 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。
通过以上方法,可以灵活控制游标返回的数据结构,并高效处理复杂业务逻辑。