使用 12c 客户端截断的存储过程 OUTPUT VARCHAR2 值

Posted

技术标签:

【中文标题】使用 12c 客户端截断的存储过程 OUTPUT VARCHAR2 值【英文标题】:Stored procedure OUTPUT VARCHAR2 value truncated using 12c client 【发布时间】:2017-08-08 23:24:04 【问题描述】:

我正在使用 oracle 11g。我的存储过程返回varchar2,但它的值被oracle client 截断。 以下是我的代码:

            if ((ds != null) && (ds.Tables.Count > 0))
                

                    foreach (DataRow rw in ds.Tables[0].Rows)
                    

                        OracleParameter param = new OracleParameter((rw["argument_name"]).ToString(), GetOracleType(rw["data_type"].ToString().ToUpper()));
                        param.Direction = GetParameterDirection((rw["in_out"]).ToString().ToUpper());
                        discoveryCommand.Parameters.Add(param);
                        if (param.Direction == ParameterDirection.Output && param.OracleType == OracleType.VarChar)
                        
                            param.Size = 4000;
                        
                    
                

我将param.size 增加到4000,但值仍然被截断。 有没有办法解决这个问题。在服务器上我有 Oracle 12c。我需要在不更新项目中的 oracle 客户端版本的情况下获得解决方案,因为由于某些原因,这是不允许的。

下面是 SP 。我对其进行了修改以返回硬编码值。还是同样的问题。

PROCEDURE access_level (
          p_emp_id IN  employees.emp_id%TYPE,
        p_id IN  NUMBER,
        p_type VARCHAR2,
          p_access_level OUT VARCHAR2
 ) IS
  BEGIN


 p_access_level := 'X' || 'RO' || 'RW';






 END IF;

【问题讨论】:

你使用什么库。你能切换到 Oracle.ManagedDataAccess 吗?首先它是本机 oracle,其次它可以让您不必打扰 app-ora 客户端数据库的匹配版本 不,很遗憾我不能@JuryGolubev 数据截断后的结果长度是多少? @CodeFuller 仅限 3 个字符 您能否提供实际数据:从存储过程返回什么字符串以及如何截断?另外,您的过程是否实际上返回 varchar2,而不是 nvarchar2? 【参考方案1】:

对于连接到服务器 12.1.0.1.0 的客户端版本 11.2.0.1.0,我无法重现您的问题。当 Oracle 12c 客户端截断输出变量时,这是一个known case,但是如果您使用的是 11g 版本的客户端,则不应该是这种情况。

我使用了以下测试表和存储过程:

CREATE TABLE TEST_TABLE
(
    ID NUMBER(11) NOT NULL,
    NAME VARCHAR2(256),
    CONSTRAINT TEST_TABLE_PK PRIMARY KEY (ID)
)
/

INSERT INTO TEST_TABLE(ID, NAME) VALUES(1, 'Some test data')
/

CREATE PROCEDURE TEST_PROCEDURE
(
   P_ID OUT NUMBER,
   P_NAME OUT VARCHAR2
)
AS
BEGIN
   SELECT ID, NAME INTO P_ID, P_NAME FROM TEST_TABLE;
END;

这是正确获取数据的客户端代码:

using (OracleConnection connection = new OracleConnection())

    connection.ConnectionString = ConfigurationManager.ConnectionStrings["TestDatabase"].ConnectionString;
    connection.Open();

    using (OracleCommand command = connection.CreateCommand())
    
        command.CommandText = "TEST_PROCEDURE";
        command.CommandType = CommandType.StoredProcedure;

        OracleParameter param1 = new OracleParameter("P_ID", OracleType.Number);
        param1.Direction = ParameterDirection.Output;
        command.Parameters.Add(param1);

        OracleParameter param2 = new OracleParameter("P_NAME", OracleType.VarChar);
        param2.Size = 4000;
        param2.Direction = ParameterDirection.Output;
        command.Parameters.Add(param2);

        using (command.ExecuteReader())
        
            Console.WriteLine($"Output: [param2.Value]");
        
    

要继续您的问题,请您执行以下操作:

    如果可以的话,创建上面的测试表和存储过程,用上面的代码检查字符串数据是如何获取的。

    如果由于某种原因无法实现,请提供以下信息:

    调用存储过程的完整代码 参与存储过程的所有表的 DDL 获取数据的完整客户端代码

魔鬼总是在细节中。我们应该只了解您的情况与上面的工作示例代码有何不同。

【讨论】:

请同时提供获取数据的客户端代码。 如果有一个已知案例,如果它指出了一个 Oracle 错误,那就太好了。【参考方案2】:

我试图通过迁移到ODP.NET 来解决问题,因为System.Data.OracleClient 已被Microsoft 弃用,如here 所述 ,但问题没有解决。以下是问题的解决方法:

    安装在机器12.1.0.2.2上的Oracle客户端版本 Output parameter truncation 错误在 Oracle 文档中提到为 Bug21616079 Oracle 已在 12.2.0.1.0 版本中提供修复,如 Oracle 文档 here 中所述。 所以从12.1.0.2.2 升级到版本12.2.0.1.0 为我解决了这个问题,因为Oracle 只在这个版本中给出了修复,官方Oracle 文档中提到了这个问题,我在上面第3 点提供了链接。

【讨论】:

我也有同样的问题。我有 12.2.0.1.0,但输出 varchar 仍被截断为“TR”为真 虽然从 Oracle 12.1 更新到 12.2,但我仍然遇到同样的问题。【参考方案3】:

我在 64 位 Windows 操作系统上都遇到了客户端 10g 和服务器 11g 的相同问题,我通过在 IIS 上托管我的 .net 应用程序并将 app_pool 的高级设置“启用 32 位应用程序”更改为 False 来规避它。

【讨论】:

以上是关于使用 12c 客户端截断的存储过程 OUTPUT VARCHAR2 值的主要内容,如果未能解决你的问题,请参考以下文章

存储过程变量中存储SQL语句被截断的问题

db2存储过程动态sql被截断

存储过程是不是可以调用截断 veiw 表并将数据输入到 MySql 中的视图表中[关闭]

sql 存储过程,删除Postgres中所有表中的所有条目而不删除或截断,并使用可选的忽略。

sql 存储过程 output参数的使用

截断表的权限