VB.Net调用Oracle存储过程pr_1报PLS-00306错误,求排查方法
调用Oracle存储过程pk_1.pr_1时触发PL/SQL参数错误:
pls-00306: wrong number or types of arguments in call to procedure 'pr_1'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignore
当前VB.Net调用代码:
Try Dim int_key As Integer = 8 Dim cnnctn As New OracleConnection Dim cmmnd As New OracleCommand With cmmnd .Connection = cnnctn .CommandType = CommandType.StoredProcedure .CommandText = "pk_1.pr_1" .Parameters.Add("@wp_subtype_1", OracleDbType.Int32, ParameterDirection.Input).Value = int_key Dim ret_PR As New OracleParameter("@wp_tab_result", OracleDbType.Varchar2, ParameterDirection.Output) .Parameters.Add(ret_PR) .Parameters.Add("@wp_cd_err" , OracleDbType.Int32, ParameterDirection.Output).Size = 5 .Parameters.Add("@wp_msg_err", OracleDbType.Varchar2, ParameterDirection.Output).Size = 250 .ExecuteNonQuery() If CInt(.Parameters("@wp_cd_erro").Value.ToString()) <> 0 Then 'TODO : error handling' End If
存储过程包规范:
create or replace PACKAGE pk_1 AS TYPE rc_cursor IS REF CURSOR; SUBTYPE subtype_1 IS PLS_INTEGER RANGE 1..10 NOT NULL; TYPE tp_tb_rslt IS TABLE OF VARCHAR2(7); -- ... PROCEDURE pr_1 ( wp_subtype_1 IN subtype_1 , wp_tab_result OUT tp_tb_rslt , wp_cd_err OUT NUMBER , wp_msg_err OUT VARCHAR2) ; END pk_1;
修正集合类型参数的映射错误
存储过程中wp_tab_result是自定义表类型tp_tb_rslt,但VB.Net代码错误使用OracleDbType.Varchar2,这是核心类型不匹配。需改用OracleDbType.Array并关联Oracle自定义类型:Dim arrayType As New OracleParameter("@wp_tab_result", OracleDbType.Array, ParameterDirection.Output) arrayType.UdtTypeName = "PK_1.TP_TB_RSLT" ' Oracle标识符默认大写,需与数据库定义一致 .Parameters.Add(arrayType)验证输入参数的取值范围
wp_subtype_1是带范围限制的PLS_INTEGER(1-10),VB.Net用OracleDbType.Int32类型兼容,但要确保传入的int_key值在1-10范围内,超出范围会触发参数校验错误。修正参数名称拼写错误
VB.Net错误处理部分引用了@wp_cd_erro,但存储过程参数是wp_cd_err,拼写错误会导致后续取值失败,虽不是当前PLS-00306的直接原因,但必须修正。确认参数顺序与存储过程严格一致
OracleCommand的参数顺序必须和存储过程定义完全匹配(部分ODP.NET版本依赖参数顺序而非名称),当前代码顺序符合要求,但需确保无遗漏或多余参数。调整参数Size的无效设置
wp_cd_err是NUMBER类型,VB.Net设置Size=5无效,可直接移除该设置;wp_msg_err的Size需与存储过程实际定义的VARCHAR2长度一致,若存储过程未指定,需确认数据库端实际长度后调整。
补充数据库连接打开逻辑
当前代码未打开数据库连接,调用ExecuteNonQuery()前必须添加cnnctn.Open(),否则会触发连接错误,也可能间接导致参数解析异常。启用ODP.NET调试日志排查
开启ODP.NET调试日志,查看实际发送到Oracle的调用语句,对比参数类型和数量是否正确:
在项目配置文件中添加:<configuration> <oracle.dataaccess.client> <settings> <add name="TraceLevel" value="7"/> <add name="TraceFileName" value="odpnet_trace.log"/> </settings> </oracle.dataaccess.client> </configuration>查看生成的日志文件,确认参数的实际传递情况。
直接在PL/SQL环境验证存储过程
在SQL Developer等Oracle客户端手动调用存储过程,验证参数逻辑是否正常:DECLARE v_subtype pk_1.subtype_1 := 8; v_result pk_1.tp_tb_rslt; v_err_code NUMBER; v_err_msg VARCHAR2(250); BEGIN pk_1.pr_1(v_subtype, v_result, v_err_code, v_err_msg); DBMS_OUTPUT.PUT_LINE('Err Code: ' || v_err_code); DBMS_OUTPUT.PUT_LINE('Err Msg: ' || v_err_msg); IF v_result IS NOT NULL THEN FOR i IN v_result.FIRST..v_result.LAST LOOP DBMS_OUTPUT.PUT_LINE('Result ' || i || ': ' || v_result(i)); END LOOP; END IF; END;若PL/SQL调用正常,说明问题出在VB.Net参数映射;若PL/SQL调用也报错,需排查存储过程本身的逻辑。
内容的提问来源于stack exchange,提问作者Tomás

