Oracle中如何传递游标作为参数并正确调用?
解决Oracle中SYS_REFCURSOR直接引用字段的PLS-00487错误
错误原因
SYS_REFCURSOR是弱类型游标,无法直接通过游标变量访问字段;同时你在存储过程中重复声明了同名的rt_ba游标变量,覆盖了传入的参数,这两个问题共同导致了PLS-00487错误。
解决步骤
1. 定义匹配游标结果集的记录类型
需要先定义与游标查询列结构完全匹配的记录类型,确保字段顺序、数据类型和查询结果一致:
-- 可在存储过程内部或包级别定义该类型 TYPE rt_ba_rec IS RECORD ( -- 对应idm_ap_mtc_acl_header_tmp表的字段 no_ba idm_ap_mtc_acl_header_tmp.no_ba%TYPE, req_id idm_ap_mtc_acl_header_tmp.req_id%TYPE, tgl_ba idm_ap_mtc_acl_header_tmp.tgl_ba%TYPE, tax_name idm_ap_mtc_acl_header_tmp.tax_name%TYPE, dc_code idm_ap_mtc_acl_header_tmp.dc_code%TYPE, -- 对应idm_ap_mtc_acl_lines_tmp表的字段 jenis_pekerjaan idm_ap_mtc_acl_lines_tmp.jenis_pekerjaan%TYPE, deskripsi_pekerjaan idm_ap_mtc_acl_lines_tmp.deskripsi_pekerjaan%TYPE, akun idm_ap_mtc_acl_lines_tmp.akun%TYPE, rate_ppn idm_ap_mtc_acl_lines_tmp.rate_ppn%TYPE, dpp idm_ap_mtc_acl_lines_tmp.dpp%TYPE, ppn idm_ap_mtc_acl_lines_tmp.ppn%TYPE, total_realisasi idm_ap_mtc_acl_lines_tmp.total_realisasi%TYPE, major idm_ap_mtc_acl_lines_tmp.major%TYPE, minor idm_ap_mtc_acl_lines_tmp.minor%TYPE, sla idm_ap_mtc_acl_lines_tmp.sla%TYPE );
2. 修改存储过程,通过记录变量访问游标数据
移除多余的游标变量声明,将游标数据FETCH到记录变量后再访问字段:
PROCEDURE create_invoice_ap2 (p_org_id IN NUMBER, p_user_id IN NUMBER, p_branch_code IN VARCHAR2, r_ba IN SYS_REFCURSOR) IS TYPE rt_ba_rec IS RECORD ( no_ba idm_ap_mtc_acl_header_tmp.no_ba%TYPE, req_id idm_ap_mtc_acl_header_tmp.req_id%TYPE, tgl_ba idm_ap_mtc_acl_header_tmp.tgl_ba%TYPE, tax_name idm_ap_mtc_acl_header_tmp.tax_name%TYPE, dc_code idm_ap_mtc_acl_header_tmp.dc_code%TYPE, jenis_pekerjaan idm_ap_mtc_acl_lines_tmp.jenis_pekerjaan%TYPE, deskripsi_pekerjaan idm_ap_mtc_acl_lines_tmp.deskripsi_pekerjaan%TYPE, akun idm_ap_mtc_acl_lines_tmp.akun%TYPE, rate_ppn idm_ap_mtc_acl_lines_tmp.rate_ppn%TYPE, dpp idm_ap_mtc_acl_lines_tmp.dpp%TYPE, ppn idm_ap_mtc_acl_lines_tmp.ppn%TYPE, total_realisasi idm_ap_mtc_acl_lines_tmp.total_realisasi%TYPE, major idm_ap_mtc_acl_lines_tmp.major%TYPE, minor idm_ap_mtc_acl_lines_tmp.minor%TYPE, sla idm_ap_mtc_acl_lines_tmp.sla%TYPE ); l_ba_rec rt_ba_rec; -- 声明记录变量 r_tax_info rt_tax_info; BEGIN ------------ setup ------------ -- 从传入的游标中获取一行数据到记录变量 FETCH r_ba INTO l_ba_rec; -- 检查是否获取到有效数据 IF r_ba%FOUND THEN r_tax_info := get_tax_code ( p_date => l_ba_rec.tgl_ba, p_group_tax_name => l_ba_rec.tax_name, p_ppn_rate => l_ba_rec.rate_ppn, p_dc_code => l_ba_rec.dc_code); ELSE -- 处理无数据场景,可根据业务需求调整 RAISE_APPLICATION_ERROR(-20001, '游标中无可用数据'); END IF; -- 若游标返回多行数据,需用循环遍历处理: -- LOOP -- FETCH r_ba INTO l_ba_rec; -- EXIT WHEN r_ba%NOTFOUND; -- -- 此处添加每行数据的业务逻辑 -- END LOOP; END;
3. 关键注意事项
- 记录类型的字段顺序、数据类型必须与游标查询的列完全匹配,否则会触发类型不匹配错误
- 若游标返回多行数据,必须使用循环遍历所有行,避免只处理第一行
- 存储过程内部不要重复声明与参数同名的变量,避免覆盖传入值
内容的提问来源于stack exchange,提问作者Steven Phan
相关产品推荐
相关产品推荐

