sql >> データベース >  >> RDS >> Oracle

数値列にOracle2ハイフンがありますか?

    それは何の意味もありませんし、「何のためにも」ではありません。あなたのデータは壊れています、私は恐れています。 - はテーブルの実際の値ですが、数値ではありません。 Oracleの数値の内部表現は、それにアクセスできる場合はノート1031902.6で説明されています。または、これそうでない場合は説明します 。それが本当に負の数だった場合、最後の16進バイトは66になります。それが表示される数をダンプすると、2つではなく1つのマイナス記号が付けられ、意味がなくなります。

    select dump(-1331013400000000000000000000, 1016) from dual;
    
    DUMP(-1331013400000000000000000000,1016)
    ----------------------------------------
    Typ=2 Len=6: 31,58,46,64,43,66           
    

    Oracleで無効な数値を作成するのは簡単ではありませんが(そうなるとは思わないでしょう)、これは私が以前に使用した方法です。二重マイナス記号とそれらがすべて同じ長さであることを除いて、手がかりの1つは、ダンプされた値を数値に戻すと同じ結果が得られないことです。

    create table t42(value number);
    
    declare
      n number;
    begin
      dbms_stats.convert_raw_value('32ea004366', n);
      insert into t42 (value) values (n);
    end;
    /
    
    select value from t42;
    
                                     VALUE
    --------------------------------------
               -<3:13400000000000000000000
    

    これはOracle9iによるもので、現在8iデータベースに近いため、結果が少し異なる場合があります。

    to_number(value)を実行できない もちろん、これも大きな手がかりです。暗黙のto_char()があります そうすると、テキスト表現を数値に変換しようとします。これがエラーの説明です。 to_char() 興味深いことに、値は単純な選択が行うこととも一致しません。データでそれを行った場合も同じエラーが表示されます。

    select to_number(value) from t42;
    select to_number(value) from t42
                     *
    ERROR at line 1:
    ORA-01722: invalid number
    
    select to_char(value) from t42;
    
    TO_CHAR(VALUE)
    ----------------------------------------
    -`003400000000000000000000
    

    悪いデータがどこから来たのかを知らず、元のデータがまだ残っていない限り、おそらくこれらの値を救うことはできません。あなたができる最善のことはそれを無視するか、移行するものに置き換えることだと思います-フィールドがnull可能の場合は null 安全なオプションです。そうでない場合は、魔法の値を選択する必要があると思います。

    影響を受ける行の識別と変更は、関数を介して実行できます。おそらく次のようなものです:

    create or replace function null_bad_number(value number)
    return number deterministic as
      tmp_value number;
      invalid_number exception;
      pragma exception_init(invalid_number, -1722);
    begin
      select to_number(value) into tmp_value from dual;
      return value;
    exception
      when invalid_number then
        return null;
    end;
    /
    

    以前に作成された同じ無効な値と1つの有効な値:

    insert into t42 (value) values (0.9574875526618150);
    
    select * from t42;
    
         VALUE
    ----------
    -`.003E+24
    .957487553
    
    update t42 set value = null
    where value is not null
    and null_bad_number(value) is null;
    
    1 row updated.
    
    select * from t42;
    
         VALUE
    ----------
    
    .957487553
    

    決して理想的ではありませんが、現時点では、できることを救っているだけだと思います。行を更新するのではなく削除したり、値を別の値に設定したりできます。これは、続行する方法によって異なります。

    Oracleを関与させて、何が起こったのかを理解し、元の値に戻すためのトリックがあるかどうかを確認することもできますが、これはありそうもないことですが、多くのサポートが得られるかどうかはわかりません。そのような古いバージョンのデータベース。

    もちろん、破損がいつどのように発生したかを知らなくても(おそらく危険なインポートを介して、またはバグのあるOCIプログラムを介して)、その列と他の場所の両方で、他のすべてのデータの有効性を疑問視する必要があります。この場合、破損は非常に均一に見えます(すべての無効な値は同じ方法で作成されているようです)ので、問題ない可能性があります。ただし、一般的に、誤ったバイトを内部値に入れるものは、間違った、しかしそれでも有効な値を偽造する可能性があります。ほぼ正しく見える場合もあれば、元の期待値から桁違いに見える場合もあり、実際に判断する方法はありません。




    1. データベースパーティションの最適サイズ

    2. 単一のODBCExecuteNonQuery(C#)での複数の挿入ステートメント

    3. PHP / MySQLi:INSERTでのSQLインジェクションを防ぐ方法(コードが部分的に機能している)

    4. 文字列からuniqueidentifierへの変換時に変換に失敗しました