- Konu sahibi
- #1
İki kaydın aynı kabul edilmesine neden olan sütun veya sütunlar için UNIQUE kısıtı tanımlayın. Uygulama tarafındaki “önce kontrol et, sonra ekle” yaklaşımı tek başına yeterli değildir; eş zamanlı iki işlem aynı anda kontrol yapıp aynı kaydı ekleyebilir. Veritabanı benzersizlik kuralını uygular, ikinci ekleme reddedilir. Kayıt zaten varsa hata almak yerine güncellemek veya hiçbir işlem yapmamak istiyorsanız buna uygun
Önce “aynı kayıt” tanımını netleştirin. Örneğin kullanıcıların e-posta adresi tekil olmalıysa yalnızca
Örneğin aşağıdaki tablo, aynı e-posta adresinin ikinci kez eklenmesini engeller:
Tablo zaten oluşturulmuşsa kısıtı sonradan da ekleyebilirsiniz:
Bu işlem sırasında tabloda aynı e-posta adresinden birden fazla varsa veritabanı kısıtı ekleyemez. Önce hangi değerlerin tekrar ettiğini bulun:
Sonuç dönerse bu, mevcut veride tekrarlar bulunduğunu gösterir; benzersizlik kuralının çalışmadığını göstermez. Tekrarlanan kayıtları hangi kaydın korunacağına göre temizledikten sonra
Kısıt eklendikten sonra normal
Aynı
Kullanılan veritabanına göre tekrar kayıtla karşılaşınca uygulanacak davranış değişir:
Seçim, iş kuralına göre yapılmalıdır. Örneğin sipariş numarası ikinci kez oluşturulmamalıysa tekrar geldiğinde işlemi reddetmek daha doğru olabilir. Dış sistemden gelen güncel ürün bilgilerini içeri aktarıyorsanız aynı ürün anahtarı bulunduğunda mevcut satırı güncellemek isteyebilirsiniz.
Aynı ürünün aynı mağazada yalnızca bir kez bulunması gerekiyorsa sütunları ayrı ayrı değil, birlikte benzersiz yapın:
Bu kural aynı mağazada aynı ürünün ikinci kez eklenmesini engeller; fakat aynı ürünün farklı mağazalarda bulunmasına izin verir.
Şu yaklaşım basit durumlarda çalışıyor gibi görünse de güvenilir bir benzersizlik koruması değildir:
İki istek aynı anda çalışırsa her ikisi de
Kısıtı ekledikten sonra aynı benzersiz değeri iki kez gönderen bir test yapın. İlk
Kısıt eklenemiyorsa önce tekrar eden değerleri,
INSERT ... ON CONFLICT, ON DUPLICATE KEY UPDATE ya da MERGE çözümünü kullanın.Benzersizlik hangi alanlarda uygulanmalı?
Önce “aynı kayıt” tanımını netleştirin. Örneğin kullanıcıların e-posta adresi tekil olmalıysa yalnızca
email sütununu; aynı ürünün aynı mağazadaki kaydı tekil olmalıysa product_id ve store_id sütunlarını birlikte benzersiz yapmalısınız.Örneğin aşağıdaki tablo, aynı e-posta adresinin ikinci kez eklenmesini engeller:
SQL:
CREATE TABLE users (
id INTEGER PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(100) NOT NULL
);
Tablo zaten oluşturulmuşsa kısıtı sonradan da ekleyebilirsiniz:
SQL:
ALTER TABLE users
ADD CONSTRAINT uq_users_email UNIQUE (email);
Bu işlem sırasında tabloda aynı e-posta adresinden birden fazla varsa veritabanı kısıtı ekleyemez. Önce hangi değerlerin tekrar ettiğini bulun:
SQL:
SELECT email, COUNT(*) AS tekrar_sayisi
FROM users
GROUP BY email
HAVING COUNT(*) > 1;
Sonuç dönerse bu, mevcut veride tekrarlar bulunduğunu gösterir; benzersizlik kuralının çalışmadığını göstermez. Tekrarlanan kayıtları hangi kaydın korunacağına göre temizledikten sonra
UNIQUE kısıtını ekleyin. Silme işlemini doğrudan üretim veritabanında çalıştırmadan önce aynı seçimi SELECT ile kontrol edin ve yedekleme politikanıza uygun hareket edin.Ekleme sırasında veritabanı nasıl korunur?
Kısıt eklendikten sonra normal
INSERT sorgusu, aynı değer ikinci kez gönderildiğinde benzersizlik ihlali hatası üretir:
SQL:
INSERT INTO users (email, name)
VALUES ('[email protected]', 'Ali');
Aynı
email zaten varsa ikinci sorgu başarısız olur. Bu sonuç, kaydın tekrar eklenmediğini kanıtlar; ancak uygulamanın kullanıcıya anlaşılır bir yanıt verdiğini veya işlemin başka bir tabloya da başarıyla yazıldığını kanıtlamaz. Uygulama bu veritabanı hatasını yakalayıp “bu e-posta zaten kayıtlı” gibi uygun bir sonuç döndürmelidir.Kullanılan veritabanına göre tekrar kayıtla karşılaşınca uygulanacak davranış değişir:
| İhtiyaç | Uygun yaklaşım |
|---|---|
| Tekrarı reddetmek | UNIQUE veya PRIMARY KEY; normal INSERT ve hata yönetimi |
| Tekrar varsa hiçbir şey yapmamak | PostgreSQL’de ON CONFLICT DO NOTHING, MySQL’de INSERT IGNORE gibi sağlayıcıya özgü sözdizimi |
| Tekrar varsa mevcut kaydı güncellemek | Upsert yaklaşımı; kullanılan veritabanının ON CONFLICT, ON DUPLICATE KEY UPDATE veya MERGE sözdizimi |
| Birden fazla sütunun birleşimi tekil olmalı | Birleşik UNIQUE kısıtı |
Birden fazla sütunla benzersiz kayıt
Aynı ürünün aynı mağazada yalnızca bir kez bulunması gerekiyorsa sütunları ayrı ayrı değil, birlikte benzersiz yapın:
SQL:
CREATE TABLE store_products (
store_id INTEGER NOT NULL,
product_id INTEGER NOT NULL,
price DECIMAL(10, 2) NOT NULL,
UNIQUE (store_id, product_id)
);
Bu kural aynı mağazada aynı ürünün ikinci kez eklenmesini engeller; fakat aynı ürünün farklı mağazalarda bulunmasına izin verir.
store_id ve product_id sütunlarını ayrı ayrı UNIQUE yapmak ise genellikle istenmeyen şekilde her mağazayı ve her ürünü tüm tabloda tek bir kayıtla sınırlar.Sadece SELECT ile kontrol etmek neden yeterli değildir?
Şu yaklaşım basit durumlarda çalışıyor gibi görünse de güvenilir bir benzersizlik koruması değildir:
SQL:
SELECT id FROM users WHERE email = '[email protected]';
-- Sonuç yoksa:
INSERT INTO users (email, name)
VALUES ('[email protected]', 'Ali');
İki istek aynı anda çalışırsa her ikisi de
SELECT sonucunu boş görebilir ve ardından ekleme yapabilir. Bu nedenle kontrol sorgusu kullanıcı deneyimini iyileştirmek için kullanılabilir, fakat asıl güvence mutlaka veritabanındaki UNIQUE veya PRIMARY KEY kısıtı olmalıdır. Gerekli durumlarda ekleme ve güncelleme işlemini transaction içinde yürütün; yine de benzersizlik kısıtını kaldırmayın.Sonucu nasıl doğrulamalısınız?
Kısıtı ekledikten sonra aynı benzersiz değeri iki kez gönderen bir test yapın. İlk
INSERT başarılı olmalı; ikinci işlem seçtiğiniz yönteme göre hata vermeli, hiçbir satır eklememeli veya mevcut satırı güncellemelidir. Ardından sayıyı kontrol edin:
SQL:
SELECT email, COUNT(*) AS kayit_sayisi
FROM users
WHERE email = '[email protected]'
GROUP BY email;
kayit_sayisi değerinin 1 olması bu değer için tabloda tek satır bulunduğunu gösterir. Ancak yalnızca bu sorgunun sonucuna bakmak, gelecekteki eş zamanlı eklemeleri güvence altına almaz; bunu sağlayan kural, tabloda tanımlı benzersizlik kısıtıdır.Kısıt eklenemiyorsa önce tekrar eden değerleri,
NULL davranışını ve metin değerlerindeki boşluk veya büyük-küçük harf farklarını inceleyin. Örneğin [email protected] ile [email protected] bazı veritabanı ve veri türlerinde farklı değer kabul edilebilir. İş kuralı büyük-küçük harf farkını yok sayıyorsa normal UNIQUE kısıtı yerine veritabanınızın desteklediği uygun normalleştirme, ifade tabanlı benzersiz indeks veya karşılaştırma ayarını kullanmanız gerekir.