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

调用Oracle包函数GET_MUSEUMBYNAME触发PLS-00306参数错误求助

排查ORA-06550/PLS-00306参数错误的原因及解决办法

错误原因分析

你遇到的PLS-00306错误,核心是C#代码调用Oracle函数时的参数映射和配置出了问题,具体来说:

  1. 参数类型未显式匹配:你直接传入字符串museum_Name,Oracle客户端默认映射的类型/长度,和PL/SQL函数定义的v_museum Museum.Name%type(即VARCHAR2(30))不匹配,触发了类型校验失败。
  2. 未启用按名称绑定:OracleCommand默认按位置绑定参数,虽然你的参数顺序是对的,但这种方式在复杂场景下容易出现映射混乱,也不利于后续代码维护。
  3. 参数配置不够严谨:输入参数的方向没有显式声明(虽然默认是Input),在部分环境下可能导致Oracle解析参数时出现偏差。

解决办法

下面提供两种可行的修正方案,你可以根据习惯选择:

方案一:完善StoredProcedure模式的参数配置

保持CommandType.StoredProcedure的调用方式,补充参数的显式配置:

public List<MuseumDto> GetMuseumsByName(string museum_Name) {
    var connectionString = ConfigurationManager.ConnectionStrings["OracleConnectionString"].ConnectionString;
    var museum = new List<MuseumDto>();
    using (var connection = new OracleConnection(connectionString)) {
        OracleCommand mycom = new OracleCommand();
        connection.Open();
        mycom.CommandText = "museum_package.get_MuseumByName";
        mycom.Connection = connection;
        mycom.CommandType = CommandType.StoredProcedure;
        // 启用按名称绑定,避免位置映射出错
        mycom.BindByName = true;

        // 显式配置输入参数:指定类型、长度、方向和值,匹配PL/SQL定义
        var inputParam = mycom.Parameters.Add("v_museum", OracleDbType.Varchar2, 30);
        inputParam.Value = museum_Name;
        inputParam.Direction = ParameterDirection.Input;

        // 配置函数返回值参数
        var returnParam = mycom.Parameters.Add("ReturnValue", OracleDbType.RefCursor);
        returnParam.Direction = ParameterDirection.ReturnValue;

        using (OracleDataReader reader = mycom.ExecuteReader()) {
            while (reader.Read()) {
                museum.Add(new MuseumDto {
                    museumId = reader.GetInt32(0),
                    name = reader.GetString(1),
                    city = reader.GetString(2),
                    about= reader.GetString(3),
                    schedule = reader.GetString(4),
                    noArtefacts= reader.GetInt32(5),
                });
            }
        }
    }
    return museum;
}

方案二:用匿名PL/SQL块调用(更直观)

改用CommandType.Text,通过匿名块调用函数,这种方式参数映射更清晰,对新手更友好:

public List<MuseumDto> GetMuseumsByName(string museum_Name) {
    var connectionString = ConfigurationManager.ConnectionStrings["OracleConnectionString"].ConnectionString;
    var museum = new List<MuseumDto>();
    using (var connection = new OracleConnection(connectionString)) {
        OracleCommand mycom = new OracleCommand();
        connection.Open();
        // 用匿名PL/SQL块调用函数,将返回值赋值给输出参数
        mycom.CommandText = "BEGIN :ReturnValue := museum_package.get_MuseumByName(:v_museum); END;";
        mycom.Connection = connection;
        mycom.CommandType = CommandType.Text;
        mycom.BindByName = true;

        // 配置输入参数
        var inputParam = mycom.Parameters.Add("v_museum", OracleDbType.Varchar2, 30);
        inputParam.Value = museum_Name;
        inputParam.Direction = ParameterDirection.Input;

        // 配置输出参数(对应匿名块中的:ReturnValue)
        var returnParam = mycom.Parameters.Add("ReturnValue", OracleDbType.RefCursor);
        returnParam.Direction = ParameterDirection.Output;

        using (OracleDataReader reader = mycom.ExecuteReader()) {
            while (reader.Read()) {
                museum.Add(new MuseumDto {
                    museumId = reader.GetInt32(0),
                    name = reader.GetString(1),
                    city = reader.GetString(2),
                    about= reader.GetString(3),
                    schedule = reader.GetString(4),
                    noArtefacts= reader.GetInt32(5),
                });
            }
        }
    }
    return museum;
}

额外注意事项

  • 如果需要支持更长的博物馆名称输入,可以修改PL/SQL函数的参数类型长度(比如改成VARCHAR2(100)),同时同步调整C#代码中参数的Size值。
  • 你原来代码中用using包裹资源、关闭阅读器的做法很规范,继续保持即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:45:01