1

Oracle ADO.Net プロバイダー (DevArt のdotConnect Universal ) で次のコードを使用しています。面白いのは、時々機能し、ほとんどの場合スローすることですDevart.Data.Oracle.OracleException: ORA-01722: invalid number

  string sql = "SELECT DISTINCT  B.PRICE_TIER_KEY,b.label, a.INSERT_DATE   AS PriceEffectiveDate,B.PROGRAM_KEY AS PRICE_PROGRAM_KEY FROM GHX_MEMBER_TIER A INNER JOIN VHA_INT_PRICE_TIER B ON A.SRC_ID_VALUE = B.PRICE_TIER_KEY WHERE RowNum <=100";

        DbProviderFactory dpf = DbProviderFactories.GetFactory(System.Configuration.ConfigurationManager.ConnectionStrings["Con_ORA_DevArt"].ProviderName);
        DbConnection conn = dpf.CreateConnection();
        conn.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["Con_ORA_DevArt"].ConnectionString;

        DbCommand dbcmd = dpf.CreateCommand();
        dbcmd.Connection = conn;
        //dbcmd.Connection = uniConnection1;
        dbcmd.CommandText = sql;
        dbcmd.CommandType = CommandType.Text;
        dbcmd.CommandTimeout = 0;


        DataTable table = new DataTable();



        try
        {
            System.Data.Common.DbDataAdapter da = dpf.CreateDataAdapter();
            da.SelectCommand = dbcmd;
            // Fill the DataTable.

            da.Fill(table);
        }
        catch (Exception ex)
        {
            throw;
        }
        finally
        {
            if (conn != null && conn.State != ConnectionState.Closed)
            {
                conn.Close();
                conn.Dispose();
            }
            if (dbcmd != null)
            {
                dbcmd.Dispose();
            }
        }
4

2 に答える 2

5

ORA-01722 はデータ変換エラーです。文字列に数値以外の値が含まれている場合に、文字列を数値に変換しようとすると発生します。これは、TO_NUMBER() キャストを使用して明示的に発生するか、JOIN または WHERE 句で異なるデータ型の列を使用して暗黙的に発生する可能性があります。

これで、すべて間違った情報を投稿したことがわかります。重要なのは、関連するテーブルのデータ構造と内容です。問題が発生する可能性が最も高い候補は、結合内の 2 つの列、SRC_ID_VALUE と PRICE_TIER_KEY です。これらは両方とも数値列ですか、それとも両方とも文字列ですか? 1 つが数値で、もう 1 つがそうでない場合、文字列 1 には数値データのみが含まれていますか?

Oracle は比較を試みる前に文字列列を数値にキャストするため、これは重要です。

たとえば、table1 にこのデータがある場合...

 1234
10789

...そしてtable2にはこのデータがあります...

'1234'
'45o7'

最初の行は正常に結合されますが、2 番目の行は ORA-01722 をスローし、クエリを脱線させます。

これを回避するには、TO_CHAR() を使用して数値列を文字列に変換します。これにより、Oracle はその列のインデックスを使用できなくなります。ほとんどの場合、両方のテーブルで完全なテーブルスキャンを実行しているだけなので、おそらく問題にはなりませんが、より正確なクエリでは問題になる可能性があります。


「それはオラクルの恐ろしい機能だと思います。」

文字列を数値にキャストすると、並べ替え順序が変更されます。これ ...

「1」、「10」、「2」、「21」、「3」

・・・こうなります・・・

1、2、3、10、21

もちろん、元のインデックスは使用できません。

回避策はありますが、やや複雑です。

  1. 入力文字列をテストし、数値の場合は数値を返し、そうでない場合は null を返す関数を作成します。
  2. その関数を使用して関数ベースのインデックスを作成します。

    GHX_MEMBER_TIER(is_a_number(SRC_ID_VALUE)) にインデックス src_id_num_fbi を作成します。

  3. クエリでその関数を使用します。

    ... ON is_a_number(A.SRC_ID_VALUE) = B.PRICE_TIER_KEY

これが努力する価値があるかどうかを判断できるのはあなただけです。

于 2013-02-07T06:20:16.257 に答える
4

に変更ON A.SRC_ID_VALUE = B.PRICE_TIER_KEYしてみてくださいON A.SRC_ID_VALUE = to_char(B.PRICE_TIER_KEY)

マニュアルから:「文字値を数値と比較するとき、Oracleは文字データを数値に変換します。」. その暗黙的な変換は常に安全であるとは限りません。代わりに、Oracle に数値を文字列に変換させる必要があります。

于 2013-02-07T06:18:08.237 に答える