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

UDT注册前置报错求助:API调用包函数失败但SQL调用正常

问题解决:调用数据库UDT函数时出现"call register type before use user defined type (UDT)"错误

问题场景

在API处理程序中调用数据库包内的GetContractorIDByName函数时,触发错误提示:call register type before use user defined type (UDT),但直接通过SQL查询调用该函数完全正常。

提供的代码

API调用代码

var responsibleID string
query := `
    BEGIN
        :1 := MYDB.RESPONSIBLE_BO.GetContractorIDByName(:2);
    END;
`
err = tx.QueryRow(query, sql.Out{Dest: &responsibleID}, req.ResponsibleName).Scan(&responsibleID)
if err != nil {
    log.Println("Failed to get ResponsibleID:", err)
    tx.Rollback()
    ctx.SetStatus(apieasy.InternalServerError, "Failed to get ResponsibleID, error: %v", err)
    return
}

数据库函数定义

FUNCTION GetContractorIDByName (i_sNAME IN VARCHAR2)
    RETURN CHAR
    IS 
      v_res CONTRACTOR.CONTRACTORID % TYPE;
    BEGIN 
      IF (i_sNAME IS NOT NULL)
      THEN
        BEGIN
          SELECT CONTRACTORID
            INTO v_res
            FROM CONTRACTOR
            WHERE NAME = i_sNAME;
          EXCEPTION
            WHEN NO_DATA_FOUND THEN
              CREATECONTRACTOR (i_sNAME, NULL, NULL, 'created by function GetContractorIDByName', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0);
              COMMIT;
              BEGIN
                  SELECT CONTRACTORID
                    INTO v_res
                    FROM CONTRACTOR
                    WHERE NAME = i_sNAME;
              EXCEPTION
                  WHEN NO_DATA_FOUND THEN
                      RAISE_APPLICATION_ERROR(-20002, 'Failed to retrieve newly created contractor TRY AGAIN');
              END;
        END;
      ELSE 
                RAISE_APPLICATION_ERROR(-20001, 'Undefined nom name');
      END IF;
      RETURN v_res;
    END GetContractorIDByName;

解决方案

  • 移除多余的Scan操作:你已经通过sql.Out{Dest: &responsibleID}指定了输出参数的目标变量,不需要再调用Scan(&responsibleID),这会导致重复读取结果引发类型处理冲突。同时,PL/SQL块执行应使用Exec而非QueryRow(后者用于处理返回结果集的查询),修改后的代码:
var responsibleID string
query := `
    BEGIN
        :1 := MYDB.RESPONSIBLE_BO.GetContractorIDByName(:2);
    END;
`
_, err = tx.Exec(query, sql.Out{Dest: &responsibleID}, req.ResponsibleName)
if err != nil {
    log.Println("Failed to get ResponsibleID:", err)
    tx.Rollback()
    ctx.SetStatus(apieasy.InternalServerError, "Failed to get ResponsibleID, error: %v", err)
    return
}
  • 消除事务上下文冲突:数据库函数内部执行了COMMIT,但API中已开启事务tx,这会破坏事务一致性。建议将COMMIT逻辑移到API层,由调用方统一控制事务提交/回滚。
  • 驱动UDT检查:如果使用godror等Oracle驱动,确保连接时未遗漏UDT类型注册,但你的函数返回CHAR类型,此问题概率较低,优先处理前两点即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 23:43:15