MySQLテーブルに挿入するか、存在する場合は更新します


875

行をデータベーステーブルに追加したいのですが、同じ一意のキーを持つ行が存在する場合、その行を更新します。

例えば:

insert into table (id, name, age) values(1, "A", 19)

一意のキーがidで、データベースにの行があるとしid = 1ます。その場合、その行をこれらの値で更新します。通常、これはエラーになります。
使用insert IGNOREするとエラーは無視されますが、それでも更新されません。


6
SQLは、このユースケースの公式の構文を必要とします。これは、構文内の値の複製を強制せず、主キーを保持します。
ピートアルビン

影響を受けるIDを取得するには、MySQL ON DUPLICATE KEY-最後の挿入IDを
Kris Roofe

警告:バージョン5.7では、このアプローチはINSERT / UPDATE操作の一部としてWHERE句を直接サポートしていません。また、UPDATEは実際には2つの別個の操作(DELETEとINSERT)...としてカウントされます。(Learnbit)
dreftymac

回答:


1599

使用する INSERT ... ON DUPLICATE KEY UPDATE

クエリ:

INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE    
name="A", age=19

86
+1私が見つけたことから、この方法は自動インクリメントキーや他の一意のキーの衝突に対してREPLACE INTOよりも問題が少なく、より効率的です。
Andrew Ensley

46
私はあなた方全員がこれについてほのめかしていることを知っていますが、私は他の人たちに明白になりたいです。挿入するIDが主キーまたは一意でない場合、これは機能しません。私のIDが一意ではなかったため、これは最初は機能しませんでした。
Keven

7
(重複キーで)単一行を正常に更新するとaffected row count、なぜ結果が2出るのでしょうか?他の誰かがこの結果を出しましたか?(データは正しく更新されます:1行のみが更新されることを意味します)
Dimitry K

15
これは少し遅れますが、とにかく:影響を受ける行を2ずつ増やすように更新するとマニュアルに記載されていますON DUPLICATE KEY UPDATE。実際に何も更新されていない場合は0を報告します(通常のと同じUPDATE)。
Vatev 2014年

61
VALUES(名前)を使用して、挿入しようとする値を参照できることにも注意してください。例:INSERT INTO table(id、name、age)VALUES(1、 "A"、19)ON DUPLICATE KEY UPDATE name = VALUES(name) 、age = VALUES(age)
好奇心が強いSam

246

REPLACEを確認する

http://dev.mysql.com/doc/refman/5.0/en/replace.html

REPLACE into table (id, name, age) values(1, "A", 19)

11
@Piontekこれは短くて理解しやすく、「重複して挿入」の方が優れている理由を誰も説明しなかったためです。
Mr_Chimp 2013年

77
レコードのIDが変更されるため、外部参照が破棄される可能性があります。
2013

102
REPLACE INTOのもう1つの問題は、すべてのフィールドに値を指定する必要があることです。そうしないと、フィールドが失われたり、デフォルト値に置き換えられたりします。REPLACE INTO は、行が存在する場合は基本的にその行を削除し、新しい行を挿入します。この例では、 'REPLACE INTO table(id、age)values(1、19)'を実行した場合、名前フィールドはnullになります。
デール

33
これは実際には行全体を削除し、新しいINSERTを実行します。
mjb 2014年

8
@mjbしたがって、DELETE特権を持っている必要がありますが、必要がない場合はDELETE特権を持たないのが最善です。私の環境のデータベースユーザーはINSERTおよびUPDATE権限しか持っていないため、REPLACEは機能しません。
ndm13

54

バッチ挿入を使用する場合は、次の構文を使用します。

INSERT INTO TABLE (id, name, age) VALUES (1, "A", 19), (2, "B", 17), (3, "C", 22)
ON DUPLICATE KEY UPDATE
    name = VALUES (name),
    ...

新しい値を操作したい場合に非常に役立ちます
Hunger

VALUES(name)動作しない場合は、試すことができますname = 'name_value',...;
Son Pham

26

これを試してください:

INSERT INTO table (id, name, age) VALUES (1, 'A', 19) ON DUPLICATE KEY UPDATE id = id + 1;

お役に立てれば。


6
実際、私は新しいIDを持つ別の行に新しい値を追加する必要はありません。代わりに、id = 1の既存の値をこの値で置き換えます。(私が理解しているように、これによりIDが増加し、データが追加されます)
Keshan

49
私は彼が重複でIDを1つ増やしたいとは思わない。
ドニー

7
"transgress"はあなたが探している単語ではありません:)残念ながら、私は "transgress"を見たので、実際の単語を視覚化することはできません。
mwfearnley

1
「トラバース」または「カバー」を探していましたか?
Chris Dev 2017年

4
@mwfearnley視覚化しようとしていた言葉は「超越的」です。1年半しかかかりませんでした:-)
Michael Krebs

20

これを試して:

INSERT INTO table (id,name,age) VALUES('1','Mohammad','21') ON DUPLICATE KEY UPDATE name='Mohammad',age='21'

注:
ここでidが主キーの場合、最初の挿入の後、id='1'毎回挿入しようとするid='1'と名前と年齢が更新され、以前の名前の年齢が変更されます。


idを使わずに作業したい。主キーなしで試しましたか?
2017

@ersksが質問を表示します。ユーザーが一意のキーがある場合について質問した
Rasel

私はそれを手に入れましたが、私はこれらの唯一の値がわかっている私の問題を解決しようとしています。だから、そのような状況で私は正しい解決策を期待して上記のコメントを書きました。
2017

15
INSERT IGNORE INTO table (id, name, age) VALUES (1, "A", 19);

INSERT INTO TABLE (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE NAME = "A", AGE = 19;

REPLACE INTO table (id, name, age) VALUES(1, "A", 19);

これらすべてのソリューションは、あなたの質問に関して機能します。

これらのステートメントについて詳しく知りたい場合は、このリンクにアクセスしてください


REPLACEリンクされたドキュメントに記載されていません。
レイバクスター

誤字だらけのSQLクエリでは、例は機能しません。これはINSERT INTO TABLE(INTO TABLEではない)およびON DUPLICATE KEY UPDATE(ON DUPLICATE UPDATE SETではない)です。誰がこれを支持しているのかわからない
ロバート・シンクレア

1
タイプミスのエラーでごめんなさい。私を訂正してくれてありがとう
Dilraj Singh

11

SQLiteを使用する場合:

REPLACE into table (id, name, age) values(1, "A", 19)

それidが主キーである場合。または、別の行を挿入するだけです。INSERT(SQLite)を参照してください。


replace into行うことはまさに「への挿入、または更新既存」です。@Owl
DawnSong

+1(1 of 3)これは自分の状況で機能することがわかりました。既存の行を一意のキーに置き換えるか、存在しない場合は行を追加する必要がありました。ここで最も簡単なソリューション。
therobyouknow 2017年

(2/3)私のクエリ: CREATE TRIGGER worklog_update AFTER INSERT ON worklog FOR EACH ROW REPLACE INTO support_time_monthly_hours ( ProjectID, monthTotalTime, Year, Month ) SELECT jiraissue.PROJECT, SUM(worklog.timeworked), YEAR(CURRENT_DATE()), MONTH(CURRENT_DATE()) FROM worklog, jiraissue WHERE worklog.issueid = jiraissue.ID AND jiraissue.PROJECT = (SELECT PROJECT FROM jiraissue WHERE NEW.issueid = jiraissue.ID ) AND worklog.startdate BETWEEN DATE_FORMAT(NOW() ,'%Y-%m-01 00:00:00') AND NOW();
2/3

(3の3)関連する質問/回答stackoverflow.com/questions/41767517/...
therobyouknow

2
mysqlでのこの問題は、他の値が提供されていない場合、replaceによって他の値が削除されることです。ただし、@ fabiano-souzaソリューションの方が適切です
Quamber Ali 2018

11

ここでこのソリューションを探していたが、同じ構造の別のテーブルから更新した場合(私の場合は、WebサイトテストDBからライブDBへ):

INSERT  live-db.table1
SELECT  *
FROM    test-db.table1 t
ON DUPLICATE KEY UPDATE
        ColToUpdate1 = t.ColToUpdate1,
        ColToUpdate2 = t.ColToUpdate2,
        ...

他の場所で述べたように、更新したい列のみをの後に含める必要がありますON DUPLICATE KEY UPDATE

INSERTまたはの列をリストする必要はありませんが、SELECTおそらくより良い方法だと思います。


4

non-primary基準/条件としてフィールドを作成したい場合はON DUPLICATEUNIQUE INDEXそのテーブルにキーを作成してをトリガーできますDUPLICATE

ALTER TABLE `table` ADD UNIQUE `unique_index`(`name`);

また、2つのフィールドを組み合わせてテーブル上で一意にする場合は、最後のパラメーターにさらに追加することでこれを実現できます。

ALTER TABLE `table` ADD UNIQUE `unique_index`(`name`, `age`);

最初に、他の行nameと同じage値を持つすべてのデータを必ず削除してください。

DELETE table FROM table AS a, table AS b WHERE a.id < b.id 
AND a.name <=> b.name AND a.age <=> b.age;

その後、ON DUPLICATEイベントをトリガーする必要があります。

INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE    
name = VALUES(name), age = VALUES(age)

2

私の場合、以下のクエリを作成しましたが、最初のクエリでは、id1が既に存在し、年齢がすでに存在している場合、その後、最初のクエリを作成した場合age、の値はageなしになります

REPLACE into table SET `id` = 1, `name` = 'A', `age` = 19

上記の問題を回避するために、以下のようなクエリを作成します

INSERT INTO table SET `id` = '1', `name` = 'A', `age` = 19 ON DUPLICATE KEY UPDATE `id` = "1", `name` = "A",`age` = 19

それがあなたを助けるかもしれません...


2
値を2回割り当てる必要がある理由を誰かが知っていますか?MySQLではなぜすべての割り当てステートメントを複製せずにON DUPLICATE KEY UPDATEでクエリを終了できないのですか?一部のデータベーステーブルには多くの列があり、これは冗長/不必要なようです。なぜ代替割り当てのオプションがあるのか​​理解していますが、それらを省略するオプションもないのはなぜですか?誰かが知っている場合はちょうど好奇心が強い。
ブルーウォーター、

2

場合によっては、古いフィールド(例:名前)を保持する必要があります。クエリは次のようになります。

INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE    
name=name, age=19;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.