Soru-Cevap Tarzı
Sorunu araştırıp saatlerce tartıştıktan sonra, masanızın yapısına ve bütünlüğü korumak için yabancı anahtar kısıtlamalarının etkinleştirilip etkinleştirilmediğine bağlı olarak bunu başarmanın iki yolu olduğunu öğrendim. Durumumda olabilecek insanlara biraz zaman kazandırmak için bunu temiz bir formatta paylaşmak istiyorum.
1. Seçenek: Satırı silmeyi göze alabilirsiniz
Başka bir deyişle, yabancı anahtarınız yoktur veya varsa, SQLite motorunuz, bütünlük istisnaları olmayacak şekilde yapılandırılmıştır. Gitmenin yolu EKLE VEYA DEĞİŞTİR . Kimliği zaten mevcut olan bir oynatıcıyı eklemeye / güncellemeye çalışıyorsanız, SQLite motoru bu satırı silecek ve sağladığınız verileri ekleyecektir. Şimdi soru geliyor: eski kimliği ilişkilendirmek için ne yapmalı?
User_name = 'steven' ve age = 32 verileriyle UPSERT yapmak istediğimizi varsayalım .
Şu koda bakın:
INSERT INTO players (id, name, age)
VALUES (
coalesce((select id from players where user_name='steven'),
(select max(id) from drawings) + 1),
32)
Hile birleşiyor. Varsa, kullanıcının 'steven' kimliğini döndürür, aksi takdirde yeni bir yeni kimlik döndürür.
2. Seçenek: Satırı silmeyi göze alamazsınız
Önceki çözümle uğraştıktan sonra, benim durumumda, bu kimlik diğer tablo için yabancı anahtar olarak çalıştığından, bunun veriyi yok etmeye neden olabileceğini fark ettim. Ayrıca tabloyu ON DELETE CASCADE cümlesiyle oluşturdum, yani verileri sessizce silecekti. Tehlikeli.
Yani, ilk önce bir IF fıkra düşündü, ama SQLite yalnızca sahiptir ÖRNEĞİ . Ve bu CASE , EXISTS ise (user_name = 'steven' olan oyunculardan id'yi seçin), eğer yoksa INSERT ise bir UPDATE sorgusu gerçekleştirmek için kullanılamaz (veya en azından ben yönetmedim) . Gitme.
Ve sonunda, kaba kuvveti başarıyla kullandım. Mantık, gerçekleştirmek istediğiniz her UPSERT için, öncelikle kullanıcımızla bir satır olduğundan emin olmak için bir INSERT OR IGNORE çalıştırın ve ardından eklemeye çalıştığınız verilerle tam olarak aynı verilerle bir UPDATE sorgusu çalıştırın .
Öncekiyle aynı veriler: user_name = 'steven' ve age = 32.
-- make sure it exists
INSERT OR IGNORE INTO players (user_name, age) VALUES ('steven', 32);
-- make sure it has the right data
UPDATE players SET user_name='steven', age=32 WHERE user_name='steven';
Ve hepsi bu!
DÜZENLE
Andy'nin yorumladığı gibi, önce eklemeye ve ardından güncellemeye çalışmak, beklenenden daha sık tetikleyici tetiklemelere neden olabilir. Bu bence bir veri güvenliği sorunu değil, ancak gereksiz olayları ateşlemenin pek mantıklı olmadığı doğrudur. Bu nedenle, iyileştirilmiş bir çözüm şöyle olacaktır:
-- Try to update any existing row
UPDATE players SET age=32 WHERE user_name='steven';
-- Make sure it exists
INSERT OR IGNORE INTO players (user_name, age) VALUES ('steven', 32);