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
相关产品推荐
相关产品推荐

