2017-08-23 15 views
0

クライアントの1人が、asp.net/oracleに基づいてかなり大きなPMSを継承しました。残念ながら、私のオラクル知識は最小限で、いくつかの問題があります。 -Oracleストアドプロシージャ出力パラメータ値

オリジナルのシステムはOracle 9をベースにしており、MSのSystem.Data.OracleClientドライバを使用しています。新しいクライアントは、Oracle 12cのアプライアンスボックスを選択しましたし、データベースが正常に転送されましたが、既存のストアドプロシージャのいくつかは問題である - パラメータがこのコードを使用して初期化される

PROCEDURE IS_PROJECT_LEADER(A_PROJ_ID NUMBER, A_ACCOUNT_ID VARCHAR2, A_SUCCESS OUT VARCHAR2) 
IS 
    v_COUNT NUMBER; 
BEGIN 
    --Check if Project Leader, or in the Project Leader Group 
    SELECT COUNT(*) 
    INTO v_COUNT 
    FROM PROJ_ACCOUNT 
    WHERE PROJ_ID = A_PROJ_ID 
    AND  ACCOUNT_ID = A_ACCOUNT_ID 
    AND  (SYS_ROLE_ID = 3 OR IS_PL_GROUP = 'Y'); 

    IF v_COUNT > 0 THEN 
     A_SUCCESS := 'Y'; 
    ELSE 
     A_SUCCESS := 'N'; 
    END IF; 
END; 

例えば - わからないが、これは正しい場合oracleの世界ではないか?

while (rdr.Read()) 
{ 
    prm = new OracleParameter(); 
    prm.ParameterName = rdr["ARGUMENT_NAME"].ToString(); 
    switch (rdr["DATA_TYPE"].ToString()) 
    { 
    case "NUMBER": 
     prm.OracleType = OracleType.Number; 
     break; 
    case "VARCHAR2": 
     prm.OracleType = OracleType.VarChar; 
     if (rdr["IN_OUT"].ToString() == "OUT" 
     || rdr["IN_OUT"].ToString() == "IN/OUT") 
     { 
     prm.Size = 4000; 
     } 
     break; 
    case "DATE": 
     prm.OracleType = OracleType.DateTime; 
     break; 
    case "BLOB": 
     prm.OracleType = OracleType.Blob; 
     break; 
     case "CLOB": 
     prm.OracleType = OracleType.Clob; 
     break; 

     } 
    switch (rdr["IN_OUT"].ToString()) 
    { 
    case "IN": 
     prm.Direction = ParameterDirection.Input; 
     break; 
    case "OUT": 
     prm.Direction = ParameterDirection.Output; 
     break; 
    case "IN/OUT": 
     prm.Direction = ParameterDirection.InputOutput; 
     break; 
    } 
    prm.Value = System.DBNull.Value; 
    cmd.Parameters.Add(prm); 
} 

現在のシステムでのA_SUCCESSの戻り値は、常に空の文字列です。 MS OracleClientを削除して最新のOracle ODP.netドライバを使用すると、必要な文字列値が返されます。データ型を変更し、A_SUCCESSの型をCHARに戻すと、すべてが機能します。 MSが推奨するようにODPクライアントに移行する計画がありますが、システムはかなり大きく、ひどく設計されているため、何ヶ月も実行されません。

これはドライバの問題であり、私が気づいていないいくつかの難解なOracleの機能性ではないと思いますが、

+0

'rdr'とは何ですか?また、' CASE'ステートメントはどのような値に一致しますか? c#コードを手動で作成する場合(実際にはそうであるように、 'rdr'変数の内容から動的に構築する)、同じ例外がスローされますか?この[質問](https://stackoverflow.com/q/27032296/1509264)のコメントには、さまざまな提案があります。 – MT0

+0

@ MT0あなたが与えたスレッドは本質的に私が言っていたことを言っています。パラメータの長さが定義されていることを確認する。 – LAS

+0

@LAS私がリンクしているスレッドは、C#でパラメータサイズを設定することを提案しています(また、私が参照していたプロシージャを段階的にデバッグする方法についても他の提案もしています) - あなたの投稿はまだ長さを設定するように思われますOracleプロシージャの一時変数を介してどちらの方法も、9iから12cまでの任意のバージョンのOracleとのインタフェースに使用されていた多くの言語/ドライバのいずれにも必要ありません。長さが必要なMicrosoft C#ドライバには奇妙な変種があるかもしれませんが、Oracleプロシージャの内部を変更する必要はありません。 – MT0

答えて

0

私は現在、Oracle 12c/c#.Netで作業しています。私たちは、Microsoftのドライバよりも成功していることが分かったOracleのODPドライバを使用します。

私はコメントのために私の答えを述べている方法を変更しています。しかし、私はそれほど遠いとは思わない。スレッドに受け入れられた答え、Exception while executing stored procedure odp.netは、MTOによって与えられたもので、varchar2フィールドのサイズまたは長さをパラメータ定義に追加しました。これは私が言うことです。 A_SUCCESSはデータベースに格納されていませんが、プロシージャ内で実行するには記憶域が必要です。ここで

は、私たちが知っているものです:

  1. あなたがCHARに手順データ型を変更したときにそれが働きました。
  2. c#側のパラメータ(prm)の設定は変更されませんでした。これは、コール側プログラムがVARCHAR2と同じ設定をCHARの場合と同じように使用したことを意味します。
  3. CHARのデフォルトの長さは1です。VARCHAR2の長さを設定する必要があります。
  4. 9iでは動作しましたが、12cでは動作しませんでした。 VARCHAR2の格納方法は9iと12cの間で変更されました。
  5. ODPと連携します。 ODPでVARCHAR2の長さを設定する必要があるため、長さの問題であればこれは奇妙です。

私はこれを試してみた:PRMの

  1. 印刷内容を各パラメータの実際に設定されていますかを確認します。
  2. A_SUCCESSがVARCHAR2として設定されていない場合は、それが正しいことと、長さまたはサイズが設定されていることを確認してください。
  3. 私はそれが長いことを知っていますが、私はローカル変数を使用してプロシージャでA_SUCCESSの長さを設定しようとします。データ型をCHARに変更したので、私はそれを提案します。
+0

これはプロシージャーです。 'A_SUCCESS'の結果をデータベースに書き込まないので、ブロックに関する話は誤解を招き、一時変数を作成する必要はありません。匿名のPL/SQLブロックからOPのコードを実行してみてください。正常に完了します(OPの状態はODP.netドライバを使用して正常に実行されます)ので、Oracleコード(Oracleのどのバージョンでも問題ありません) 。 – MT0

0

ありがとうございました。クライアントは、最も論理的なソリューションと思われるように、ODPへの変換を開始することを決めました。期待どおりに働く。

関連する問題