SQL "Duplicate entry for key" hatası, eklemek veya güncellemek istediğin değerin tabloda tanımlı bir benzersizlik kuralıyla çakıştığını bildirir. Çözüm, aynı komutu körlemesine yinelemek yerine hangi anahtarın ihlal edildiğini, bu anahtarın hangi sütunları kapsadığını ve mevcut satırın gerçekten amaçlanan kayıt olup olmadığını belirlemektir.
Hata kodu ve mesajın tam biçimi kullanılan veritabanı yönetim sistemine göre değişebilir; aşağıdaki tam hata çıktısı MySQL örneğine aittir.
SQL "Duplicate entry for key" hatası ne anlatır?
Primary key, her satırın kimliğini belirleyen anahtardır. Bir tabloda tek bir primary key tanımı bulunur; bu tanım tek sütunlu olabilir veya birkaç sütunun birlikte oluşturduğu birleşik anahtar şeklinde kurulabilir. UNIQUE kısıtlaması ise tek bir sütundaki değerin ya da sütun kümesinin oluşturduğu kombinasyonun tekrarını sınırlar.
Tek sütunlu primary key'de tekillik bir sütun üzerinden, birleşik anahtarda ise sütunların birlikte oluşturduğu değer üzerinden değerlendirilir. Öğrenci-ders tablosunda PRIMARY KEY (student_id, course_id) veya UNIQUE (student_id, course_id) kullanılırsa aynı öğrenci aynı derse ikinci kez kaydedilemez; bu kural açısından başka bir öğrenci aynı derse kaydedilebilir.
Bu nedenle hata, veritabanının veriyi rastgele reddettiğini değil, tanımlanmış veri bütünlüğünü koruduğunu gösterir. Çakışma primary key üzerinde de UNIQUE kuralı üzerinde de oluşabilir.
Çakışan anahtar ve değeri nasıl teşhis edilir?

MySQL'in bu hata biçiminde Duplicate entry sonrasındaki değeri ve for key sonrasındaki key/index adını ayrı oku. Key adı sütun adıyla aynı olmak zorunda değildir.
- Çakışan değeri hata mesajından aynen ayır.
- Key/index adını aynen kaydet.
- Komutun hedef tablosunu belirle; MySQL'de
SHOW CREATE TABLE users;ile tablo tanımını,SHOW INDEX FROM users;ileKey_nameveColumn_namealanlarını kontrol et.
Birleşik anahtarda aynı Key_name altında listelenen bütün sütunları birlikte ara. Örneğin koşul student_id = 7 AND course_id = 3 olmalıdır; yalnızca bir sütunu kullanan sorgu eksik teşhis verebilir. Bu SELECT yalnızca teşhis adımıdır, otomatik olarak UPDATE kararı vermez.
MySQL ile e-posta çakışmasını bulma
CREATE TABLE users (
user_id INT NOT NULL,
email VARCHAR(255) NOT NULL,
PRIMARY KEY (user_id),
UNIQUE KEY uq_users_email (email)
);
Bu şemada satır kimliği user_id, e-posta için key/index adı uq_users_email, bağlı sütun ise email'dir.
İlk kayıt kabul edilir:
INSERT INTO users (user_id, email)
VALUES (1, '[email protected]');
Aynı e-postayı farklı bir primary key değeriyle ekleyen ayrı komut:
INSERT INTO users (user_id, email)
VALUES (2, '[email protected]');
MySQL'de bu örnek için beklenen hata çıktısı:
ERROR 1062 (23000): Duplicate entry '[email protected]' for key 'users.uq_users_email'
Burada çakışan değer [email protected], ihlal edilen key/index ise users.uq_users_email'dir.
Mevcut satırı bulmak için:
SELECT user_id, email
FROM users
WHERE email = '[email protected]';
+---------+------------------+
| user_id | email |
+---------+------------------+
| 1 | [email protected] |
+---------+------------------+
Sonuçta yalnızca user_id = 1 ve [email protected] değerlerini içeren satır görünür. Bu sorgu çakışmayı teşhis eder; yeni kaydın mevcut kayıtla aynı anlamı taşıyıp taşımadığına göre sonraki işlem ayrıca belirlenir.
Aynı e-posta için dört işlem akışı nasıl karşılaştırılır?
[email protected] değeri üzerinden dört akışı birbirine karıştırmamak gerekir. Aşağıdaki SQL adımları, sözdizimini somutlaştırmak için MySQL biçiminde yazılmıştır; karar mantığı kullandığın DBMS'ye göre uyarlanmalıdır. Benzersiz anahtar ihlalinde normal INSERT başarısız olur, UPDATE de yeni değer başka bir satırda varsa aynı kısıtlamaya takılabilir.
| Akış | Amaç | SQL adımı | Beklenen sonuç | Karar ölçütü |
|---|---|---|---|---|
| Hatalı INSERT | Yeni kayıt istenir, ancak e-posta zaten kullanılıyordur. | INSERT INTO users (email, name) VALUES ('[email protected]', 'Ayşe'); |
Yeni satır eklenmez, duplicate-key hatası oluşur. | Çakışan değeri ve anahtar adını incele, aynı eklemeyi körlemesine tekrarlama. |
| SELECT ile kontrol | Çakışan e-postaya sahip mevcut satırı teşhis etmek. | SELECT user_id, email FROM users WHERE email = '[email protected]'; |
Eşleşen mevcut satır bulunur. | SELECT çözüm değil, sonraki INSERT veya UPDATE kararını veren bilgidir. |
| UPDATE | Mevcut kaydı doğru user_id ile hedeflemek. |
UPDATE users SET email = '[email protected]' WHERE user_id = 42; |
Hedef satır güncellenir; değer başka satırdaysa güncelleme tamamlanmaz. | user_id ve yeni değerin başka bir satırla çakışmadığını doğrula. |
| Yeni değerle INSERT | [email protected] yerine doğrulanmış yeni değerle gerçekten yeni kayıt oluşturmak. |
INSERT INTO users (email, name) VALUES ('[email protected]', 'Ayşe'); |
Yeni satır eklenir. | Yeni e-postanın benzersiz olduğu doğrulanmış olmalıdır. |
SELECT sorgusunun çalışma sonucunu görmek için şu örneği kullanabilirsin:
SELECT user_id, email
FROM users
WHERE email = '[email protected]';
Beklenen çıktı, eşleşme varsa ilgili user_id ve e-posta değerini taşıyan mevcut satırdır. Sonuç boşsa yeni kayıt akışı değerlendirilebilir. UPDATE'i otomatik olarak INSERT'in yerine koyma: amaç mevcut satırı değiştirmekse güncelle, amaç yeni satır oluşturmaksa benzersiz değerle ekle.
Yeni kayıt mı, mevcut kayıt mı? Karar ağacı nasıl kurulur?

Karar ağacını hata mesajındaki iki parçayla başlat: çakışan değer, örneğin [email protected], ve anahtar adı, örneğin uq_users_email. Bu bilgiler, ihlal edilen benzersizlik kuralını gösterir.
Çakışan değer ve anahtar adı, ihlal edilen benzersizlik kuralını gösterir. Hedef mevcut kayıtsa doğru satırıUPDATEet; hedef yeni kayıtsa veriyi düzeltip benzersiz değerleINSERTet. Kuralı anlamadanINSERT IGNOREkullanma.
Evet: Hedef mevcut kayıtsa, SELECT ile doğru user_id'yi doğrula ve yalnızca o satırı güncelle. Yeni değer başka bir satırda bulunuyorsa değeri değiştir veya güncelleme kararını yeniden değerlendir.
Hayır: Hedef mevcut kayıt değilse, aynı isteğin tekrar gönderilmesiyle hatalı kaynak verisini ayır. Tekrarlanan istekte yeni INSERT yapma; kaynak veri hatalıysa düzelt; gerçekten yeni kayıtsa benzersizliği doğrulanan değerle ekleme yap.
MySQL'de INSERT IGNORE, benzersiz anahtar çakışmasında ilgili satırı eklemeyip hatayı uyarı düzeyine indirebilir. Bu nedenle reddedilen veriyi görünmez hâle getirebilir ve veri politikasının yerine geçmez. Farklı DBMS'lerde aynı ifade veya aynı davranış varsayılmamalı, kullanılan sistemin resmî çakışma yönetimi belgeleri incelenmelidir.
Ön kontrol neden tek başına yetmez? DBMS farkları ve eşzamanlı işlemler
SELECT ile “bu değer bulunamadı” sonucunu almak, yazma işleminin garanti edildiği anlamına gelmez. Kontrol ile INSERT veya benzersiz sütunu değiştiren UPDATE arasındaki kısa aralıkta başka bir işlem aynı değeri yazabilir. Benzersizlik kuralı bu yüzden yalnızca ön kontrolde değil, yazma aşamasında da değerlendirilir. Ön kontrol teşhis için yararlıdır, ancak tek başına eşzamanlılık çözümü değildir.
Kontrol ile yazma arasında ne olur?
- t0: İşlem A,
[email protected]değerini arar ve eşleşen satır bulamaz. - t1: İşlem B aynı e-posta ile yeni kayıt ekler ve işlemini tamamlar.
- t2: İşlem A ekleme yapmayı dener. Veritabanı, benzersiz anahtarda artık aynı değer bulunduğunu görür ve normal hata akışında duplicate hatası üretir.
Bu yarışı yönetmek için işlem sınırını, transaction isolation ayarını, gerekiyorsa kilitleme yaklaşımını ve conflict-handling veya upsert seçeneğini birlikte değerlendirmen gerekir. Daha sıkı izolasyon ya da açık kilitleme bazı çakışmaları farklı biçimde yönetebilir; bekleme davranışı, kilitlerin kapsamı ve kaynak kullanımı ise DBMS'ye göre değişir. Bu nedenle tek bir SELECT kalıbını her veritabanına reçete gibi uygulama.
| Kategori | Teşhis sorusu | Neden DBMS'ye göre değişir? |
|---|---|---|
| Hata kodu ve mesajı | Hangi kural ihlal edildi, değer ve key adı nasıl raporlandı? | Hata kodları ve mesaj biçimleri farklıdır. |
| Şema metadata bilgisi | Key hangi sütunlardan oluşuyor, birleşik mi? | Information schema, sistem katalogları ve metadata görünümleri değişebilir. |
| Transaction ve isolation | SELECT hangi veri görünümünü gördü? |
İzolasyon seviyeleri, sürümleme ve okuma davranışları farklıdır. |
| Kilitlenme yaklaşımı | Çakışan yazma bekleyecek mi, engellenecek mi? | Satır, anahtar aralığı veya tablo kilitlerinin davranışı değişebilir. |
| Conflict-handling ve upsert | Çakışmada hata mı verilecek, kayıt atlanacak mı, güncellenecek mi? | Söz dizimi ve işlem sonucunun raporlanma biçimi aynı değildir. |
Örneğin PostgreSQL'de ON CONFLICT, MySQL'de ise ON DUPLICATE KEY UPDATE gibi farklı çakışma yönetimi söz dizimleri bulunur. Metadata bilgisine erişim ve benzersiz anahtarın sütunlarını inceleme yöntemi de kullanılan sisteme göre değişir.
Hata ayıklama sırasında bu ayrımı, yalnızca komutları ezberlemek yerine veri akışını ve işlem sırasını izleyerek kullanabilirsin. Benzer açıklamalar için SQL, algoritmik düşünme ve hata ayıklama üzerine diğer yazılar bölümüne göz atabilirsin.
SQL duplicate hatasını çözmek için uygulanabilir kontrol listesi
Her duplicate olayında aşağıdaki sırayı kısa bir teşhis listesi olarak kullan:
- İşlemin
INSERTmi,UPDATEmi olduğunu belirle. - Hata mesajındaki çakışan değeri ve key adını kaydet.
- Key'in sütunlarını ve birleşik olup olmadığını doğrula; yalnızca e-posta sütununa bakma.
- Aynı key değerini taşıyan mevcut satırı
SELECTile bul. - İş kuralına göre bunun yeni kayıt mı, mevcut kayıt mı olduğuna karar ver.
- Mevcut kayıtsa doğru satırı hedefleyen
UPDATE, yeniyse doğrulanmış yeni değerleINSERT, kaynak hatalıysa kaynak veriyi düzelt. - İşlemin sonucunu, etkilenen satırı ve hata durumunu kontrol et; sessizce atlanan bir kaydı başarı sayma.
- Eşzamanlı işlem ihtimalini değerlendir ve aynı benzersiz değerin iki istek tarafından aynı anda yazıldığı bir test senaryosu çalıştır.
Bu kontrol sırası SQL'e özel bir test vaadi değildir. Dilden bağımsız algoritmik düşünme ve programlama temellerini ayrıca değerlendirmek için ücretsiz bilgi testleri merkezini inceleyebilirsin.
Sık Sorulan Sorular
SQL "Duplicate entry for key" hatası neden oluşur?
Eklenmek veya güncellenmek istenen değer, UNIQUE kısıtlaması ya da PRIMARY KEY tarafından zaten kullanılan bir değerle çakışır. Birleşik anahtarlarda kontrol tek bir sütuna değil, sütunların birlikte oluşturduğu değere uygulanır.
Hata mesajındaki çakışan değer ve anahtar adı nasıl bulunur?
Mesajda bu bilgiler veriliyorsa, duplicate değer genellikle değer bölümünde, anahtar adı ise key veya constraint bölümünde yer alır. Biçim DBMS'ye göre değişebileceği için hata kodunu, tam mesajı ve şema metadata bilgilerini birlikte kaydetmek en güvenli yaklaşımdır.
Aynı e-posta bulunduğunda INSERT mi UPDATE mi kullanmalıyım?
Bu karar teknik değil, iş kuralıyla ilgilidir. E-posta mevcut kişiyi temsil ediyorsa doğru satırı hedefleyen UPDATE seçilebilir. Yeni bir kayıt olması gerekiyorsa kaynak veri düzeltilmeli veya geçerli yeni bir benzersiz değer kullanılmalıdır. Her iki davranış da kabul ediliyorsa, DBMS'nin upsert seçeneği güncellenecek sütunlar açıkça belirlenerek kullanılabilir.
INSERT IGNORE neden her durumda güvenli bir çözüm değildir?
MySQL'de INSERT IGNORE, bazı duplicate durumlarını hata yerine uyarı olarak ele alıp satırı atlayabilir. Ayrıca bazı veri hatalarının da işlemi durdurmak yerine uyarıyla sürdürülmesine yol açabilir. Bu nedenle kayıt gerçekten eklenmeden işlem başarılı görünmesin diye sonuç ve uyarılar ayrıca kontrol edilmelidir.
SELECT ile kontrol ettiğim hâlde duplicate hatası neden tekrar oluşabilir?
Kontrol ile yazma arasında başka bir işlem aynı benzersiz değeri eklemiş olabilir. Ayrıca kontrol yalnızca e-postaya bakıp birleşik anahtarın diğer sütunlarını dikkate almamış veya yanlış satırı hedeflemiş olabilir.
Duplicate hatasını kalıcı olarak çözmek için yalnızca çakışan satırı değil, benzersizlik kuralını, doğru işlem türünü ve eşzamanlı yazma ihtimalini birlikte değerlendirmek gerekir.