web-dev-qa-db-ja.com

ストアドプロシージャOUTPUTVARCHAR2値は12cクライアントを使用して切り捨てられました

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.size4000に増やしましたが、それでも値が切り捨てられています。これに対する解決策はありますか?サーバー上に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;
9
ubaid ashraf

前述のようにODP.NETMicrosoftによって非推奨になっているため、System.Data.OracleClientに移行して問題を解決しようとしました ここ 、しかし問題は解決されませんでした。以下は、問題がどのように解決されたかです。

  1. マシンにインストールされているOracleクライアントのバージョン12.1.0.2.2
  2. Output parameter truncationバグはOracleドキュメントでBug21616079として言及されています
  3. Oracleは、Oracleドキュメント here に記載されているように、バージョン12.2.0.1.0で修正を行いました。
  4. したがって、12.2.0.1.0からバージョン12.1.0.2.2にアップグレードすると、この問題が修正されました。Oracleはこのバージョンでのみ修正を行い、これは私が提供した公式のOracleドキュメントに記載されています。上記のポイント3のリンク。
2
ubaid ashraf

サーバー12.1.0.1.0に接続しているクライアントバージョン11.2.0.1.0の問題を再現できませんでした。 Oracle 12cクライアントが出力変数を切り捨てる場合は 既知のケース ですが、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}]");
        }
    }
}

質問を進めるには、次のことを行ってください。

  1. 可能であれば、上記のテストテーブルとストアドプロシージャを作成し、上記のコードで文字列データがどのようにフェッチされるかを確認します。
  2. 何らかの理由でそれが不可能な場合は、次の情報を提供してください。

    • 呼び出されたストアドプロシージャの完全なコード
    • ストアドプロシージャに関与するすべてのテーブルのDDL
    • データをフェッチする完全なクライアントコード

悪魔は常に細部にあります。あなたの場合、上記の模範的なコードの動作と何が違うのかを理解する必要があります。

5
CodeFuller