SQL*Loaderを使ってデータをインポートするのですが、既存データが存在するテーブルにインポートするため、実行前に、条件に一致する一部のデータを削除します。
ですが、SQL*Loaderでインポートが失敗した際には、元に戻したいと思っています。
そういう場合に、SQL*PlusからDELETEのSQL文を実行してから、SQL*Loaderを起動してインポートするとなると、SQL*Plusから抜けた時点でCOMMITされてしまいますよね?そのためSQL*LoaderでインポートがエラーになってROLLBACKされても、削除されたデータは元に戻らないですよね・・・。
全件削除なら、CTLファイル内でREPLACEを指定してインポートするのですが・・・
データの一部削除とSQL*Loaderでのインポートを一連の処理として、エラーの際にはROLLBACKさせられる方法はありますでしょうか?
よろしくお願いします。
No.5ベストアンサー
- 回答日時:
一つ言い忘れていたので...
MERGE文は9iからの機能ですので、もし8や8iをお使いであれば使用できません。
MERGEを使わない方法としてはinsteadトリガと呼ばれるものがあります。
トリガには
beforeトリガ(実行前に自動的に実行)
afterトリガ(実行後に自動的に実行)
logonトリガ(ログオン直後に自動的に実行)
など色々ありますが
insteadトリガは(実行内容の変わりにトリガのみを実行)という機能になります。
今回のトリガの内容までは詳しく記述しませんがinsertが来たら既存行と一致するかしないかによって
代わりにupdateを実行するかinsertを実行するかを振り分けれます。
insteadトリガを使うときに気をつけなければいけないのは
VIEWにしか定義できないことと(必然的に本来挿入をしたい表を参照するVIEWを作成し、
そのVIEWにinsteadトリガを定義しておいてからVIEW目掛けてSQL*loaderでINSERTを行うことになります。)
SQL*Loaderはデフォルトではある程度の単位で勝手にcommitが切られてしまうので
bindsizeやrowsといったSQL*Loaderのパラメータを大きめに設定してやる必要があります。
(途中でcommitを切ってしまっていると挿入の途中で失敗してしまった場合中途半端な
状態でcommitされてしまい、rollbackもできなくなるため)
緊急で質問していたにも関わらず、お返事が大変遅れまして申し訳ありません。
(当日以降、お返事ができない環境になってしまいました)
> SQL*Loaderはデフォルトではある程度の単位で勝手にcommitが切られてしまう
というのも知りませんでした・・・。
> VIEWにinsteadトリガを定義しておいてからVIEW目掛けてSQL*loaderでINSERTを行うことになります
というのが、一番本来の目的(LoaderでのエラーでRollbackしたい、或いはLoaderでのデータインポートの際にUpdateのような形をとりたい)に叶っている気が致します。
お返事、本当にありがとうございました!
No.4
- 回答日時:
別表へのSQL*LoaderでのINSERT+
MERGE文で解決できないでしょうか。
まず、本来の表と全く同じ定義の空の表を
create table temp_table as select * from moto_table;
で作成し、そこにSQL*LoaderでINSERTします。
SQL*LoaderによるINSERTが失敗すればtemp_tableを空にして失敗で終わりです。
成功すれば次に以下のようなMERGE文で
merge into moto_table m using temp_table t
on (e.id = t.id)
when matched then update set e.comment=t.comment
when not matched then insert (id,comment)
values(id,comment);
(id列が一致すればcomment列を上書き、一致しなければINSERT)
1トランザクションにてtemp_tableからmoto_table
へデータを更新または挿入します。
成功すればcommitすれば良いですし、失敗すれば自動的にROLLBACKされた後、
SQL*Loaderの時と同様にtemp_tableを空にして終わりと
なります。
性能の面などの問題などもありますがいかがでしょうか?
Margeというのは初めて知りました・・・
なるほど、空の状態でインポートしておいて、そこに「元からあるもので、インポートされていないデータを追加する」ということですね!
検討したいと思います。
ありがとうございました。
No.3
- 回答日時:
こんにちは。
具体的な方法は思いついていなくて申し訳ないのですけども
SQL*Loaderの代わりに外部表を使用し、SQL文によるデータの参照と
インポートを行う事で、一連の処理をROLLBACKする事ができないですかね?
9i以降限定&インポート時のエラー処理が思い浮かばず…。
ごめんなさい、ゴミレスでした。
そう言えば、環境も書いてなかったですね・・・(Window2000で9iです)
SQL*Loaderでのインポートのみであれば、エラー発生時にはCommitされない?と思うので、問題ないのですが・・・
やはり他の方が言われるように、ビューや事前のExportなど、「Rollback」できる環境を別途考える必要があるようですね(^^)
お返事ありがとうございました。
No.2
- 回答日時:
もしかして
如何なる時でも、テーブルは新・旧いずれかの参照が出来る。
新を参照するのは、全件正常の場合のみ。
というのを考えているのですか?
そうであるなら、REPLACEを指定する方法では無理です。
#1で書かれた方法では無理です。
考えやすいのは、2つのテーブルとビュー(またはシノニム)を使う方法でしょうか。
・テーブルを2つ用意する(例えば、AとB)
・SQL*LOADERで、Bへロードする。
・ロード正常なら、ビューの参照先をAからBへ変更。
次回のロードでは
・SQL*LOADERで、Aへロードする。
・ロード正常なら、ビューの参照先をBからAへ変更。
参照する人は、ビューを参照する。
ビューの定義を切り替える瞬間だけが微妙ですが、
基本的にDMLでなく、DDL側が弾かれるハズですので
大丈夫でしょう。
注意がいるとすれば、ビューに依存するようなストアドやビューは、
切り替えの瞬間に、invalid状態になり、リコンパイルが必要に
なります。
ストアドなら、どちらを参照すべきか考えて、テーブルを見るようにすれば良いと思います。
依存ビューもやめることは可能だと思いますし、そのビュー定義を同時に変更しても
良いと思います。
ビューを使う方法もあったのですね・・・
やはり一連の処理の中でRollbackというのは無理なのですよね(^^;
> もしかして
> 如何なる時でも、テーブルは新・旧いずれかの参照が出来る。
> 新を参照するのは、全件正常の場合のみ。
> というのを考えているのですか?
という意味がちょっと分からなかったのですが、イメージ的には「失敗したからRollbak」というように、「処理をなかったことにする」ということが可能かどうか・・・と思っていました。
頂いた回答を参考にして、他の処理を追加することで対応していきたいと思います。
ありがとうございました。
No.1
- 回答日時:
SQL*Loaderで失敗した際、データを元に戻す為にはLoad前にデータをExportし、その後SQL*Loaderでデータをロード。
その後、失敗していた場合、ExportしたデータをImportすればROLLBACKもどきになります。SQL*Loaderが失敗した時の判断ですが、使用しているOSがWindowsであれば、ERRORLEVELが取得できると思うので、それを利用するのが良いかと思います。
その他のOSは良くわかりませんので、SQL*LoaderのマニュアルとOSのマニュアルを見てバッチなりスクリプトを作成してください。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- MySQL #1062 - '0' は索引 'PRIMARY' で重複しています。とでています。 1 2023/01/01 06:13
- Outlook(アウトルック) 【 Windows 10 】アドレス帳に正しくインポートを完了させたい。 3 2023/04/23 13:41
- Access(アクセス) access,vbaでフォルダ内のファイルをテーブルにインポート、ファイル名もフィールドに追加したい 1 2022/08/31 11:11
- SQL Server AccessのInsertクエリのあとつづけてDeleteクエリを行いたいがSQLでどう書いたらいい 3 2023/05/27 14:12
- Excel(エクセル) CSVファイルがカンマ区切りにならない。対処法を教えていただきたいです。 仕事でSMS一斉送信ができ 2 2022/07/01 21:24
- Access(アクセス) アクセス 削除するレコードを含んだテーブルを指定してくださいのエラー対処方法 1 2022/11/24 15:01
- PostgreSQL DBFluteについて質問です。 環境:PostgreSQL java8 前提:webアプリケーショ 1 2022/07/07 00:49
- WordPress(ワードプレス) WordPress のブログを初期化したい。リスクは? 1 2023/01/01 05:47
- システム 帳票出力を行う単体テストのテストデータが作成できません 2 2023/08/26 21:26
- Visual Basic(VBA) データベースから絞り込んでデータを読み込み 1 2023/02/21 19:51
このQ&Aを見た人はこんなQ&Aも見ています
-
性格の違いは生まれた順番で決まる?長男長女・中間子・末っ子・一人っ子の性格の傾向
同じ環境で生まれ育っても、生まれ順で性格は違うものなのだろうか。家庭教育研究家の田宮由美さんに教えてもらった。
-
SQLローダーCSV取込で、囲み文字がデータ中に入っている場合について
Oracle
-
SQL*LoaderでCSVから指定した列のみインポートしたい。
Oracle
-
SQLLOADER
Oracle
-
-
4
sql*loader 数値のロード
Oracle
-
5
SQL*Loader Append
Oracle
-
6
SQL*Loaderのコミットポイント設定がうまくいってない?
Oracle
-
7
SQL*Loaderで、データを加工してロードしたいです。
Oracle
-
8
SQL*Loaderでのsysdate使用
Oracle
-
9
SQL*Loader フォーマット変換について
Oracle
-
10
SQL*LOADER実行時のロードデータチェック
Oracle
-
11
SQL Loaderを使いたい
Oracle
-
12
sqlldrの使用方法について
Oracle
-
13
SQLローダーで複数のCSVファイルのデータを一つのテーブルにInsertしたい
その他(データベース)
-
14
importについて
Oracle
-
15
異なるスキーマからデータを抽出するには?oracl、PL/SQL
Oracle
-
16
SQLPLUSで結果を画面に表示しない
Oracle
-
17
selectした結果の余計な余白を取るにはどうしたらよいのでしょうか
Oracle
-
18
VB上でのSQLローダ利用
その他(データベース)
-
19
Oracleの排他制御について教えてください
その他(データベース)
-
20
badファイルの内容を知る方法
その他(データベース)
関連するカテゴリからQ&Aを探す
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
オラクルのUPDATEで複数テーブル
-
テーブル定義書(Oracle) 【IX】...
-
CASEでBETWEEN制約
-
truncate tableを使って複数の...
-
エラーを起こす方法
-
既にテーブルが存在する場合の...
-
現在、VBAにてUNICODEのCSVを出...
-
データ削除とSQL*Loaderでのイ...
-
教えてください。Oracleで作成...
-
複数テーブルへの問合せ
-
複数レコードの複数フィールド...
-
[materialized]マテリアライズ...
-
任意のテーブルをdrop tableしたい
-
SQL 外部結合について
-
SQL HAVING句の使い方について
-
sequenceの値の表示
-
【SQL】他テーブルに含まれる値...
-
SELECT INTOで一度に複数の変数...
-
フラグをたてるってどういうこ...
-
Accessで今日から5日後
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
オラクルのUPDATEで複数テーブル
-
truncate tableを使って複数の...
-
エラーを起こす方法
-
既にテーブルが存在する場合の...
-
データ削除とSQL*Loaderでのイ...
-
テーブル定義書(Oracle) 【IX】...
-
Where句のNot条件をAnd条件にし...
-
複数レコードの複数フィールド...
-
CASEでBETWEEN制約
-
[materialized]マテリアライズ...
-
AccessからOracle DB(View)を...
-
ORA-01630の対応方法について
-
oracle ora-02298
-
テーブルDROPできないのです。。。
-
Olacle Database 9iと10gの違い
-
viewの性能
-
accessのデータをoracleへinser...
-
pro*cobol ⇔ oracle のデータ型...
-
テーブルに変更があったらCSV出力
-
任意のテーブルをdrop tableしたい
おすすめ情報