MySQL tablosuna ekleyin veya varsa güncelleyin


875

Bir veritabanı tablosuna satır eklemek istiyorum, ancak aynı benzersiz anahtarla bir satır varsa, satırı güncellemek istiyorum.

Örneğin:

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

Diyelim ki benzersiz anahtar var idve Veritabanımda bir satır var id = 1. Bu durumda, bu satırı bu değerlerle güncellemek istiyorum. Normalde bu bir hata verir.
Ben kullanırsanız insert IGNOREo hatayı göz ardı eder, ama yine de güncelleme olmayacaktır.


5
SQL, bu kullanım durumu için sözdizimindeki değerlerin yinelenmesini zorlamayan ve birincil anahtarı koruyan resmi bir sözdizimine ihtiyaç duyar.
Pete Alvin


Uyarı: 5.7 sürümünden itibaren bu yaklaşım INSERT / UPDATE işleminin bir parçası olarak WHERE yantümcesini doğrudan desteklemez. Ayrıca, bir UPDATE aslında denetim amaçları için önemli olduğu takdirde iki ayrı işlem (DELETE ve INSERT) olarak sayılır. (Learnbit)
dreftymac

Yanıtlar:


1599

kullanım INSERT ... ON DUPLICATE KEY UPDATE

SORGU:

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

86
+1 Bulduğum kadarıyla, bu yöntem otomatik artış tuşları ve diğer benzersiz anahtar çarpışmaları için INTO REPLACE'dan daha az sorunludur ve daha verimlidir.
Andrew Ensley

46
Hepinizin bunu ima ettiğini biliyorum, ama diğerleri için açık olmak istiyorum. Eklediğiniz kimlik BİRİNCİL ANAHTAR veya BENZERSİZ değilse, bu çalışmaz. Bu benim için işe yaramadı çünkü kimliğim benzersiz değildi.
Keven

7
Acaba neden tek satır başarıyla (yinelenen anahtar) güncellenirken affected row countsonuçları 2? Bu sonuca sahip olan başka biri var mı? (Veriler doğru şekilde güncellenir: yani sadece 1 satır güncellenir)
Dimitry K

15
Bu biraz geç, ama yine de: kılavuzdaON DUPLICATE KEY UPDATE , etkilenen satırları 2 oranında arttıran güncellemeler belirtilmiştir. Hiçbir şey gerçekten güncellenmemişse (normal ile aynı UPDATE) 0 bildirir .
Vatev

61
Ayrıca, girmeye çalıştığınız değere başvurmak için VALUES (ad) kullanabileceğinizi unutmayın; örneğin INT tabloya (id, ad, yaş) INSERT IN VALUES (1, "A", 19) ON DUPLICATE KEY UPDATE name = VALUES (name) , yaş = DEĞERLER (yaş)
Meraklı Sam

246

DEĞİŞTİRİN

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

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

11
@Piontek Çünkü bu daha kısa ve kolay anlaşılır ve hiç kimse neden "tekrar üzerine eklemek" daha iyi açıkladı.
Mr_Chimp

77
kaydın kimliklerini değiştirir ve böylece dış referansları yok edebilir.
boh

102
REPLACE INTO ile ilgili diğer sorun, TÜM alanlar için değer belirtmeniz gerektiğidir ... aksi takdirde alanlar kaybolur veya varsayılan değerlerle değiştirilir. REPLACE INTO , varsa, satırı siler ve yeni satırı ekler. Örnekte, 'DEĞİŞTİR tablo (id, yaş) değerlerini (1, 19) değiştirdiyseniz, ad alanı null olur.
Dale

33
Bu aslında tüm satırı SİL ve yeni INSERT gerçekleştir.
mjb

8
@mjb Bu nedenle, DELETE ayrıcalıklarına sahip olmanız gerekir, bu da onlara ihtiyacınız yoksa sahip olmamanızdır. Ortamımın veritabanı kullanıcısında yalnızca INSERT ve UPDATE izinleri var, bu nedenle REPLACE çalışmaz.
ndm13

54

Toplu ekleme kullanırken aşağıdaki sözdizimini kullanın:

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

Yeni değeri değiştirmek istiyorsanız çok yararlı
Açlık

Eğer VALUES(name)değil çalışır, deneyebilirsinname = 'name_value',...;
Oğul Pham

26

Şunu deneyin:

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

Bu yardımcı olur umarım.


6
aslında yeni bir kimlik ile başka bir satıra yeni değerler eklemek zorunda değilim yerine id = 1 mevcut değerleri bu değerlerle değiştirmek istiyorum. (anladığım gibi bu kimliği
arttırır

49
Yinelemelerde kimliği bir arttırmak istediğini sanmıyorum.
Donnie

7
"geçiş" aradığınız kelime değil :) Ne yazık ki, şimdi "geçiş" gördüm, artık gerçek kelimeyi görselleştiremiyorum ..
mwfearnley

1
"Travers" veya "cover" mı arıyorsunuz?
Chris Dev

4
@mwfearnley Görselleştirmeye çalıştığınız kelime "aşmalar" dır. Sadece bir buçuk yıl aldı :-)
Michael Krebs

20

Bunu dene:

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

Not:
Burada id birincil anahtarsa, ilk ekleme işleminden sonra id='1'her ekleme girişimi ile id='1'ad ve yaşı güncelleyecek ve önceki ad yaşı değişecektir.


Kimlik kullanmadan çalışmak istiyorum . Birincil anahtar olmadan denediniz mi?
ersks

@ersks soruyu görüyor. kullanıcı benzersiz bir anahtar olduğunda sordu
Rasel

Bunu anladım, ama sadece bu değerlerin bilindiği sorunumu çözmeye çalışıyorum. Yani, böyle bir durumda yukarıda doğru çözümü umarak yorum yazdım.
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);

Tüm bu çözümler sorunuzla ilgili olarak çalışacaktır.

Bu bildirimle ilgili ayrıntıları öğrenmek istiyorsanız bu bağlantıyı ziyaret edin


REPLACEbağlı belgede belgelenmedi.
Ray Baxter

yazım hatalarıyla dolu sql sorguları, örnekleriniz çalışmaz. Tabloya (tabloya değil) ve dupleks anahtar güncellemesine (duplup güncelleme setine değil) yerleştirilir. Bunu kimin onaylayacağından emin değilim
Robert Sinclair

1
Yazım hatası için özür dilerim. Beni düzelttiğiniz için teşekkürler
Dilraj Singh

11

SQLite kullanırken:

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

idBirincil anahtar olması şartıyla . Ya da sadece başka bir satır ekler. Bkz. INSERT (SQLite).


Ne replace intoyapar tam olarak "içine insert veya güncelleme mevcut" dir. @Owl
DawnSong

+1 (1/3) Bunu durumum için işe yaradı buldum - Varolan bir satırı benzersiz bir anahtarla değiştirmem gerekiyordu veya yoksa yoksa satırı ekleyin. Burada en basit çözümler.
therobyouknow

( 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) Sorgum

(
3/3

2
Bu mysql sorunu, sağlanmadığı takdirde yerine diğer değerleri kaldıracak olmasıdır. Ancak @ fabiano-souza çözümü daha uygundur
Quamber Ali

11

Sadece burada bu çözümü arıyor ama aynı yapılandırılmış başka bir tablodan güncellemek için (benim durumumda web sitesi DB canlı DB test):

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

Başka bir yerde belirtildiği gibi, yalnızca güncellemek istediğiniz sütunların daha sonra dahil edilmesi gerekir ON DUPLICATE KEY UPDATE.

Sütunları listelemeye gerek yok INSERTveya SELECTmuhtemelen daha iyi bir uygulama olduğunu kabul ediyorum.


4

Bir non-primaryalanı ölçüt / koşul olarak yapmak istemeniz durumunda , o tabloyu üzerinde tetiklemek ON DUPLICATEiçin bir UNIQUE INDEXanahtar yapabilirsiniz DUPLICATE.

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

Ve iki alanı tablo üzerinde benzersiz kılmak için birleştirmek isterseniz, bunu son parametreye daha fazla ekleyerek başarabilirsiniz.

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

Dikkat edin, önce diğer satırlarda aynı nameve agedeğere sahip tüm verileri sildiğinizden emin olun .

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

Bundan sonra, ON DUPLICATEolayı tetiklemelidir .

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

2

Benim durumumda sorguların altında oluşturdum ama ilk sorguda id1 zaten varsa ve yaş zaten oradaysa, bundan sonra agedeğeri olmadan ilk sorgu oluşturursanız agehiçbiri olmaz

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

yukarıdaki sorunu önlemek için aşağıdaki gibi sorgu oluşturun

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

size yardımcı olsun ...


2
Değerleri neden iki kez atamamız gerektiğini bilen var mı? MySQL neden tüm atama ifadelerini çoğaltmadan sorguyu ON DUPLICATE KEY UPDATE'de sonlandırmamıza izin vermiyor? Bazı veritabanı tablolarının birçok sütunu vardır ve bu gereksiz / artağan gibi görünür. Neden alternatif ödevler için bir seçeneğe sahip olduğumuzu anlıyorum, ama neden bunları atlama seçeneğine de sahip değilsiniz? Sadece kimse biliyor mu merak ediyorum.
Mavi Su

2

Eski alanı korumak istiyorsanız (Örn: ad için). Sorgu şu şekilde olacaktır:

INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE    
name=name, age=19;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.