2

MySQL にロードできるように、CSV に取得しようとしている Oracle .dmp ファイルを継承しました。

私が使用している一般的なアプローチについては、こちらで説明しています。しかし、私は1行に問題があります。次のように 5544-09-14 の日付が含まれています。

alter session set nls_date_format = 'dd-MON-yyyy';
select OID, REF, TRADING_DATE From LOAN WHERE REF = 'XXXX';

OID REF                  TRADING_DATE
--- -------------------- ------------
1523 XXXX                 14-SEP-5544

これは、入力日付を検証しなかったレガシー システムからのガベージ データです。しかし、データをエクスポートする PL/SQL 関数がこの値でチョークするのはなぜでしょうか?

その行を「0000-00-00T00:00:00」の TRADING_DATE 値でエクスポートしますが、その理由がわかりません。

SELECT dump(TRADING_DATE) FROM LOAN WHERE REF = 'XXXX';

DUMP(TRADING_DATE)
--------------------------------------------------------------------------------
Typ=12 Len=7: 44,156,9,14,1,1,1

SELECT to_char(trading_date, 'YYYYMMDDHH24MISS') FROM LOAN WHERE REF = 'XXXX';
TO_CHAR(TRADIN
--------------
00000000000000
4

1 に答える 1

8

その列に格納されている値は有効な日付ではありません。の最初のバイトは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

したがって、これには同じデータを持つ単一の行があります。I を使用する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 プログラムからのものである可能性が高いと思います。この「生の」トリックはもともとhereからのものでした。ノート 331831.1 も参照してください。そして、この前の質問は多少関連しています。

于 2012-09-17T09:13:49.287 に答える