使用Oracle.ManagedDataAccess.dll调用Oracle存储过程遇ORA-06502错误求助
问题描述
使用Microsoft.Practices.EnterpriseLibrary.Data.dll时,VB.NET代码调用Oracle存储过程一切正常,但改用Oracle.ManagedDataAccess.dll重写相同调用时,出现错误:ORA-06502: PL/SQL: numeric or value error: character string buffer too small。
使用Microsoft.Practices.EnterpriseLibrary.Data的代码
Dim db As Database = GetDatabase("connection string") Dim dbCommand As DbCommand dbCommand = db.GetStoredProcCommand("procedurename") db.AddInParameter(dbCommand, "piv_userid", DbType.String, strUserID) db.AddInParameter(dbCommand, "piv_userpwd", DbType.String, strPassword) db.AddInParameter(dbCommand, "piv_appstub", DbType.String, My.Application.Info.ProductName) db.AddOutParameter(dbCommand, "pon_error_no", DbType.Decimal, 10) db.AddOutParameter(dbCommand, "pov_error_msg", DbType.String, 400) db.AddOutParameter(dbCommand, "pov_applist", DbType.String, 100) db.ExecuteNonQuery(dbCommand)
使用Oracle.ManagedDataAccess.dll的代码
Dim conn As New OracleConnection("connection string") Dim cmd As New OracleCommand("procedurename", conn) cmd.CommandType = CommandType.StoredProcedure cmd.Parameters.Add("piv_userid", OracleDbType.Varchar2, ParameterDirection.Input).Value = strUserID cmd.Parameters.Add("piv_userpwd", OracleDbType.Varchar2, ParameterDirection.Input).Value = strPassword cmd.Parameters.Add("piv_appstub", OracleDbType.Varchar2, ParameterDirection.Input).Value = My.Application.Info.ProductName cmd.Parameters.Add("pon_error_no", OracleDbType.Decimal, 10, ParameterDirection.Output) cmd.Parameters.Add("pov_error_msg", OracleDbType.Varchar2, 400, ParameterDirection.Output) cmd.Parameters.Add("pov_applist", OracleDbType.Varchar2, 100, ParameterDirection.Output) cmd.ExecuteNonQuery()
问题原因
核心在于两个组件对字符串参数的类型映射和长度计数逻辑不一致:
- 旧代码中使用
DbType.String,EnterpriseLibrary会自动将其映射为Oracle的NVARCHAR2类型,长度按字符数计算(比如设置400就代表允许400个任意字符,包括中文等多字节字符)。 - 新代码中指定
OracleDbType.Varchar2,该类型默认按字节数计算长度(取决于数据库字符集,如AL32UTF8下一个中文占3字节)。如果存储过程返回的字符串包含多字节字符,实际占用的字节数会超过你设置的数值,触发缓冲区不足的错误。
另外,若存储过程中的输出参数定义为NVARCHAR2类型,而你用Varchar2绑定,也会因类型不匹配引发长度问题。
解决方案
方式一:改用OracleDbType.NVarchar2匹配原逻辑
将字符串参数的类型改为NVarchar2,长度按字符数计数,和EnterpriseLibrary的行为完全一致:
Dim conn As New OracleConnection("connection string") Dim cmd As New OracleCommand("procedurename", conn) cmd.CommandType = CommandType.StoredProcedure ' 输入参数改用NVarchar2 cmd.Parameters.Add("piv_userid", OracleDbType.NVarchar2, ParameterDirection.Input).Value = strUserID cmd.Parameters.Add("piv_userpwd", OracleDbType.NVarchar2, ParameterDirection.Input).Value = strPassword cmd.Parameters.Add("piv_appstub", OracleDbType.NVarchar2, ParameterDirection.Input).Value = My.Application.Info.ProductName cmd.Parameters.Add("pon_error_no", OracleDbType.Decimal, 10, ParameterDirection.Output) ' 输出字符串参数改用NVarchar2,保持原长度设置 cmd.Parameters.Add("pov_error_msg", OracleDbType.NVarchar2, 400, ParameterDirection.Output) cmd.Parameters.Add("pov_applist", OracleDbType.NVarchar2, 100, ParameterDirection.Output) conn.Open() ' 补充原代码遗漏的连接打开步骤 cmd.ExecuteNonQuery() conn.Close()
方式二:按字节数调整参数Size(不推荐,除非明确字符集)
如果必须使用Varchar2,需要根据数据库字符集计算足够的字节数。比如AL32UTF8字符集下,每个中文占3字节,将原400字符的缓冲区调整为1200字节:
cmd.Parameters.Add("pov_error_msg", OracleDbType.Varchar2, 1200, ParameterDirection.Output) cmd.Parameters.Add("pov_applist", OracleDbType.Varchar2, 300, ParameterDirection.Output)
内容的提问来源于stack exchange,提问作者user3859666
相关产品推荐
相关产品推荐

