Masukkan ke dalam tabel MySQL atau perbarui jika ada

875

Saya ingin menambahkan baris ke tabel database, tetapi jika ada baris dengan kunci unik yang sama, saya ingin memperbarui baris.

Sebagai contoh:

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

Katakanlah kunci uniknya adalah id, dan di Database saya , ada baris dengan id = 1. Dalam hal ini, saya ingin memperbarui baris itu dengan nilai-nilai ini. Biasanya ini memberikan kesalahan.
Jika saya menggunakannya insert IGNOREakan mengabaikan kesalahan, tetapi masih tidak memperbarui.

Keshan
sumber
6
SQL membutuhkan sintaksis resmi untuk kasus penggunaan ini yang tidak memaksa duplikasi nilai dalam sintaksis dan mempertahankan kunci utama.
Pete Alvin
Untuk mendapatkan id yang terpengaruh, rujuk ke MySQL ON DUPLICATE KEY - id insert terakhir?
Kris Roofe
Peringatan: pada versi 5.7 pendekatan ini tidak secara langsung mendukung klausa WHERE sebagai bagian dari operasi INSERT / UPDATE. Juga, UPDATE sebenarnya diperhitungkan sebagai dua operasi terpisah (HAPUS dan INSERT) ... dalam kasus yang penting untuk tujuan audit. (Learnbit)
dreftymac

Jawaban:

1600

Menggunakan INSERT ... ON DUPLICATE KEY UPDATE

PERTANYAAN:

INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE    
name="A", age=19
Donnie
sumber
86
+1 Dari apa yang saya temukan, metode ini tidak terlalu bermasalah untuk kunci kenaikan otomatis dan benturan kunci unik lainnya daripada REPLACE INTO, dan metode ini lebih efisien.
Andrew Ensley
46
Saya tahu Anda semua menyinggung ini, tapi saya ingin menjadi eksplisit untuk orang lain. Jika ID yang Anda masukkan BUKAN KUNCI UTAMA atau UNIK, maka ini tidak akan berfungsi. Awalnya ini tidak berfungsi untuk saya karena ID saya tidak unik.
Keven
7
Saya heran mengapa affected row counthasil 2ketika berhasil memperbarui (pada kunci duplikat) satu baris? Adakah yang punya hasil ini? (Data diperbarui dengan benar: artinya hanya 1 baris yang diperbarui)
Dimitry K
15
Ini agak terlambat, tetapi bagaimanapun: dinyatakan dalam manual bahwa pembaruan dalam ON DUPLICATE KEY UPDATEmeningkatkan baris yang terkena dampak oleh 2. Ia melaporkan 0 jika tidak ada yang benar-benar diperbarui (sama seperti biasa UPDATE).
Vatev
61
Perhatikan juga bahwa Anda dapat menggunakan VALUES (nama) untuk referensi ke nilai yang Anda coba masukkan misalnya tabel INSERT INTO (id, name, age) VALUES (1, "A", 19) PADA DUPLICATE KEY UPDATE nama = VALUES (nama) , age = VALUES (age)
Penasaran Sam
246

Lihat REPLACE

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

REPLACE into table (id, name, age) values(1, "A", 19)
Martin Schapendonk
sumber
11
@Piontek Karena yang ini lebih pendek dan lebih mudah dipahami dan tidak ada yang menjelaskan mengapa "masukkan duplikat" lebih baik.
Mr_Chimp
77
itu mengubah ID catatan dan dengan demikian dapat menghancurkan referensi asing.
boh
102
Masalah lain dengan REPLACE INTO adalah Anda harus menentukan nilai untuk SEMUA bidang ... jika tidak, bidang akan hilang atau diganti dengan nilai default. REPLACE INTO dasarnya menghapus baris jika ada, dan menyisipkan baris baru. Dalam contoh, jika Anda melakukan nilai REPLACE INTO table (id, age) (1, 19) maka bidang nama akan menjadi nol.
Dale
33
Ini sebenarnya HAPUS seluruh baris dan lakukan INSERT baru.
mjb
8
@ mjb Karenanya, Anda harus memiliki hak istimewa DELETE, yang sebaiknya tidak dimiliki jika Anda tidak membutuhkannya. Pengguna basis data lingkungan saya hanya memiliki izin INSERT dan UPDATE, sehingga REPLACE tidak akan berfungsi.
ndm13
54

Saat menggunakan batch insert, gunakan sintaks berikut:

INSERT INTO TABLE (id, name, age) VALUES (1, "A", 19), (2, "B", 17), (3, "C", 22)
ON DUPLICATE KEY UPDATE
    name = VALUES (name),
    ...
Fabiano Souza
sumber
Sangat berguna jika Anda ingin memanipulasi nilai baru
Kelaparan
Jika VALUES(name)tidak berhasil, Anda dapat mencobaname = 'name_value',...;
Son Pham
26

Coba ini:

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

Semoga ini membantu.

Luis Reyes
sumber
6
sebenarnya saya tidak perlu menambahkan nilai baru ke baris lain dengan ID baru sebagai gantinya saya ingin mengganti nilai yang ada id = 1 dengan nilai-nilai ini. (Seperti yang saya pahami, ini menambah id dan menambahkan data)
Keshan
49
Saya tidak berpikir dia ingin meningkatkan id satu per satu di duplikat.
Donnie
7
"melampaui" bukanlah kata yang Anda cari :) Sayangnya, sekarang saya telah melihat "melampaui", saya tidak dapat lagi memvisualisasikan kata yang sebenarnya ..
mwfearnley
1
Apakah Anda mencari "melintasi" atau "selimut"?
Chris Dev
4
@ mwfearnley Kata yang ingin Anda visualisasikan adalah "melampaui". Hanya butuh satu setengah tahun :-)
Michael Krebs
20

Coba ini:

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

Catatan:
Di sini jika id adalah kunci utama maka setelah penyisipan pertama dengan id='1'setiap kali upaya memasukkan id='1'akan memperbarui nama dan usia dan usia nama sebelumnya akan berubah.

Rasel
sumber
Saya ingin bekerja tanpa menggunakan id . Sudahkah Anda mencoba tanpa kunci primer?
ersks
@ks melihat pertanyaannya. pengguna bertanya tentang kapan ada kunci unik
Rasel
Saya mengerti, tetapi saya mencoba untuk menyelesaikan masalah saya di mana hanya nilai-nilai ini yang diketahui. Jadi, dalam situasi seperti itu saya menulis komentar di atas dengan harapan solusi yang tepat.
ersks
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);

Semua solusi ini akan bekerja mengenai pertanyaan Anda.

Jika Anda ingin mengetahui secara detail mengenai pernyataan ini, kunjungi tautan ini

Dilraj Singh
sumber
REPLACEtidak didokumentasikan dalam dokumen tertaut.
Ray Baxter
sql kueri yang penuh dengan kesalahan ketik, contoh Anda tidak akan berfungsi. Ini INSERT INTO TABLE (bukan INTO TABLE) dan ON DUPLICATE UPDATE KUNCI (bukan ON DUPLICATE SET UPDATE). Tidak yakin siapa yang memperbaiki ini
Robert Sinclair
1
Maaf atas kesalahan pengetikan. Terima kasih telah mengoreksi saya
Dilraj Singh
11

Saat menggunakan SQLite:

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

Asalkan itu idadalah kunci utama. Atau hanya memasukkan baris lain. Lihat INSERT (SQLite).

DawnSong
sumber
Apa yang replace intodilakukan adalah "masukkan ke dalam, atau perbarui bila ada". @ Owl
DawnSong
+1 (1 dari 3) Saya menemukan ini berfungsi untuk situasi saya - saya perlu mengganti baris yang ada dengan kunci unik atau jika tidak ada kemudian tambahkan baris. Solusi paling sederhana di sini.
therobyouknow
(2 dari 3) Permintaan saya: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();
therobyouknow
(3 dari 3) Pertanyaan / jawaban terkait stackoverflow.com/questions/41767517/…
therobyouknow
2
Masalah dengan ini di mysql adalah bahwa replace akan menghapus nilai-nilai lain jika mereka tidak disediakan. Namun solusi @ fabiano-souza lebih tepat
Quamber Ali
11

Hanya karena saya di sini mencari solusi ini tetapi untuk memperbarui dari tabel lain yang terstruktur identik (dalam kasus situs web saya uji DB untuk hidup DB):

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

Seperti disebutkan di tempat lain, hanya kolom yang ingin Anda perbarui yang perlu dimasukkan setelahnya ON DUPLICATE KEY UPDATE.

Tidak perlu mendaftar kolom di INSERTatau SELECT, meskipun saya setuju itu mungkin praktik yang lebih baik.

SteveCinq
sumber
4

Jika Anda ingin menjadikan non-primarybidang sebagai kriteria / kondisi untuk ON DUPLICATE, Anda bisa membuat UNIQUE INDEXkunci di tabel itu untuk memicu DUPLICATE.

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

Dan jika Anda ingin menggabungkan dua bidang untuk membuatnya unik di atas meja, Anda bisa mencapainya dengan menambahkan lebih banyak pada parameter terakhir.

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

Catatan, pastikan untuk menghapus terlebih dahulu semua data yang memiliki nilai yang sama namedan agedi seluruh baris lainnya.

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

Setelah itu, harus memicu ON DUPLICATEacara.

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

Dalam kasus saya, saya membuat pertanyaan di bawah ini tetapi dalam permintaan pertama jika id1 sudah ada dan usia sudah ada di sana, setelah itu jika Anda membuat permintaan pertama tanpa agedari nilai agetidak akan ada

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

untuk menghindari masalah di atas, buat permintaan seperti di bawah ini

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

semoga akan membantu Anda ...

Renish Gotecha
sumber
2
Adakah yang tahu mengapa kita harus menetapkan nilai dua kali? Mengapa MySQL tidak mengizinkan kami untuk mengakhiri permintaan di ON DUPLICATE KEY UPDATE tanpa menduplikasi semua pernyataan tugas? Beberapa tabel database memiliki banyak kolom, dan ini tampak berlebihan / tidak berguna. Saya mengerti mengapa kami memiliki opsi untuk tugas alternatif, tetapi mengapa tidak memiliki opsi untuk menghilangkannya juga? Hanya ingin tahu apakah ada yang tahu.
Blue Water
2

Dalam hal ini, Anda ingin menyimpan bidang yang lama (Misalnya: nama). Kueri akan:

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