You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go使用go-ora/v2调用Oracle包获取REFCURSOR输出报错

问题背景

在Oracle数据库中创建测试包如下:

CREATE OR REPLACE PACKAGE PKG_TEST IS
    TYPE REFCURSOR IS REF CURSOR;
    PROCEDURE PROC_GET_DUAL(P_CUR OUT REFCURSOR);
end PKG_TEST;
/
CREATE OR REPLACE PACKAGE BODY PKG_TEST is
    PROCEDURE PROC_GET_DUAL(
        P_CUR OUT REFCURSOR)
        IS
    BEGIN
        OPEN P_CUR FOR
            select * from dual;
    END PROC_GET_DUAL;
end PKG_TEST;
/

使用Golang的github.com/sijms/go-ora/v2驱动连接Oracle,ping检测连通正常,最初编写的调用代码如下:

var cursor go_ora.RefCursor
fmt.Println(db.Ping())
statement := `begin :x := PKG_TEST.PROC_GET_DUAL(); end;`
_, err := db.Exec(statement, sql.Out{Dest: &cursor})
//check errors

defer cursor.Close()
rows, err := cursor.Query()
// check for error

var (
    var1 string
)
for rows.Next_() {
    err = rows.Scan(&var1)
    // check for error
    fmt.Println(var1)
}

参考驱动文档编写代码但执行时报错,核心报错信息如下:

PLS-00222: no function with name 'PROC_GET_DUAL' exists in this scope
ORA-06550: line 1, column 13:
PL/SQL: Statement ignored

报错原因

核心问题是混淆了Oracle存储过程和函数的调用语法:

  • 定义的PROC_GET_DUAL是存储过程,没有返回值,结果游标通过参数列表的OUT类型参数传出
  • 编写的调用语句:x := PKG_TEST.PROC_GET_DUAL()是函数调用语法,执行时会去查找名为PROC_GET_DUAL、无入参、带返回值的函数,找不到对应对象就会触发PLS-00222错误。
修复方案
  1. 修改PL/SQL调用语句,改为存储过程的标准调用格式,将游标占位符作为存储过程的入参传入,不要使用赋值语法:
    begin PKG_TEST.PROC_GET_DUAL(:x); end;
    
  2. 调整Go代码逻辑,补充错误校验和资源释放操作,修正后完整可运行代码:
    var cursor go_ora.RefCursor
    // 校验ping错误,不要仅打印返回值不做处理
    err := db.Ping()
    if err != nil {
        panic(err)
    }
    fmt.Println("数据库连通正常")
    
    // 修正为存储过程调用语法
    statement := `begin PKG_TEST.PROC_GET_DUAL(:x); end;`
    _, err = db.Exec(statement, sql.Out{Dest: &cursor})
    if err != nil {
        panic(err)
    }
    defer cursor.Close()
    
    rows, err := cursor.Query()
    if err != nil {
        panic(err)
    }
    defer rows.Close() // 主动关闭结果集,避免游标资源泄漏
    
    var var1 string
    // go-ora v2版本遍历使用Next()即可,旧版本Next_()已废弃
    for rows.Next() {
        err = rows.Scan(&var1)
        if err != nil {
            panic(err)
        }
        fmt.Println(var1)
    }
    

修复后执行即可正常输出dual表的X字段值。


内容的提问来源于stack exchange,提问作者htan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 15:09:19