↓うpひろいもの

スポッ
こんばんわ。
toritoriです。
Oracle話第3弾。
今回はDBリンクのお話です。
あるサブシステムで、プログラムに不具合があった関係で
データがちょいとおかしくなってしまいました。
プログラムのバグを直すのはもちろんのこと、
おかしくなったデータの復旧もしないといけません。
そこで復旧の手順として
①開発系DBにバックアップデータを戻す
②開発→本番サーバのDBリンクを使用して、差分データの件数確認。
条件を指定して、オンライン訂正されているものを除く
③②で抽出したデータのみを更新するような無名SQL文を作成して実行
というような流れで復旧することにしました
(この手法はよく使います。楽なので)
とりあえずこのような場合、データの復旧が最優先ですので
すぐさま①②まで実行し、件数の確認まで終わりました。
そして復旧してもいいかをお客さんに確認し
いざ③を実行したのですが…
Ora-020xx …
Ora-020xx …
Ora-00600 …
Ora-00607 …
Ora-06512 …
(大体内部エラー)
エェェ(´Д`)ェェエ
なんでなんで?
無名SQLを確認しましたが、パっと見た感じは全然問題なさそう…
↓ちなみにこんな感じ
DECLARE
CURSOR cur IS
SELECT … ②の条件
;
BEGIN
FOR rec IN cur LOOP
UPDATE …(DBリンク先のテーブルを更新)
WHERE …
END LOOP;
END;
というか前にも似たような事はやってるのにな~
とりあえずその場では原因がわからなかったので、
②の結果をテキストに落とし、
それを読み込んで更新するようなバッチを作成して事なきを得ました。
しかしなんとも腑に落ちなかったので
後日改めてそのSQLを確認したところ
原因っぽいのをハケーン!
それは、↓のUPDATE文の部分。
FOR rec IN cur LOOP
UPDATE テーブル名@DBリンク名 set 列名1=rec.列名1
WHERE キー列1 = rec.キー列1 and …
END LOOP;
普通、DBリンクを使用したテーブルの項目を使う場合、
別名を使わないとエラーになるんです。(たしか)
なので、上記のSQLを
FOR rec IN cur LOOP
UPDATE テーブル名@DBリンク名 別名A set 別名A.列名1=rec.列名1
WHERE 別名A.キー列1 = rec.キー列1 and …
END LOOP;
というようにしないといけませんでしたね
(よくよく考えると当たり前…)
直接SQL文を投げると、通常のエラーを返してくれることが多いですが、
プロシージャや無名PL/SQL文などで同じ文を投げると
内部エラーになることが良くあります。
ローダとかの制御文とかで間違ったSQL文を書いても
内部エラーになることがあるみたいです…(というかあります)
エラー出てるんだからどっちでもいいじゃん!
という人もいるかもしれませんが、
内部エラーというのは特殊なエラーなのです。
内部エラーが出ると…
①びっくりする
②オラクルが落ちないか心配になる
③管理者に何か聞かれる(今の出向先の話)
オラクルってやっぱバグも多いから、変なエラーもたまに出るんですよ。
オラクルの人、ちゃんとデバッグして!
特にプロシージャ関係多いですよ!( ゜Д゜)ノ=

スポッ
こんばんわ。
toritoriです。
Oracle話第3弾。
今回はDBリンクのお話です。
あるサブシステムで、プログラムに不具合があった関係で
データがちょいとおかしくなってしまいました。
プログラムのバグを直すのはもちろんのこと、
おかしくなったデータの復旧もしないといけません。
そこで復旧の手順として
①開発系DBにバックアップデータを戻す
②開発→本番サーバのDBリンクを使用して、差分データの件数確認。
条件を指定して、オンライン訂正されているものを除く
③②で抽出したデータのみを更新するような無名SQL文を作成して実行
というような流れで復旧することにしました
(この手法はよく使います。楽なので)
とりあえずこのような場合、データの復旧が最優先ですので
すぐさま①②まで実行し、件数の確認まで終わりました。
そして復旧してもいいかをお客さんに確認し
いざ③を実行したのですが…
Ora-020xx …
Ora-020xx …
Ora-00600 …
Ora-00607 …
Ora-06512 …
(大体内部エラー)
エェェ(´Д`)ェェエ
なんでなんで?
無名SQLを確認しましたが、パっと見た感じは全然問題なさそう…
↓ちなみにこんな感じ
DECLARE
CURSOR cur IS
SELECT … ②の条件
;
BEGIN
FOR rec IN cur LOOP
UPDATE …(DBリンク先のテーブルを更新)
WHERE …
END LOOP;
END;
というか前にも似たような事はやってるのにな~
とりあえずその場では原因がわからなかったので、
②の結果をテキストに落とし、
それを読み込んで更新するようなバッチを作成して事なきを得ました。
しかしなんとも腑に落ちなかったので
後日改めてそのSQLを確認したところ
原因っぽいのをハケーン!
それは、↓のUPDATE文の部分。
FOR rec IN cur LOOP
UPDATE テーブル名@DBリンク名 set 列名1=rec.列名1
WHERE キー列1 = rec.キー列1 and …
END LOOP;
普通、DBリンクを使用したテーブルの項目を使う場合、
別名を使わないとエラーになるんです。(たしか)
なので、上記のSQLを
FOR rec IN cur LOOP
UPDATE テーブル名@DBリンク名 別名A set 別名A.列名1=rec.列名1
WHERE 別名A.キー列1 = rec.キー列1 and …
END LOOP;
というようにしないといけませんでしたね
(よくよく考えると当たり前…)
直接SQL文を投げると、通常のエラーを返してくれることが多いですが、
プロシージャや無名PL/SQL文などで同じ文を投げると
内部エラーになることが良くあります。
ローダとかの制御文とかで間違ったSQL文を書いても
内部エラーになることがあるみたいです…(というかあります)
エラー出てるんだからどっちでもいいじゃん!
という人もいるかもしれませんが、
内部エラーというのは特殊なエラーなのです。
内部エラーが出ると…
①びっくりする
②オラクルが落ちないか心配になる
③管理者に何か聞かれる(今の出向先の話)
オラクルってやっぱバグも多いから、変なエラーもたまに出るんですよ。
オラクルの人、ちゃんとデバッグして!
特にプロシージャ関係多いですよ!( ゜Д゜)ノ=