UPDATE Mevcut Satırları Değiştirir
INSERT yeni satır ekler. UPDATE ise zaten var olan satırları değiştirir. Yapısı kısa ve ezberlemeye değer:
UPDATE table_name
SET column = value
WHERE condition;
Çalışan bir örnek:
SET neyi değiştireceğini söyler, WHERE ise hangi satırları. Tablonun geri kalanına dokunulmaz.
Pratikte WHERE Olmadan UPDATE Yazmayın
Teknik olarak WHERE opsiyoneldir. Ama pratikte onu yazmayı unutmak, junior geliştiricilerin tüm öğleden sonrasını mahveden klasik hatadır:
UPDATE users SET status = 'inactive';
-- artık her kullanıcı pasif durumda
Filtre yoksa her satır eşleşir. SQLite de bunu sessiz sedasız yapar. Önce WHERE'i yazıp sonra SET'e geçmeyi alışkanlık edinin — bu küçük refleks bile pek çok kazanın önüne geçiyor.
WHERE koşulunuzdan emin değilseniz, aynı koşulu önce bir SELECT ile çalıştırın:
Aynı koşul, iki ayrı sorgu. SELECT burada deneme çekimi gibi düşün.
Birden Fazla Sütunu Aynı Anda Güncelleme
Tek bir SET içinde, atamaları virgülle ayırarak yazıyoruz. Tek SET, birden çok sütun:
Tek seferde veritabanına gidiş-dönüş, bir satır değişti, üç sütun güncellendi. Tek bir UPDATE ile halledebilecekken üç ayrı UPDATE yazmayın.
= İşaretinin Sağında İfadeler
= işaretinden sonraki değer illa sabit (literal) olmak zorunda değil. Burada herhangi bir ifade kullanabilirsiniz — sütunun mevcut değerine atıfta bulunan bir ifade bile olabilir:
price * 1.10 ifadesi mevcut fiyatı okur, çarpar ve sonucu geri yazar. SQLite, sağ taraftaki ifadeyi bu cümledeki atamalar uygulanmadan önceki satır değerleriyle değerlendirir; yani aynı anda birden fazla sütuna güvenle başvurabilirsiniz:
UPDATE products SET price = price * 1.10, stock = stock + price;
-- Buradaki sağ taraftaki 'price', az önce güncellenen değer değil ESKİ fiyattır.
UPDATE ... FROM: Başka Bir Tablodan Değer Çekme
SQLite 3.33 ile birlikte UPDATE artık FROM cümlesini destekliyor; yani tablolar arası güncelleme yapabiliyorsunuz. İki tablo arasında veri senkronize etmenin en temiz yolu bu:
Alt sorgu müşteri bazında toplamları hesaplıyor; dıştaki UPDATE ise bu sonuçları id üzerinden customers tablosuyla birleştiriyor. UPDATE ... FROM olmasaydı her sütun için ayrı bir korelasyonlu alt sorgu yazmak zorunda kalırdınız — çok daha gürültülü olurdu.
Aklınızda bulundurmanız gereken birkaç kural:
- Hedef tablo
UPDATEifadesinden sonra gelir,FROMlistesinde yer almaz. - Birleştirmeyi
WHEREifadesi yapar — buradaONanahtar kelimesi yoktur. FROMtarafında birden fazla satırla eşleşme ihtimali varsa sonuç belirsiz olur. Birleştirme anahtarlarınızın hedef satır başına en fazla bir eşleşme üretmesine dikkat edin.
RETURNING: Neyin Değiştiğini Görün
SQLite (3.35 ve sonrası), UPDATE ile değiştirilen satırları aynı ifade içinde döndürmenize olanak tanır. Uygulamanızın güncelleme sonrası değerlere ek bir SELECT çekmeden ulaşması gerektiğinde tam aradığınız şey:
Yapılan değişikliği gerçekten geçirilen satırlarla birlikte, güncellenmiş halleriyle geri alırsınız. Bu sayede ekstra bir sorgu atmaya gerek kalmaz ve eşzamanlı kodda sıkça karşılaşılan bir grup race condition sorunu da ortadan kalkar. RETURNING için bu bölümün ilerleyen sayfalarında ayrı bir başlık var.
UPDATE OR REPLACE: Kısıt Çakışmalarını Yönetmek
Yaptığınız güncelleme bir UNIQUE kısıtını ihlal ediyorsa, varsayılan davranış sorguyu hatayla iptal etmektir. OR ifadesi ise size farklı bir politika seçme imkânı sunar:
Seçenekler şunlar: OR ABORT (varsayılan), OR REPLACE, OR IGNORE, OR FAIL ve OR ROLLBACK. Bunlar arasında tehlikeli olanı REPLACE — çakışan satırı siler ve bu silme, foreign key zincirleri üzerinden domino etkisi yaratabilir. Yalnızca "bu eşsiz değere sahip bir satır zaten varsa, gözden çıkar" demek istediğinde kullan.
Upsert tarzı işlerin çoğunda, ayrı bir komut olan INSERT ... ON CONFLICT sözdizimi çok daha anlaşılır. Onun için ayrı bir sayfa var.
Riskli Güncellemeleri Transaction İçine Al
Çok sayıda satırı değiştirirken ya da birlikte başarılı olması gereken birden fazla UPDATE çalıştırırken, hepsini bir transaction içine sar. Bir şey ters giderse, her şeyi öncesine geri alabilirsiniz:
İkinci ifade başarısız olursa (mesela bir kısıt devreye girerse), ROLLBACK ilk işlemi de geri alır. Transaction olmadan, yarım kalmış bir transferle baş başa kalırdınız — Ada'nın hesabından 25 düşmüş, Boris'inkine ise hiçbir şey eklenmemiş olurdu. Transaction'ları ileride ayrı bir bölümde detaylıca işleyeceğiz; şimdilik var olduklarını ve toplu güncellemelerin neredeyse her zaman bir transaction içinde yapılması gerektiğini bilin yeter.
Sık Yapılan Hatalar
İnsanların sık tökezlediği birkaç nokta:
WHERE'i unutmak — bütün satırları günceller. İfadenizi çalıştırmadan önce sesli okuyun.WHEREiçinde yanlış operatör —WHERE status = NULLhiçbir satırla eşleşmez. Bunun yerineIS NULLkullanın. Operatörler sayfasında bunu detaylıca ele alacağız.- Tek satır beklerken birden fazla satır döndüren bir alt sorgu (subquery) ile güncelleme yapmak. Ya
LIMIT 1kullanın ya da alt sorguyu aggregate edin; aksi halde hata alır ya da beklemediğiniz sonuçlarla karşılaşırsınız. - UPDATE OR REPLACE ile UPSERT'ü karıştırmak.
OR REPLACEçakışan satırları siler.INSERT ... ON CONFLICT DO UPDATEise onları yerinde günceller. Bunlar tamamen farklı işlemlerdir.
Sırada: DELETE
UPDATE satırları değiştirir; DELETE ise siler. Aynı WHERE disiplini burada da geçerli — ve "önce bir SELECT çalıştır" alışkanlığı sizi yine aynı tür felaketlerden kurtaracak. Bir sonraki sayfanın konusu bu.
Sıkça Sorulan Sorular
SQLite'ta UPDATE komutunun temel söz dizimi nedir?
UPDATE tablo_adi SET sutun = deger WHERE kosul; şeklindedir. SET kısmında değiştirmek istediğiniz sütunları ve yeni değerlerini yazarsınız. WHERE ise hangi satırların etkileneceğini belirler — onu yazmazsanız tablodaki tüm satırlar güncellenir, dikkat.
Tek bir UPDATE ile birden fazla sütunu nasıl güncellerim?
SET ifadesinin içinde atamaları virgülle ayırmanız yeterli: UPDATE users SET name = 'Ada', email = 'ada@x.com' WHERE id = 1;. Tek sorgu, tek veritabanı çağrısı, tek satır günceller. Her sütun için ayrı SET yazmaya gerek yok.
SQLite'ta bir tabloyu başka bir tablodan güncelleyebilir miyim?
Evet — SQLite 3.33 ile gelen UPDATE ... FROM özelliği sayesinde başka bir tabloyu veya alt sorguyu join ederek güncelleme yapabilirsiniz. Yazım şu şekilde: UPDATE hedef SET col = kaynak.col FROM kaynak WHERE hedef.id = kaynak.id;. Tablolar arasında veri taşımanın en temiz yolu budur.