web-dev-qa-db-ja.com

MySQL一括挿入または更新

MySQLサーバーでINSERT OR UPDATEのようなクエリを一括で実行する方法はありますか?

INSERT IGNORE ...

フィールドが既に存在する場合、それは単に無視され、何も挿入されないため、機能しません。

REPLACE ...

フィールドが既に存在する場合、フィールドを更新するのではなく、最初にDELETEそれからINSERTそれを再び使用するため、機能しません。

INSERT ... ON DUPLICATE KEY UPDATE

動作しますが、一括して使用することはできません。

そのため、一括で発行できるINSERT ... ON DUPLICATE KEY UPDATEなどのコマンドがあるかどうかを知りたい(同時に複数行)。

27
rid

INSERT ... ON DUPLICATE KEY UPDATEを使用して、複数の行を挿入/更新できますcandocumentation には次の例があります。

INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);

それとも私はあなたの質問を誤解していますか?

69
user359996

これを行う1つの方法は、一時テーブルを作成し、そこにデータを挿入し、結合を使用して1つのクエリを実行し、存在しないレコードを挿入してから、存在するフィールドを更新することです。基本はこのようなものです。

CREATE TABLE MyTable_Temp LIKE MyTable

LOAD DATA INFILE..... INTO MyTable_Temp

UPDATE MyTable INNER JOIN 
MyTable_Temp
ON MyTable.ID=MyTable_Temp.ID
SET MyTable.Col1=MyTable_Temp.Col1, MyTable.Col2=MyTable_Temp.Col2.....

INSERT INTO MyTable(ID,Col1,Col2,...)
SELECT ID,Col1,Col2,... 
FROM MyTable_Temp
LEFT JOIN MyTable 
ON MyTable_Temp.ID = MyTable.ID
WHERE myTable.ID IS NULL

DROP TABLE MyTable_Temp

構文は正確ではないかもしれませんが、これで基本がわかるはずです。また、私はそれがきれいではないことを知っていますが、仕事を終わらせます。

更新

最初に挿入を行うと、更新が呼び出されたときに挿入されたすべての行が更新されるため、挿入と更新の順序を入れ替えました。最初に更新すると、既存のレコードのみが更新されます。結果は同じであるはずですが、これによりサーバーの作業が少し少なくなります。

18
Kibbee

この質問はすでに正しく回答されていますが(MySQLは、予想される複数の値セット構文でON DUPLICATE UPDATEを介してこれをサポートします)、MySQLを使用して誰でも実行できるデモを提供することでこれを拡張したいと思います:

CREATE SCHEMA IF NOT EXISTS `test`;
DROP TABLE IF EXISTS test.new_table;
CREATE TABLE test.new_table (`Key` int(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`Key`)) ENGINE=InnoDB AUTO_INCREMENT=106 DEFAULT CHARSET=utf8;

SELECT * FROM test.new_table;
INSERT INTO test.new_table VALUES (1),(2),(3),(4),(5) ON DUPLICATE KEY UPDATE `Key`=`Key`+100;
SELECT * FROM test.new_table;
INSERT INTO test.new_table VALUES (1),(2),(3),(4),(5) ON DUPLICATE KEY UPDATE `Key`=`Key`+100;
SELECT * FROM test.new_table;

出力は次のとおりです。

Empty set (0.00 sec)

Query OK, 5 rows affected (0.00 sec)
Records: 5  Duplicates: 0  Warnings: 0

+-----+
| Key |
+-----+
|   1 |
|   2 |
|   3 |
|   4 |
|   5 |
+-----+
5 rows in set (0.00 sec)

Query OK, 10 rows affected (0.00 sec)
Records: 5  Duplicates: 5  Warnings: 0

+-----+
| Key |
+-----+
| 101 |
| 102 |
| 103 |
| 104 |
| 105 |
+-----+
5 rows in set (0.00 sec)
2

プリフライトチェックを実行し、(既存の行を更新した後)重複キーの挿入をキャンセルする挿入トリガーを追加してみてください。

Infileのロードデータで動作することはもちろん、一括挿入でうまくスケーリングできるかどうかはわかりませんが、私が考えることができる最高の方法です。 :-)

0

OracleまたはMicrosoft SQLを使用している場合は、MERGEを使用できます。ただし、MySQLはそのステートメントと直接相関していません。あなたが言及した単一行のソリューションがありますが、あなたが指摘したように、それはあまりうまく行いません。これは、OracleとMySQLの違いと、MySQLでMERGEを使用してOracleが行うことについてのブログ投稿です。

http://blog.mclaughlinsoftware.com/2009/05/25/mysql-merge-gone-awry/

それはきれいな解決策ではなく、おそらくあなたが望むほど完全な解決策ではありませんが、私はそれが最善の解決策だと信じています。

0
IAmTimCorey