rm /blog

IT系技術職のおっさんがIT技術とかライブとか日常とか雑多に語るブログです。* 本ブログに書かれている内容は個人の意見・感想であり、特定の組織に属するものではありません。/All opinions are my own.*

【Oracle】DEFAULT付の項目にimpdpするとORA-38500が発生することに対するちょっとした愚痴

特定のテーブルAからデータをexpdpして、別スキーマにある同名テーブルAに、default付きの項目をaddしたA'をつくり、A→A'にimpdpすると、「ORA-38500: Unsupported operation: Oracle XML DB not present」というOracleエラーが発生する。
これが意味不明。
…っていう愚痴の記事。

どうも「dmpファイル側には存在しない項目をdefault付きでaddしたテーブルにはimpdpができない」ということでエラーになってるっぽいのだが、このエラーメッセージからは全くそれが連想できない。
「impdp ORA-38500」とかでググってもそれっぽい記事も出てこないので最初全くわからなかった。
なんとなく項目の違いがあるせいかもってのは疑いのネタにできたが、それにしたってこのエラーメッセージはわかりづらすぎる。
Oracle側の内部事情がいろいろあるんだろうが、もう少しわかりやすいメッセージにできなかったもんかね。
(まあOracleのエラーがわかりづらいのは今に始まったわけじゃないのでこれもその仲間というだけの話なのだけど)



 


【もくじ】

1.失敗時の事例
2.成功時の事例
3.実験時の事例




       1.失敗時の事例

(1)とあるスキーマS1に以下のテーブルTEST_TAB1を作成する。

create table TEST_TAB1(
    test_no number(10)
   ,test_name varchar2(100)
)
/


(2)適当に3件くらいデータをいれておく。

insert into TEST_TAB1 select 1,'テスト1' from dual;
insert into TEST_TAB1 select 2,'テスト2' from dual;
insert into TEST_TAB1 select 3,'テスト3' from dual;


(3)そんでexpdpする。

< expdp S1USER/S1PASS@TESTDB tables=TEST_TAB1 content=DATA_ONLY direcorty=TEST_DIR dumpfile=S1_TEST_TAB1.dmp logfile=S1_TEST_TAB1_expdp.log


(4)移行先のスキーマS2にも同じ定義でテーブルTEST_TAB1を作成する。
DDLは(1)と同様なので省略。

(5)default付きの項目をaddする

alter table TEST_TAB1 add( TEST_FLG number(1) default 0);


(6)そんでimpdpする。

< impdp S2USER/S2PASS@TESTDB content=DATA_ONLY direcorty=TEST_DIR dumpfile=S1_TEST_TAB1.dmp REMAP_SCHEMA=S1:S2 table_exists_action=truncate logfile=S2_TEST_TAB1_impdp.log


と、冒頭書いた「ORA-38500: Unsupported operation: Oracle XML DB not present」というエラーが発生する。




       2.成功時の事例

ちなみにdefaultがついていなければ項目addしててもimpdpは成功する。
つまり上記の(5)を(5')として以下のように変更し
(5')defaultなしの項目をaddする

alter table TEST_TAB1 add TEST_FLG number(1) ;


このあと(6)なら問題なし。impdpは成功する。




       3.実験時の事例

ひょっとしてREMAP_SCHEMAがいけないのか?と思って、
つまり「別スキーマへの移行がネックになってるのか?」と思って、同一スキーマ間でのテーブル移送を実験してみたが、結果は同じだった。
(まあこの場合はREMAP_SCHEMAがないけどREMAP_TABLEがあるからね…)

(4')同じスキーマ名に同じレイアウトだが違う名前のテーブルTEST_TAB2をつくり

create table TEST_TAB2(
    test_no number(10)
   ,test_name varchar2(100)
)
/


(5')default付きの項目をaddする

alter table TEST_TAB2 add( TEST_FLG number(1) default 0);


(6')そんでimpdpする。

< impdp S2USER/S2PASS@TESTDB content=DATA_ONLY direcorty=TEST_DIR dumpfile=S2_TEST_TAB1.dmp REMAP_TABLE=TEST_TAB1:TEST_TAB2 table_exists_action=truncate logfile=TEST_TAB2_impdp.log


これも同様。「ORA-38500: Unsupported operation: Oracle XML DB not present」が発生する。




DEFAULT付きの項目に関しては別件でも悩まされたことがある。
個人的には、「初期値があるかないか」というだけで、「項目」としての存在、というのか、概念、というのか、その辺りが大きくブレることはないと思っていたのだが、Oracle的には結構扱いが違うようだな、と改めて知らしめられた。
正直個人的にもDEFAULTってそんなに好きではない(できれば使いたくない)のだが、
-って書くとこの流れではもはやこの問題のことを知らなかった負け惜しみの言い訳みたいに聞こえるがw、まじなのだ。
 テーブルへデータを書き込む役割が、アプリケーションとDB定義で分離されているのが気持ち悪い。
 「この項目はアプリ側、この項目はDB定義」っていうようになっているのがわかりづらい、っていう風に言い換えてもいい。
 この切り分けは知ってる人(設計した人)でないと直感的にわかりづらく、経験上保守性もよくない。
 ので、あまり好きではない。(言い訳以上)-
諸々の事情でDEFAULTを使わざるを得ない場面というのも実際ちょこちょこ遭遇しているのも事実であり、
そうしたときにこの辺の問題に悩まされることを一つの経験談として生かしていけるようにならなければならん、と思ったのである。