• 締切済み

Insert Into Select での重複について

DB:SQLServer2000 こんにちは お世話になっております。 トランザクションのテーブルA から ワークのテーブルBへInsert Into Select を使用してデータを格納しているのですが、その際に重複が発生してしまいます。 テーブルA 主キーあり テーブルB 主キーなし Delete B Insert into B select 項目1,項目2,・・・ from A With(Nolock) where 日付項目 = 20080101 テーブルAの主キー項目は全てテーブルBへInsertしており、Insert完了後のテーブルBの中身を見ると、まれに全く同じデータが2件出来ていることがあります。 このInsert into selectが実行されている間に、テーブルAに対して登録更新が行われることもあります。 色々と試してはいるのですが、原因が特定できずに困っております。 もし何かお気づきになられる方がいらっしゃいましたら、ご教示下さい。 よろしくお願い致します。

  • aoman
  • お礼率85% (6/7)

みんなの回答

  • agricap
  • ベストアンサー率40% (79/195)
回答No.5

>>・すでに存在するレコードA1をテーブルAにInsertして(これがCOMMITするまではエラーにならないとして)、COMMITしないうちにSELECTされる >⇒十分にあり得るとは思いますが、この様な場合は、既に存在するレコードA1と新たにInsertされようとした重複するレコードA1’がNolockでSelectした場合2件抽出されることになるのでしょうか? 理論上はあり得ると思いますね。 ただROLLBACKのログがない、ということですから、これもあり得ないということでしょうか。 エラーになったらROLLBACKされるはずですよね。 となると、いよいよわかりません。

aoman
質問者

お礼

ご回答ありがとう御座います。 >ただROLLBACKのログがない、ということですから、これもあり得ないということでしょうか。 >エラーになったらROLLBACKされるはずですよね。 そうですね。これもあり得ないことになってしまいます。 色々ありがとうございました。 まだ、あきらめずに調べて行きたいと思います。

  • agricap
  • ベストアンサー率40% (79/195)
回答No.4

ということは、 「Insert into B select 項目1,項目2,・・・ from A With(Nolock) where 日付項目 = 20080101」 の対象になるようなレコードが、これを実行中にテーブルAにInsertされる可能性がある、ということですね? ・すでに存在するレコードA1をテーブルAにInsertして(これがCOMMITするまではエラーにならないとして)、COMMITしないうちにSELECTされる、とか ・2つのトランザクションからともにレコードA1をテーブルAにInsertしようとして、この2つがCOMMITしないうちにSELECTされる、とか ・1つのトランザクションが レコードA1をテーブルAにInsert →SELECTされる →InsertをROLLBACK →レコードA1をテーブルAにInsert →InsertをCOMMIT →再びSELECT とか・・・ はありえないですかね?

aoman
質問者

お礼

ご回答ありがとう御座います。 またまた、お礼が遅くなり申し訳御座いません。 >これを実行中にテーブルAにInsertされる可能性がある、ということですね? ⇒その通りです。Insert・Updateがあり得ます。 >・すでに存在するレコードA1をテーブルAにInsertして(これがCOMMITするまではエラーにならないとして)、COMMITしないうちにSELECTされる ⇒十分にあり得るとは思いますが、この様な場合は、既に存在するレコードA1と新たにInsertされようとした重複するレコードA1’がNolockでSelectした場合2件抽出されることになるのでしょうか? >・2つのトランザクションからともにレコードA1をテーブルAにInsertしようとして、この2つがCOMMITしないうちにSELECTされる ⇒テーブルAにInsertを行うトランザクションは1つしかない為、この様なことは無いと思います。 >1つのトランザクションが >レコードA1をテーブルAにInsert >→SELECTされる >→InsertをROLLBACK >→レコードA1をテーブルAにInsert >→InsertをCOMMIT >→再びSELECT ⇒これは、Insert into Selectが流れている間に、一連の流れが行われるということでしょうか。それとも2度Insert into Selectが実行されるということでしょうか。 前者の場合、あり得るとは思いますが、事実上テーブルAの登録する際にROLLBACKはかかっておりません。 (ROLLBACKの際にはエラー情報としてログが出力されるが、そのログが存在していない為) 後者の場合、テーブルAのSELECTを行う前にテーブルBはクリアされる為、重複はしないと思われます。 色々お手間掛けまして申し訳御座いません。 よろしくお願い致します。

  • agricap
  • ベストアンサー率40% (79/195)
回答No.3

すみませんが、わかりません。 Nolockが少し気になります。 他のロックに変えたら発生しないということはないですかね。

aoman
質問者

お礼

ご回答ありがとう御座います。 >Nolockが少し気になります。 >他のロックに変えたら発生しないということはないですかね。 私もNolockが一番怪しいのではと考えておりますが、どうしてもSQLの修正を行う前に原因を特定する必要がありましたので、Nolockを外したり等のテストを実際のSQLで行うことが出来ず、また、テスト環境で同様のSQLを実施したりしておりますが、現象(重複)の再現すら出来ずに行き詰っていた次第です。 すいません。本当は色々変更して試せれば良いのですが諸事情により本番のSQLを変更しての確認が出来ず、またテスト環境での再現が出来ていないことが最大のネックになっております。 私が今考えているのは、Nolockを使用することにより、テーブルAに更新が行われた際に、テーブルBへのINSERTが同時に処理され、未コミットデータがまずSELECTにて抽出され、INSERT。その同じタイミングで更新がコミットされ、そのコミットされたデータが再び、SELECTにて抽出され、INSERTされているのではと考えていますが、この様なことは実際にありえるのか、調査しているところです。 もし、何かご存知でしたら、ご教示頂けると幸いです。

  • agricap
  • ベストアンサー率40% (79/195)
回答No.2

「このInsert into selectが実行されている間に、テーブルAに対して登録更新が行われることもあります」 とのことですが、これはどのような登録・更新でしょうか? 「select 項目1,項目2,・・・ from A With(Nolock) where 日付項目 = 20080101」 の内容が変わることもあるような更新でしょうか?

aoman
質問者

お礼

ご回答ありがとう御座います。 お礼が遅くなってしまい申し訳御座いません。 >これはどのような登録・更新でしょうか? 登録は単純に新規データの登録が行われます。 更新はテーブルAに持っているフラグ項目の更新です。0→1など >内容が変わることもあるような更新でしょうか? この内容が変わることはありません。 よろしくお願い致します。

  • agricap
  • ベストアンサー率40% (79/195)
回答No.1

単純に同じSQLが2回実行されれば、同じレコードが2つできるのではないですか?

aoman
質問者

お礼

ご回答ありがとう御座います。 この重複は1度だけの実行で発生しています。 すいません。質問の内容が曖昧でした。少しだけ質問内容に補足させて頂きますが、Insert Into Select で登録される件数が大体10,000件程度なのですが、このうち数件だけ、まれに重複していることがあります。 何らかのタイミングでこの様になるとは思うのですが・・・ よろしくお願いします。

関連するQ&A

  • select insertで複数テーブルから値を取得したい

    環境:oracle9i select insertで、2つのテーブルから値を取得して、1つのテーブルにinsertすることは可能でしょうか? たとえば、以下の場合、どのようなSQL文を書けばよいか、アドバイスいただけますでしょうか。 よろしくお願いします。 insertしたいテーブル:A Aテーブルの項目:o,p,q,r,s,t 値を取得するテーブル:B,C Bテーブルの項目:o,p,q,r Cテーブルの項目:o,p,s,t oとpが主キーになっていて、それらが一致するBとCのデータを あわせて、Aにinsertしたいと思っています。 insert into A(o,p,q,r,s,t) select このあと、どのように書けばよいのかがわかりません。

  • Insert Intoでアップデートをかけたい

    テーブルから他テーブルへデータの更新をしたいと思っています。 テーブルは下記のような構成になっています。 テーブルSTOCK(主キーは商品コード) 商品コード(varchar),数量(int) A001,5 B002,10 C003,30 テーブルTOTAL(主キーは商品コード) A001,10 B002,20 やりたいことは、テーブルTOTALを更新させる事です。テーブルSTOCKの商品コードがテーブルTOTALにあれば、減算をおこないたいです。 そこで下記のSQLを書きました。 INSERT INTO テーブルTOTAL SELECT * FROM テーブルSTOCK ON DUPLICATE KEY UPDATE テーブルTOTAL.数量 = テーブルTOTAL.数量 - テーブルSTOCK.数量 更新結果 A001,5 B002,10 C003,30 商品コードがA001、B002は欲しい結果がでました。欲しい結果はC003が「-30」になることです。 テーブルTOTALにはC003の商品コードがないため、30でアップデートされてしまうのですが、なんとか「-30」で更新できるようにできないでしょうか? よろしくお願いいたします。

    • ベストアンサー
    • MySQL
  • トランザクション中にSELECTした場合について

    InnoDBを使っているのですが、 以下の1.から5.の処理の間に、サーバー1.の「テーブルA」へ SELECTを掛けた場合、何か遅い気がします・・原因は何でしょうか? 1.サーバー1でトランザクション開始 2.サーバー1の「テーブルA」をDELETEでを全削除 3.サーバー2から「テーブルA」の新しいデータを取得 4.3.で取得したデータをサーバー1の「テーブルA」へINSERT 5.サーバー1でトランザクション終了 他のトランザクションでDELETEされたレコードに対し、 SELECTすると結果が返るのは遅いでしょうか?

    • ベストアンサー
    • MySQL
  • Insert文で・・・

    失礼します。SQL初心者なので質問します。 Insert into Aテーブル Select X , Y , Z From Bテーブル というSQLがあり、Aテーブルの列数を3から4にした際、AテーブルへのInsertの項目を、BテーブルからSelectされたX,Y,Z以外に普通の変数αも新たに作成した4つめの項目として同時にInsertしたい場合、どのようなSQLにすれば良いでしょうか? Insert into Aテーブル (Select X , Y , Z From Bテーブル),α みたいに都合良くはいきませんよね??

  • select into句のトランザクションについて

    お世話になってます。 sqlについて質問です。 ddlを発行するとトランザクションは暗黙的にコミットされると思いますが、 select into #temptable ・・・ のように、select into 句で一時テーブルを作成した場合、トランザクションはどうなるのでしょうか? また、以下のように一時テーブルと普通のテーブルで挙動は変わりますか? begin transaction select into #temptable from A ← ここでコミットされてしまう? …(1) select into temptable from A ← ここでコミットされてしまう? …(2) rollback transaction 以上、よろしくお願いいたします。

  • insert into select で別テーブルのID分挿入したい

    SQLでこんなことは可能でしょうか。 列 IDとTEXT をもつテーブルA と、 列 IDをもつテーブルBがあります。 テーブルAに、テーブルBのID分のデータを挿入したいです。 TEXTはテーブルAのID=1のTEXTデータを全ての列に挿入します。 このような場合のSQL文を調べてるのですが、 なかなかわからなくて困っています。 insert into select b.id,a.text from tableA as a, tableB as b でもうまくいきませんでした。 何かいい方法はないでしょうか? 回答お待ちしております。

  • Insertで重複となったキーをさがすSQL文

    テーブルの移行(Aテーブルのデータをキーを変更してBテーブルにInsertする)を行ったところ、 ERROR: duplicate key violates unique constraint "Bテーブル_unique"とメッセージが出ます。 SQL文はつぎの通りです。 INSERT INTO Bテーブル(契約番号, ユニット番号, 資源番号, 入力日, 数量) SELECT a.契約番号, a.ユニット番号, a.資源番号, a.入力日, a.数量 FROM Aテーブル a ; Bテーブルのキーは、契約番号, ユニット番号, 資源番号, 入力日です。 Aテーブルのキーは、契約番号,入力日,レベル1,レベル2です。 データ件数は約3万件です。 Bテーブルを調査して、重複となるレコードを表示させたいのですが、 SQL文がわかりません。 よろしくご教授ください。

  • Access にて DISTINCROW を使用した INSERT SELECT

    お世話様です。 Access2003 VBAにて、DoCmd.RunSQLを使用してSQL文を流す際、 普通のINSERT-SELECT文はOKですが、 そのSELECT文にDISTINCROW句を使用していると、 数百件程度のSELECT結果しかINSERTできません。 本当は数千件のSELECT結果をINSERTしたいのですが、 これを実行した場合、エラーにもならず、1レコードもINSERTされません。 ためしに、DINSTINCTROWではなく、SQL文を変更してDISTINCTにしてみたところ、 2000件以上でもINSERTできました。 DISTINCROW句を使用して数千件でもINSERTできる方法はあるでしょうか? ちなみにSELECT単体ですと、DISTINCTROWを使用していながら、 数千件でも結果を表示できます。 SQL例: str_SQL = " INSERT INTO 結果テーブル(フィールド1, フィールド2, フィールド3)  SELECT DISTINCTROW A.項目1, A.項目2, B.項目1  FROM テーブル1 A, テーブル2 B  (WHERE句はあってもなくても現象変わらず)  ORDER BY A.項目4 ASC, A.項目5 ASC " DoCmd.RunSQL (str_SQL) よろしくお願いいたします。

  • データ登録時、重複エラーを避けたい

    MYSQLのデータベースの、IDという項目が主キーのTESTというテーブルに、データをに登録する際、 既に主キーが同じデータがない場合に、という条件をつけたいのですが、 下のように書くと、エラーになってしまいます。 INSERT INTO TEST (ID, NAME) VALUES ('a', 'abc') WHERE NOT EXISTS (SELECT * FROM TEST WHERE ID = 'a'); どうしたらよいか教えてください。

    • ベストアンサー
    • MySQL
  • 別テーブルからselectした値を他のテーブルにinsertしたいのですが、上手くできません

    以下のように行ったのですが、 全ての値が別テーブルにinsertされません。 $sql = "SELECT tbl_A.id, tbl_A.data FROM tbl_A "; $rst = mysql_query( $sql ); while ( $col = mysql_fetch_array( $rst ) ) { $sql = "INSERT INTO tbl_B (          date, id, data ) VALUES ( '" . date( 'Y-m-d' ) . "', '" . mysql_real_escape_string( $col['id'] ) . "', '" . mysql_real_escape_string( $col['data'] ) . "' )"; } このやり方では、テーブル内の1つの値しかinsertされません。 selectされた全ての値をinsertするにはどのようにしたら良いのでしょうか? よろしくお願いします。 DB:mysql5 SP:php5

    • ベストアンサー
    • MySQL