- ベストアンサー
なければInsert、あればUpdate …ってできますか?
MySQL 3.23.49-nt を使用中です。 とあるテーブルを、3つのサーバで使用中で、このテーブルを一つのサーバで更新して、他のサーバへ レコードをコピーしたいのですが、「他のサーバ」に既に同じキーの レコードが存在する可能性があります。 こちらで更新したいサーバ(A)のテーブルの内容をこんな感じだとします。 キー番号 | SEQ | 項目A | 項目B ---------+-----+-------+------ 1001 | 1 | 11-AA | 11-BB 1001 | 2 | 12-AA | 12-BB 1002 | 1 | 21-AA | 21-BB 1002 | 2 | 22-AA | そして、コピー先のサーバ(B)のテーブルの内容をこんな感じだとします。 キー番号 | SEQ | 項目A | 項目B ---------+-----+-------+------ 1001 | 1 | 11-BA | 11-XX 1002 | 1 | 21-BA | 21-YY 1002 | 2 | | 22-YY 「キー番号」「SEQ」「項目A」だけを、サーバAと同一にしたいと考えています。 キー番号とSEQが同一のレコードが存在する場合、サーバBの「項目B」は変えたく ありません。 すなわち、サーバ(B)が キー番号 | SEQ | 項目A | 項目B ---------+-----+-------+------ 1001 | 1 | 11-AA | 11-XX ---- 項目Aを更新 1001 | 2 | 12-AA | ---- レコードをINSERT 1002 | 1 | 21-AA | 21-YY ---- 項目Aを更新 1002 | 2 | 22-AA | 22-YY ---- 項目Aを更新 のようになって欲しいのです。 そこで、 「キー番号="1001"、SEQ = "1" のレコードがあれば、そのレコードの項目Aに'11-AA'をセットしてUPDATE。 レコードがなければ、キー番号="1001"、SEQ = "1"、項目A='11-AA'のレコードをINSERT。」 というようなMySQLの命令文(?)を書けないかなぁ?と、一生懸命参考書をひっくり返してもがいています。 できるようなできないような... 無理でしょうか?
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
プログラムを使わないで、MySQLのコマンドだけでですか? 簡単な方法としては一度、全部のデータをinsertしてから全部のデータをupdateすれば良いと思います。 ※キー番号とSEQがプライマリKEYになっている前提で 1.全部のデータをinsert →1001/2のデータ以外はエラーになって更新されない。 2.全部のデータをupdate →1001/2を含む全データがupdateされる。
その他の回答 (3)
- R34_666
- ベストアンサー率25% (17/66)
うわ、こんなコマンドあったんだ^^; Kanataさん便乗でありがとうございました。 私も全部作り直しします(苦笑) Tues17さん、すみませんでした。
お礼
いえいえ、どういたしまして...って私が教えたわけではないのですが ^^; 私ももうちょっとMySQLのコマンドを勉強します。 Kanataさん、R34_666さん、どうもありがとうございました。
どこまでお望みのことができるかどうかは分かりませんが、REPLACE INTOを使ってはできないでしょうか? たぶん「MySQL REPLACE INTO」とでも検索すれば、使い方は出てくると思います。 #INSERTと似てますけど・・・ 間違いがありましたらご指摘ください。 ではでは☆
お礼
ご回答ありがとうございます。 残念ながら、REPLACE INTO は今回の私の要求には合わないようです。 (『REPLACE は INSERT とほぼ同じように動作しますが、唯一異なる点として、UNIQUE インデックスまたは PRIMARY KEY に 関して新しいレコードと同じ値がテーブル内の以前のレコードに含まれていると、以前のレコードが削除されてから新しい レコードが挿入されます。 』というやつですよね?) キー番号「1001」SEQ「1」のレコードについて、REPLACE INTOを使うと、 サーバBの値は項目A:「11-AA」項目B:「11-BB」となってしまいますよね? でも、サーバBのこのレコードの項目Bは、もともとの「11-XX」を残して、 項目Aの「11-BA」だけを、サーバAに合わせて「11-AA」に上書きしたいのです。 今回は、#2に書いたように、「Insert IGNORE」+「Update」の組み合わせで更新できました。 KanataさんにアドバイスいただいたReplace into は全然知らなかったのですが、今後の参考にさせていただきます。勉強になりました。
- R34_666
- ベストアンサー率25% (17/66)
うーん、他の人からの回答が無いところ見るとSQLコマンドだけでは無理かもしれないですね。 私も分かりません^^; 補足を読んだ感じでアドバイスですが、 Tues17さんが1つのサーバを管理していて、他の2つのサーバ管理者にSQLファイルを送っているようですが、 それならば、他管理者へは直接出来上がったDBファイルを送れば済みそうですがどうでしょう? Windowsサーバですと、c:\mysql\data\DB名\下に テーブル名のファイルが3つあります。 それをそのまま送って同じ場所に上書きコピーすればOKです。 これならばTues17さんだけエラーを我慢すればすみます(笑)
お礼
項目によって、こちらから送った値を生かしたい項目と、先方のサーバの値を生かしたい項目が混在しているので、やっぱりテーブルのファイルをそのまま送るのはダメなんです... 結局、補足に書いたとおり、Insert IGNORE + Update で対処できました。 どうもありがとうございました。 #1にポイントを上げておきますね...
補足
回答ありがとうございます。 おっしゃるとおり、私だけがエラーを我慢すればOKならそうするのですが...サーバBと同様なサーバCがさらに別の場所(別の管理者のところ)にあって、そこのデータも「なければInsert、あればUpdate」したいのです。Updateする場合は、Updateしたくない項目もあるので... #1でいただいたアドバイスを元に、「まず全件Insertしてみる」路線で頑張っています。Insertの「IGNORE」オプションが使えるのでは?とこの週末に自宅でSQLを試してみるつもりだったのですが、体調不良で果たせませんでした... また結果をご報告します。
補足
連休を挟んでしまって遅くなり失礼しました。 「エラー承知でいったん全部Insertして...」と言うアイディアに、「目からウロコ!」とは思ったのですが... 結論から言うと、「やっぱりエラーなしでやりたい」です。 理由は二つあります。 1.他の2つのサーバへの処理は他の人に依頼するので、エラーが出ると不安がられる。 2.SQLをファイルに保存して、Dosでのコンソールから実行すると、エラーが発生した行で停止してしまう。 Windows上のSQL実行ソフトでやれば、エラー発生も警告表示だけで先に進んでくれるんですが... やっぱりMySQLのコマンドだけでは無理なのでしょうかね。