SQLServer2005環境で、Aテーブルの最新データをBテーブルにUpdate/Insertする方法

このQ&Aのポイント
  • SQLServer2005環境で、Aテーブルの最新データをBテーブルに効率的にUpdate/Insertする方法を紹介します。
  • Merge文を使用することはできませんが、ストアドを利用して、Aテーブルに存在しないデータをBテーブルからDeleteすることも可能です。
  • サンプルコードや解説サイトは多数存在しますので、これらを活用しながら、目的に合ったストアドを実装してください。
回答を見る
  • ベストアンサー

ストアド。存在チェックをしてから登録したい。

SQLServer2005環境です。 同じ構造のテーブルA、Bがあり、AのデータをBにコピーしたいと思っています。 Aのデータは最新のデータ、Bの中にあるのは古いデータなので、もしキーが かぶるレコードがあれば、Updateをかけ、なければInsertをするような仕組みに したいと思っています。 更に可能であれば、Aに存在しないデータがBにあった場合は、Deleteしたいです。 一度BをDeleteしてInsertすれば話が早いのですが、そうもいかず、UpdateとInsertを 交え、小出しに更新するような形にしたいのです。 2008であれば、Merge文という便利なものがあるのですが、2005では上のような 動作をストアドで実現するのは難しいでしょうか。 サンプルコードですとか、解説しているサイトなどがありましたら、教えていただけますと 大変助かります。 宜しくお願いします。

  • ginfix
  • お礼率34% (330/962)

質問者が選んだベストアンサー

  • ベストアンサー
  • KHSSSK
  • ベストアンサー率76% (13/17)
回答No.2

UPDATE - INSERT - DELTE の順で処理し UPDATE は INNER JOIN で他は NOT EXISTS を使用する方法はいかがでしょうか。 例えば BEGIN UPDATE TableB SET TableB.Filde1 = TableA.Filde1 ・・・・・・ FROM TableB INNER JOIN TableA ON TableB.ID = TableA.ID END BEGIN INSERT INTO TableB SELECT * FROM TableA WHERE NOT EXISTS(SELECT * FROM TableB WHERE TableA.ID = TableB.ID) END BEGIN DELETE FROM TableB WHERE NOT EXISTS(SELECT * FROM TableA WHERE TableB.ID = TableA.ID) END こんな感じで。 SELECT文で確認してから実行してね!

その他の回答 (1)

  • nora1962
  • ベストアンサー率60% (431/717)
回答No.1

ストアド内で SELECT ... WITH(UPDLOCK) でデータがあるかどうか調べて処理を分岐させては。 ただし、同時実行するトランザクションがあると、上記のSELECT時点ではなかったキー値がINSERT、COMMIT時点では存在する可能性はあります。

関連するQ&A

  • ストアドの書き方?

    Aテーブルに同じフィールドを持ったcsvをd, e, f, g と4つのフィールドを比べて 1つでも違っていたら、insertするというSQLをつくりたいのですが、 これは、ストアドになるのでしょうか? データはだいたい5万件くらいあります。 サーバーはSQLServerになります。 宜しくお願い致します。

  • ストアドプロシージャの多用でパフォーマンスは向上するか?

    抽象的な話で非常に恐縮なのですが、 ストアドの中で行うSELECTやINSERTなどの処理を 更にストアドにすることで、パフォーマンスは向上するのでしょうか? たとえば、「テーブルAの内容を取得してテーブルBにINSERT」というストアドがあったとします。 この場合、以下のような記述になると思います。 ---------------------------------- SELECT (略) FROM TBL_A INSERT INTO TBL_B (略) ---------------------------------- このSELECT及びINSERT処理をそれぞれストアド化し、 ---------------------------------- EXEC SP_A (略) EXEC SP_B (略) ---------------------------------- とすると、わずかなりでも処理速度は向上するのでしょうか? (極論ですが、全てのSELECT、INSERT、UPDATEをストアド化するのがベストなのでしょうか?) 現在、数百万~数千万件のレコードを処理するストアドを作成中で、処理時間の短縮が大きな課題になっています。 1件あたりの処理が0.1秒でも縮めば、10万件の処理時間は10,000秒(=3時間弱)の短縮になり、決して馬鹿にはできません。 妙な質問ですが、良策があればご教授ください。

  • ストアドプロシージャについて

    教えてください。 NT4.0上でAccess2000+MSDEで使用しているのです。 ストアドプロシージャでUPDATE文のあとにSELECT文を使い更新したデータを受け取ろうとしているのですが、実行すると「ストアドプロシージャは実行されましたがレコードは返されませんでした。」とメッセージが表示されるだけなのです。UPDATE文を注釈にするとレコードは返されるのでデータはあるのだと思います。 宜しくお願いします。

  • CSVを取込むストアドプロシージャで、1件目が登録されない現象が起きています

    いつもお世話になっております 古い環境なので大変恐縮ですが、行き詰ってしまったので、 ご教示いただきたいと思います。 環境: WinXP sp2 SQLServer8.0 VB6.0 sp4 VBでCSVのデータ1行について、ストアドプロシージャにて3つのテーブルに格納しようとしています。 トランザクションの管理はVB側で行っています。 1行ごとにCommitを行えば、全行格納されるのですが、 2行以上ごとにCommitを行うと、最初の1行のみが格納されないという現象がおきています。 6800行存在する同じCSVファイルについて、1行ごとにCommitを行った場合は、6800件登録されるのに 処理の最後でCommitをきった場合、6799行しか登録されません。 1行ごとにCommitをきった場合に6800行登録されるので、キー重複は考えられません。 いろいろ試してみたことを下記に書きます 結果はこのような感じです。 CASE1・・・全件登録できます CASE2・・・2件目で重複エラーが発生します CASE3・・・全件 - 1件が登録できます CASE4・・・全件登録できます CASE5・・・全件登録できます CASE2, CASE3 で全件登録できない理由をご教示いただきたく思います。 よろしくお願いいたします。 CASE1(VBでINSERT文を記述)  localConnection.beginTrans localConnection.execute "DELETE FROM TABLE_A" localConnection.execute "DELETE FROM TABLE_B" localConnection.execute "DELETE FROM TABLE_C" FOR i = 1 to 6800 localConnection.execute "INSERT INTO TABLE_A (COL_A1, COL_A2) VALUES ('" & VAL_A1(i) & "','" & VAL_A2(i) & "')" localConnection.execute "INSERT INTO TABLE_B (COL_B1, COL_B2) VALUES ('" & VAL_A1(i) & "','" & VAL_B2(i) & "')" localConnection.execute "INSERT INTO TABLE_C (COL_C1, COL_C2) VALUES ('" & VAL_A1(i) & "','" & VAL_C2(i) & "')" NEXT  localConnection.commitTrans CASE2(ストアドプロシージャ) localConnection.beginTrans localConnection.execute "DELETE FROM TABLE_A" localConnection.execute "DELETE FROM TABLE_B" localConnection.execute "DELETE FROM TABLE_C" ' -- ストアドプロシージャのパラメータ作成 FOR i = 1 to 6800 localConnection.execute NEXT  localConnection.commitTrans CASE3(ストアドプロシージャ) localConnection.beginTrans localConnection.execute "DELETE FROM TABLE_A" localConnection.execute "DELETE FROM TABLE_B" localConnection.execute "DELETE FROM TABLE_C"  localConnection.commitTrans ' -- ストアドプロシージャのパラメータ作成 localConnection.beginTrans FOR i = 1 to 6800 localConnection.execute NEXT  localConnection.commitTrans CASE4(ストアドプロシージャ) localConnection.beginTrans localConnection.execute "DELETE FROM TABLE_A" localConnection.execute "DELETE FROM TABLE_B" localConnection.execute "DELETE FROM TABLE_C"  localConnection.commitTrans ' -- ストアドプロシージャのパラメータ作成 localConnection.beginTrans FOR i = 1 to 6800 localConnection.execute   localConnection.commitTrans   localConnection.beginTrans NEXT  localConnection.commitTrans CASE5(ストアドプロシージャ) localConnection.beginTrans localConnection.execute "DELETE FROM TABLE_A" localConnection.execute "DELETE FROM TABLE_B" localConnection.execute "DELETE FROM TABLE_C"  localConnection.commitTrans ' -- ストアドプロシージャのパラメータ作成 localConnection.beginTrans FOR i = 1 to 6800 localConnection.execute if i = 1 then   localConnection.commitTrans   localConnection.beginTrans end if NEXT  localConnection.commitTrans

  • MySQLでテーブルの完全同期

    MySQLでテーブルの完全同期を行いたいです。 例えばAテーブルをUpdateしたらリアルタイムでBテーブルもUpdate、同様にInsert、Delete。 Aテーブルに1000レコードはいっていて、Bテーブルが0件の場合、自動的に1000件Bテーブルに取り込む。 このようなことを実現することは可能でしょうか

    • ベストアンサー
    • MySQL
  • SQLServerのロック?について

    お世話になっております。 早速ですが、質問させていただきます。 ASP+SQLServer2000で社内システムの作成などを行っております。 ASP上から社員がデータを打ち込んでいるシステムがあるのですが、同時にSELECT、UPDATE、INSERT、DELETEを一つのテーブルで行っております。 その際、SELECTとUPDATE、INSERT、DELETEの処理がかぶると画面が固まったように処理が長くなります。 自分でわかる限りの原因としては検索レコードは10万件くらいからやっているのですが、SELECTで検索中にINSER、UPDATE、DELETE処理がくるとウエイト状態になり、異常に時間がかかってしまい、タイムアウトしてしまっています。 INSERTやUPDATEが処理かぶっても特に処理はとまらないのですが、先にSELECT処理していてINSERTやUPDATE処理がくるとまったく動かなくなってしまうのです。 こちらの原因とか少しでもわかる方いらっしゃれば、お知恵をお貸しください。

  • IFで条件を分岐させてのINSERT(ストアド)。

    SQL Server2005環境です。 ストアドプロシージャを作成しています。 テーブルAを読み込んで、その値を元に、テーブルBに値を INSERTしていくという処理をしたいと考えています。 1.テーブルA.区分1<>0の時、テーブルB.区分は1 2.テーブルA.区分2<>0の時、テーブルB.区分は2 3.テーブルA.区分1<>0 かつ テーブルA.区分2<>0であれば、  テーブルB.区分が1のレコードと、2のレコード、2つ作る 以上のような処理をしたいと考えています。 ストアドはまったく初心者なのですが、分岐については、 DECLARE TEST CURSOR FOR SELECT 区分1, 区分2 FROM テーブルA OPEN TEST FETCH NEXT FROM TEST INTO @KBN1, @KBN2 --条件分岐 IF KBN1<>0 BEGIN @INKBN=1 END IF KBN2<>0 @INKBN=2 END WHILE @@FETCH_STATUS = 0 BEGIN INSERT INTO テーブルB(区分) VALUES(@INKBN) こんな感じになるのか?と思っているのですが、これではケース3の、 区分1、2ともに0ではない場合の処理ができません。 このような場合、どのように記述すれば目的の処理を達成できるのか 教えていただけないでしょうか? よろしくお願いします。

  • postgresのストアドファンクションでエラーの

    postgresのストアドファンクションでエラーの拾い方を教えてください。 insertして重複したらアップデートに切り替えるというサンプルをよく見かけます。 DECLARE BEGIN insert文 RETURN TRUE; EXCEPTION WHEN unique_violation THEN update文 END; それと同じノリで、何かしらのエラーがあった時に、 『RETURN FALSE;』するか、もしくはエラーコードをそのまま拾って返すというようなサンプルが欲しいです。 DECLARE BEGIN 何かしらのSQL RETURN TRUE; EXCEPTION WHEN すべてのエラー THEN RETURN FALSE; END; DECLARE BEGIN 何かしらのSQL RETURN TRUE; EXCEPTION WHEN すべてのエラー THEN RETURN エラーコード; END;

  • AccessVBAからのストアド起動について

    現在、Accessで元来の記述にストアド起動の1文を追加し、 SQLserver上のmasterデータベースに登録しているストアドを起動させようとしております。 起動方法として、xp_cmdshellを利用してみたのですが、 しかし、起動に必要なパラメータの受け渡しが上手くいかないため、動作が正常に行われません。 『』部は実際には定数が入っております。 VBA内容は以下の通りです。 ・既存箇所 set DB = createobject( "adodb.connection" ) DB.oprn "PROVIDER = SQLOLEDB.SERVER = "『サーバIPアドレス』","『ログインID』","『ログインパスワード』" ~~~(ここで開いたDB中のテーブル上のデータを読み取るなど実行) ・追加しようとしている記述(Null時はNz関数で""に置換) A = 「パラメータ1」 B = 「パラメータ2」 C = 「パラメータ3」 (これらは上記のDBからRecordsetで取得。必要な値が取得できることは確認済み) strsql= "EXEC MATSER..xp_cmdshell ’EXEC mastter..『ストアド名』 & A & B & C & "'" DB.Execute stersql sqlserver上で起動するときは EXEC mastter..『ストアド名』 'パラメータ1' ,'パラメータ2' ,'パラメータ3' で起動することが確認記できております。 既存部でパラメータ引き渡しの必要のないストアドは動作しているため、 パラメータの引き渡しに問題があると判断しておりますが、 何パターンか変更してもうまく動かないため、 アドバイスをいただければと思います。

  • ストアドプロシージャの戻り値が取得できない

    ストアドプロシージャの戻り値が取得できない ストアドプロシージャ内でSelectとUpdateを行い、設定した戻り値をリターンしたいのです。 ついでにSelectとした複数行の結果の読み込みもしたいのですが。 Dim cmd As New System.Data.SqlClient.SqlCommand Dim i As Integer Dim readerA As System.Data.SqlClient.SqlDataReader cmd.CommandType = Data.CommandType.StoredProcedure cmd.CommandText = "SP名" cmd.Parameters.Add("A", System.Data.SqlDbType.Int) cmd.Parameters("A").Direction = System.Data.ParameterDirection.ReturnValue readerA = cmd.ExecuteReader() i = cmd.Parameters("A").Value if (i = 0) Then 処理 End If While readerA.Read() 処理 End While 上記でSelectした結果をreaderA("カラム名") で読みこめているのですが、戻り値Aの値が取得できていません。 ウォッチ式でcmd.Parameters("A").Valueを見るとNothingになっています。 ちなみに、違うストアドを実行しているところでは戻り値は取得できています。。。 ストアドがおかしいんでしょうか。Selectの取得結果も見ようとしているのがまずいのでしょうか。 環境はvb.net、SQLServer2005です。