Google'da aramaya başladım ve muteks tablolarından bahseden bu makaleyi buldum.
Yaklaşık 14 milyon kayıt içeren bir tablom var. Aynı formatta daha fazla veri eklemek istersem, eklemek istediğim kaydın bir çift sorgu kullanmadan zaten mevcut olmadığından emin olmanın bir yolu var mı (yani, kontrol etmek için bir sorgu ve sonuç kümesi boşsa eklemek için bir sorgu)?
Bir alan üzerindeki unique
kısıtlaması, alan zaten oradaysa insert
işleminin başarısız olacağını garanti eder mi?
Görünüşe göre sadece bir kısıtlama ile, php aracılığıyla ekleme yaptığımda, komut dosyası çöküyor.
INSERT IGNORE INTO table` kullanın
bkz. http://bogdan.org.ua/2007/10/18/mysql-insert-if-not-exists-syntax.html
Ayrıca INSERT ... ON DUPLICATE KEY UPDATE
sözdizimi de vardır, açıklamaları dev.mysql.com adresinde bulabilirsiniz.
Google'ın web önbelleğine]1 göre bogdan.org.ua adresinden yapılan yayın:
18 Ekim 2007
Başlamak için: En son MySQL'den itibaren, başlıkta sunulan sözdizimi mümkün. Ancak bunu başarmanın çok kolay birkaç yolu vardır mevcut işlevsellik kullanılarak bekleniyor.
3 olası çözüm vardır: INSERT IGNORE, REPLACE veya INSERT ... ON DUPLICATE KEY UPDATE.
Bir tablomuz olduğunu düşünün:
CREATE TABLE
transcripts
(ensembl_transcript_id
varchar(20) NOT NULL,transcript_chrom_start
int(10) unsigned NOT NULL,transcript_chrom_end
int(10) unsigned NOT NULL, PRIMARY KEY (ensembl_transcript_id
) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;Şimdi transkriptleri içe aktaran otomatik bir boru hattımız olduğunu hayal edin Ensembl'den meta veriler ve çeşitli nedenlerden dolayı boru hattı uygulamanın herhangi bir aşamasında kırılabilir. Bu nedenle, iki şeyi sağlamamız gerekir şeyler: 1) Boru hattının tekrarlanan infazları bizi yok etmeyecektir veritabanı ve 2) tekrarlanan yürütmeler 'yinelenen' nedeniyle ölmeyecektir. birincil anahtar' hataları.
Yöntem 1: REPLACE kullanarak
Çok basit:
REPLACE INTO
transcripts
SETensembl_transcript_id
= 'ENSORGT00000000001',transcript_chrom_start
= 12345,transcript_chrom_end
= 12678;Eğer kayıt mevcutsa, üzerine yazılacaktır; eğer henüz mevcut değilse mevcutsa, oluşturulacaktır. Ancak, bu yöntemi kullanmak verimli değildir bizim durumumuz için: mevcut kayıtların üzerine yazmamıza gerek yok, sorun değil sadece onları atlamak için.
Yöntem 2: INSERT IGNORE kullanarak Ayrıca çok basit:
INSERT IGNORE INTO
transcripts
SETensembl_transcript_id
= 'ENSORGT00000000001',transcript_chrom_start
= 12345,transcript_chrom_end
= 12678;Burada, eğer 'ensembl_transcript_id' zaten mevcutsa veritabanı, sessizce atlanacaktır (yok sayılacaktır). (Daha kesin olmak gerekirse, İşte MySQL referans kılavuzundan bir alıntı: "Eğer IGNORE kullanıyorsanız anahtar sözcüğü, INSERT deyimi yürütülürken oluşan hatalar şunlardır bunun yerine uyarı olarak değerlendirilir. Örneğin, IGNORE olmadan, bir satır tablodaki mevcut bir UNIQUE dizini veya PRIMARY KEY değerini çoğaltır yinelenen anahtar hatasına neden olur ve ifade iptal edilir.".) Eğer kaydı henüz mevcut değilse, oluşturulacaktır.
Bu ikinci yöntemin aşağıdakiler de dahil olmak üzere çeşitli potansiyel zayıflıkları vardır başka bir sorun oluşması durumunda sorgunun iptal edilmemesi (bkz. manuel). Bu nedenle, daha önce test edilmemişse kullanılmalıdır. IGNORE anahtar sözcüğü.
Bir seçenek daha var:
INSERT ... ON DUPLICATE KEY UPDATE
kullanmak sözdizimi ve UPDATE kısmında sadece anlamsız bir şey yapmayın (boş) işlemi, 0+0'ı hesaplamak gibi (Geoffray MySQL optimizasyon motorunun bunu göz ardı etmesi için > id=id ataması operasyon). Bu yöntemin avantajı, yalnızca yinelenen anahtar olayları ve diğer hatalarda yine de iptal eder.Son bir uyarı olarak: bu yazı Xaprb'den esinlenmiştir. Ayrıca şunu da tavsiye ederim Esnek SQL sorguları yazma konusundaki diğer yazısına bakın.
yinelenen anahtar güncellemesinde veya yoksay ekle MySQL ile uygulanabilir çözümler olabilir.
mysql.com'a dayalı yinelenen anahtar güncellemesinde güncelleme örneği
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
UPDATE table SET c=c+1 WHERE a=1;
mysql.com'a dayalı insert ignore örneği
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
{VALUES | VALUE} ({expr | DEFAULT},...),(...),...
[ ON DUPLICATE KEY UPDATE
col_name=expr
[, col_name=expr] ... ]
Ya da:
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
SET col_name={expr | DEFAULT}, ...
[ ON DUPLICATE KEY UPDATE
col_name=expr
[, col_name=expr] ... ]
Ya da:
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name [(col_name,...)]
SELECT ...
[ ON DUPLICATE KEY UPDATE
col_name=expr
[, col_name=expr] ... ]
Bir istisna kabul edilebilirse, herhangi bir basit kısıtlama işi yapmalıdır. Örnekler:
Üzgünüm, bu aldatıcı bir şekilde basit görünüyor. Bizimle paylaştığınız bağlantıya göre kötü göründüğünü biliyorum ;-(
Ama yine de bu cevabı veriyorum, çünkü ihtiyacınızı karşılıyor gibi görünüyor. (Eğer değilse, gereksinimlerinizi güncellemenizi tetikleyebilir ki bu da "İyi Bir Şey"(TM) olacaktır).
Düzenlendi: Bir ekleme veritabanı benzersiz kısıtlamasını bozacaksa, sürücü tarafından aktarılan veritabanı düzeyinde bir istisna atılır. Komut dosyanızı kesinlikle bir hata ile durduracaktır. PHP'de bu durumu ele almak mümkün olmalıdır ...