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

调用Oracle存储过程遇ORA-06502:宿主绑定数组过小(C#端排查)

ORA-06502: PL/SQL: numeric or value error: host bind array too small 问题解决

问题描述

调用Oracle存储过程读取字符串数组时触发以下错误:

ORA-06502: PL/SQL: numeric or value error: host bind array too small. 

存储过程本身可正常运行,但通过C#调用时报错,推测为C#代码参数配置问题。

相关代码

C#调用代码

string[] myArray2 = new string[NoOfDay];
OracleString[] arrDays = null;

OracleParameter P_result2 = new OracleParameter("UTILDAYS", OracleDbType.Varchar2, 20);
P_result2.Direction = ParameterDirection.Output;
P_result2.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
P_result2.Size = myArray2.Count();
P_result2.ArrayBindSize = new int[myArray2.Count()];
cmd.Parameters.Add(P_result2);

try
{
    con.Open();
    cmd.ExecuteNonQuery(); // 错误触发位置
    arrDays = (OracleString[]) cmd.Parameters["UTILDAYS"].Value;
    con.Close();
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

Oracle存储过程代码

TYPE myArray2 IS TABLE OF VARCHAR2(20) INDEX BY PLS_INTEGER;

CREATE OR REPLACE PROCEDURE GETUTILDAYS (
 "DATE1"       IN     VARCHAR2,
   "DATE2"       IN     VARCHAR2,
   "TESTER"      IN     VARCHAR2, 
  "UTILDAYS"      OUT GETUTIL.myArray2
 )
IS
   currDate   VARCHAR2 (20);
   prevDate   VARCHAR2 (20);
   total      NUMBER;
   total0     NUMBER;
   cnt        NUMBER;
   firstR     NUMBER;

   CURSOR V_CUR
   IS
        SELECT idle_category,
               TO_CHAR (CAST (probed_time AS DATE), 'MM-DD-YYYY') AS pd
          FROM inprogress
         WHERE tester_id = TESTER
               AND probed_time >
                      TO_TIMESTAMP (CONCAT (DATE1, ' 00:00:00'),
                                    'mm-dd-yyyy hh24:mi:ss')
               AND probed_time <
                      TO_TIMESTAMP (CONCAT (DATE2, ' 23:59:59'),
                                    'mm-dd-yyyy hh24:mi:ss')
      ORDER BY probed_time ASC;
BEGIN
   total := 0;
   total0 := 0;
   cnt := 1;
   firstR:=1;

   FOR V_REC IN V_CUR
   LOOP
      currDate := V_REC.pd;

      IF firstR = 1
      THEN
         firstR:=99;
         prevDate := V_REC.pd;
      END IF;

      IF prevDate = currDate
      THEN
         total := total + 1;

         IF V_REC.idle_category = 0
         THEN
            total0 := total0 + 1;
         END IF;
      ELSE
         UTILDAYS (cnt) := prevDate;
         cnt := cnt + 1;
         total := 0;
         total0 := 0;
         prevDate := currDate;
      END IF;
   END LOOP;
   UTILDAYS (cnt) := currDate;
END GETUTILDAYS;

解决方法

错误核心是C#中定义的输出数组大小不足以容纳存储过程返回的元素数量,或单个元素缓冲区未正确设置。

  1. 确保数组Size足够大

    • NoOfDay的取值需覆盖DATE1到DATE2之间的所有天数,建议直接计算两个日期的天数差再加1,或设置一个足够大的初始值(比如366,覆盖一年所有可能天数),避免实际返回元素数量超过数组大小。
  2. 正确初始化ArrayBindSize

    • ArrayBindSize用于指定数组中每个元素的最大长度,需与存储过程中VARCHAR2(20)的长度匹配。修改代码,将ArrayBindSize的每个元素设置为20:
      P_result2.ArrayBindSize = Enumerable.Repeat(20, myArray2.Count()).ToArray();
      
    • 不设置的话,默认缓冲区大小可能不足,导致单个元素存储报错。
  3. 动态匹配数组大小

    • 可以在存储过程中添加输出参数返回实际生成的元素数量,或在C#调用前先查询DATE1到DATE2之间的天数,动态设置数组大小,确保足够容纳所有返回值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 07:35:20