- ベストアンサー
複数レコードの複数フィールドを一括UPDATEする方法
- 複数のレコードの複数のフィールドを一括でUPDATEする方法について解説します。
- 顧客テーブルを更新テーブルのデータで更新する際に、年齢と県のフィールドを一括で更新する方法を紹介します。
- 具体的なデータの例を使用して、顧客テーブルの更新後のデータと更新するためのSQL文を示します。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
またまた実験してみました。 フィールド名を変えてみたり、型を変えてみたりしましたが、すぐに更新完了しました。 インデックスが原因で遅くなってないでしょうか? インデックスは一意になっていますか? (No.のみに一意制約がかかってますか?) また、現在のテーブルをリネームしておいて、新たに同じ定義のテーブルを作成しなおし、リネームしたテーブルから入れてみてはどうでしょうか?
その他の回答 (5)
- kenthy
- ベストアンサー率28% (2/7)
下の回答した者です。 試しに、20000件のテーブルと500件のテーブルを用意して20000件のうち500件をアップデートしてみました。 SQLPlus WorkSheetで実行し、かかった時間は1分かかりませんでした。 ところで、SQLが帰ってこないというのはプログラムで実行しているのでしょうか?それともSQLWorkSheetなどでじかにSQL実行した結果でしょうか? もしプログラムからしているのでしたら、プログラムのループ処理が無限ループに入っている可能性はないかチェックしてみてください。 また、直接SQLを実行していないならSQLWorkSheetなどでSQL単体で実行テストをしてみてください。 ちなみに当方の環境はOracle9iです
補足
いつもいろいろありがとうございます。 SQLは、SQL Plusで実行しています。 クライアントからとサーバから試しましたが同じ結果でした。 テストを実証していただいたので、同様にテストをしてみました。 テストテーブル1 + テストテーブル2 の更新だと問題なく動作します。しかもすごく高速で500件のデータ更新に数秒です。 これを テストテーブル1 + 既存テーブル1 とすると25分。 既存テーブル1 + 既存テーブル2 SQLが終了しない。(2時間経過も終了しない) となってしまいます。 テストテーブル1と2は全く同じ定義のフィールドを持つテーブル同士です。 フィールド名が異なる、フィールド長が異なる、フィールド定義が異なる、のが処理速度の遅さや停止の原因になってるのかとも思っています。
- kenthy
- ベストアンサー率28% (2/7)
>table_n が 500件、table_a が20000件ほどあります。 >よって更新するデータは500件ほどです。 ということは、Aの内容をBで更新するという事ですよね? 実際試されたSQLを見ると、本当は「更新される側」を更新する必要があるところを「更新する側」に更新をしていますね。 正しくは下のSQLでいけると思います。 UPDATE table_a a SET (a.年齢,a.県)=(SELECT n.年齢,n.県 FROM table_n n WHERE n.CODE = a.CODE) WHERE EXISTS (SELECT * FROM table_n n WHERE a.CODE = n.CODE)
補足
助言ありがとうございます。 更新用のテーブルで実行するとなぜか上手くいかず2時間以上たってもSQLが終了しません。 そこで仮のテーブルを作ってテストしたら400件のデータ更新で約20分ほどで更新されました。 いままで同じ処理をループをかけて1件づつ行っていました。このSQLも実行速度はあまり期待しないほうがよろしいのでしょうか? もうちょっと工夫してやってみます。
- kenthy
- ベストアンサー率28% (2/7)
質問にあるNo.というのはこれだけで一意になってるんですよね? 私の示したSQLではIDをNo.と置き換えて考えて頂けたでしょうか? どんなSQLを書いて無理だったか貼り付けてもらえませんか? SELECT COUNT(*) FROM TEST_M M WHERE EXISTS(SELECT * FROM TEST_S S WHERE S.ID = M.ID) これで更新件数を確認できると思いますが、意図通りの更新件数が得られるでしょうか?
補足
Noは一意です。これがキーで、重複はありません。 UPDATE table_n n SET (n.年齢,n.県)=(SELECT a.年齢,a.県 FROM table_a a WHERE a.CODE = p.CODE) WHERE EXISTS (SELECT * FROM table_a a WHERE a.CODE = p.CODE) CODEがIDと考えてください。 データは、 table_n が 500件、table_a が20000件ほどあります。 よって更新するデータは500件ほどです。 SQLを発行すると終了しなくなってしまいます。 オラクルのバージョンの問題でしょうか? バージョンは、8.0.5とちょっと古いんです。 更新フィールドが1つのSQLは別のもので試したら動くのですが。 いままでデータを1件1件ループさせて更新していたのでSQL文をすっきりさせて処理の向上が図れればと思ってます。 よろしくお願いいたします。
- siokara
- ベストアンサー率41% (7/17)
自分自身を更新の情報に参照することができなかったかと思います。(別名を使っても) ですのでまず、更新したい更新情報テーブルを作ってしまい、その情報を元に更新するしかないと思います・ 参考までに・・ 1.更新したいテーブル構造を作る create table 更新情報テーブル AS select * from 更新元テーブル where ・・・ としてできたテーブル情報を手修正なり、一度trancateして変更情報をInsertなりして 更新情報テーブルを用意する。 >この場合、1つのSQLで、複数レコードの複数フィールドを一括でUPDATEは出来ますでしょうか? 更新元=更新先でUPDATEはできないと思うので、1つのSQLでは不可能だと・ 2つのテーブルを用意したなら、後は連結させて更新するだけです。
- kenthy
- ベストアンサー率28% (2/7)
これでいけないでしょうか? 更新用をTEST_S、顧客テーブルをTEST_Mとします UPDATE TEST_M M SET (年齢,県)=(SELECT 年齢,県 FROM TEST_S S WHERE S.ID = M.ID) WHERE EXISTS(SELECT * FROM TEST_S S WHERE S.ID = M.ID)
補足
ヒントありがとうございます。 試してみたのですが、サーバが処理を終了してくれません。ループに入って終了しないような。 検索条件を絞って実行してみたのですが同じ結果です。 処理件数は500レコードほどです。 テストは7レコードでも行ってみました。 何が問題なんでしょうか?
お礼
出来ました。 新テーブルにユニークキーを設置したら動きました。 テーブルを見直してみたところ、 主テーブル...Noがプライマリーキー 新テーブル...他コードがプライマリーキー、Noはキー設定なし。 となっていました。 キー設定のあるなしでこんなに動作に違いが出ると思いませんでした。 これでデータの更新は簡単に行えるのでひとまず安心しました。 本当にありがとうございました。