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

PL / SQLを介してOracleをエクスポートしようとすると、日付は0000-00-00になります。

    その列に格納されている値は有効な日付ではありません。 dumpの最初のバイト 世紀である必要があります。これは、Oracleサポートノート69028.1によると、「excess-100」表記で格納されます。つまり、100+実際の世紀の値である必要があります。したがって、1900は119、2000は120、5500は155になります。したがって、44は-5600を表します。保存した日付は、実際には5544-09-14 BCを表しているようです。 。 Oracleは、年が-4713〜 + 9999の日付のみをサポートしているため、これは認識されません。

    これはかなり簡単に再現できます。最も難しいのは、そもそも無効な日付をデータベースに取り込むことです。

    create table t42(dt date);
    
    Table created.
    
    declare
        d date;
    begin
        dbms_stats.convert_raw_value('2c9c090e010101', d);
        insert into t42 (dt) values (d);
    end;
    /
    
    PL/SQL procedure successfully completed.
    
    select dump(dt), dump(dt, 1016) from t42;
    
    DUMP(DT)
    --------------------------------------------------------------------------------
    DUMP(DT,1016)
    --------------------------------------------------------------------------------
    Typ=12 Len=7: 45,56,9,14,1,1,1
    Typ=12 Len=7: 2d,38,9,e,1,1,1
    

    したがって、これには、同じデータを含む単一の行があります。 alter sessionを使用する 有効な日付のように見えます:

    alter session set nls_date_format = 'DD-Mon-YYYY';
    select dt from t42;
    
    DT
    -----------
    14-Sep-5544
    
    alter session set nls_date_format = 'YYYYMMDDHH24MISS';
    select dt from t42;
    
    DT
    --------------
    55440914000000
    

    しかし、明示的な日付マスクを使用すると、ゼロになります:

    select to_char(dt, 'DD-Mon-YYYY'), to_char(dt, 'YYYYMMDDHH24MISS') from t42;
    
    TO_CHAR(DT,'DD-MON-Y TO_CHAR(DT,'YY
    -------------------- --------------
    00-000-0000          00000000000000
    

    そして、私があなたの手順を実行した場合:

    exec dump_table_to_csv('T42');
    

    結果のCSVは次のようになります:

    "DT"
    "0000-00-00T00:00:00"
    

    違いは、ノート69028.1に記載されているように、日付を表示しようとするものは内部日付データ型12に固執し、ゼロを表示しようとするものは外部データ型13を使用していることです。

    つまり、プロシージャは何も悪いことをしておらず、エクスポートしようとしている日付は内部的に無効です。それが何であるかを知らない限り、それはあなたの出発点を与えられそうにないようですが、それを推測するか無視する以外にあなたができることはあまりないと思います。おそらく、データがどのように挿入されたかを知っていて、データがどのように破損したかを理解できる場合を除きます。

    私がここで行ったことよりも、OCIプログラムからのものである可能性が高いと思います。この「生の」トリックはもともとここからのものでした。ノート331831.1も参照してください。そして、この前の質問は多少関連しています。




    1. PostgreSQLのテーブルを参照する保存された関数を一覧表示します

    2. Oracleを学ぶ前に知っておくべきこと

    3. SQL Server(T-SQL)でパーティションを2つに分割する

    4. MySQLに保存するためにIPv6をバイナリから変換する方法