SQLite 3.53.0, 9 Nisan 2026'da yayımlandı ve geri çekilen 3.52.0 sürümünün yerini aldı. En önemli değişiklikler şunlardır: WAL kipinde nadir bir bozulmaya yol açan "WAL-reset" hatasının düzeltilmesi, ALTER TABLE ile NOT NULL ve CHECK kısıtı ekleyip kaldırabilme, ifade indekslerini yeniden kuran REINDEX EXPRESSIONS, yeni json_array_insert() fonksiyonu, komut satırında sonuçları biçimlendiren yeni QRF kütüphanesi ve ondalık sayıların metne çevrilmesinde varsayılanın 15 yerine 17 anlamlı basamak olması.

Ardından 3.53.1 (5 Mayıs 2026), 3.53.2 (3 Haziran 2026), 3.53.3 (26 Haziran 2026) ve 3.53.4 (24 Temmuz 2026) yama sürümleri çıktı. Sürüm notlarına göre bu yamalar kullanıcıların bildirdiği ve büyük ölçüde yapay zekâ araçlarıyla bulunan hataları düzeltir; yeni özellik eklemez. Bu yazıdaki örneklerin yeni özellik gerektirenleri, elimizdeki 3.50.6 ve 3.45.3 sürümlerinde çalışmadığı için yalnızca belgeye dayanılarak yazıldı ve açıkça işaretlendi. Eski sürümde aldığımız hatalar ise gerçekten çalıştırıldı.

3.52.0 neden geri çekildi?

3.52.0 neden geri çekildi?

SQLite haber sayfasına göre 3.52.0, 6 Mart 2026'da yayımlandı; ancak bazı yeni özellikleri önceki sürümlerle yüzde yüz uyumlu olmadığı için geri çekildi. Duyuruya göre sorun, metin veya JSONB girdisinden türetilen bir ondalık sayıyı hesaplayan ifade indeksleri ya da VIRTUAL hesaplanan sütun indeksleri bulunan veritabanlarında, nadir durumlarda eski sürümlerle birlikte çalışmanın bozulabilmesiydi. Onun yerine 13 Mart 2026'da 3.51.3 yama sürümü yayımlandı. 3.53.0 ise duyuruda 3.52.0'ın, bayat ifade indeksleri sorununa yönelik ek iyileştirmelerle yeniden yayımlanmış hâli olarak tanımlanır. Bu yüzden belgelerin bazı yerlerinde bir özelliğin "3.52.0 ile geldiği" yazar; pratikte o özelliği içeren ilk genel sürüm 3.53.0'dır.

WAL-reset bozulma hatası düzeltildi

3.53.0 sürüm notlarının ilk maddesi WAL-reset hatasının düzeltilmesidir. WAL belgesindeki açıklamaya göre hata 3 Mart 2026'da bir SQLite geliştiricisi tarafından bulunup düzeltildi ve büyük olasılıkla 3.7.0'dan (2010) 3.51.2'ye kadar tüm sürümlerde mevcut. Düzeltme 3.51.3 ve sonrasında var; bazı eski sürümler için 3.44.6 ve 3.50.7 geri taşıma yamaları yayımlandı. Hata yalnızca WAL kipindeki bir veritabanında, ayrı iş parçacıklarında veya süreçlerde açık iki bağlantının aynı anda yazmaya ya da checkpoint yapmaya çalıştığı çok dar bir zaman aralığında ortaya çıkar.

Belgedeki ayrıntılı senaryo şöyledir: bir checkpoint tamamlanır, hemen ardından ikinci bir checkpoint başlarken başka bir bağlantı WAL dosyasını sıfırlayıp başına yeni içerik yazar. Bir veri yarışı yüzünden ikinci checkpoint sıfırlamayı fark etmez ve WAL indeksinin başlığında bir alanı yanlış bırakır. Sonraki bir checkpoint bu yanlış bilgiye dayanarak işlemin bir kısmını ana dosyaya hiç aktarmaz ve dosya bozulur. Geliştiriciler hatayı laboratuvarda kendiliğinden üretemedi; özel test kodu eklemek zorunda kaldılar. Belgeye Ağustos 2026'da eklenen bir nota göre daha sonra bu test kodunu gerektirmeyen bir yeniden üretim yöntemi de bulundu. Belge, gözlenen sıklığın SSD arızalarından fazla olmadığını, acil durum olmadığını ama yükseltmenin önerildiğini belirtir.

ALTER TABLE ile NOT NULL ve CHECK ekleme, kaldırma

SQLite'ın ALTER TABLE desteği uzun süre tablo ve sütun yeniden adlandırma, sütun ekleme ve sütun silme ile sınırlıydı. Var olan bir sütuna NOT NULL eklemek veya bir CHECK kısıtını kaldırmak için tabloyu yeniden oluşturan 12 adımlı yöntemi uygulamak gerekiyordu. 3.53.0 ile bu iki tür kısıt doğrudan eklenip kaldırılabilir hâle geldi. Söz dizimi diyagramındaki biçimler şunlardır:

sql
-- SQLite 3.53.0 veya sonrası gerekir (çalıştırılmadı, söz dizimi belgeden)
ALTER TABLE urun ALTER COLUMN ad SET NOT NULL;
ALTER TABLE urun ALTER COLUMN ad DROP NOT NULL;
ALTER TABLE urun ADD CONSTRAINT fiyat_pozitif CHECK (fiyat > 0);
ALTER TABLE urun DROP CONSTRAINT fiyat_pozitif;

ALTER TABLE belgesi NOT NULL davranışı hakkında birkaç incelik verir. SET NOT NULL gereksiz ikinci bir kısıt eklemez: sütun zaten NOT NULL ise yeni kısıt eskisinin yerini alır, bu sayede farklı bir ON CONFLICT yan tümcesi atayabilirsiniz. Ancak CREATE TABLE ile aynı sütuna birden fazla NOT NULL yazılmışsa DROP NOT NULL bunlardan en az birini kaldırmayı garanti eder, hepsini değil. CHECK kısıtını adıyla kaldırabilmek için kısıtı eklerken CONSTRAINT ad biçiminde isimlendirmek iyi bir alışkanlıktır. Kesin dilbilgisi için canlı söz dizimi diyagramına bakmanızı öneririz; yerel belgelerde diyagramlar düz metne çevrilmiştir.

Eski bir sürümde bu komutları çalıştırdığınızda ne olacağını görmek için aynı ifadeleri 3.50.6 üzerinde denedik. Uygulamanız farklı SQLite sürümleriyle çalışabiliyorsa göç betiğinde önce sürümü kontrol etmeniz gerekir; aksi hâlde göç söz dizimi hatasıyla yarıda kalır.

sql
-- SQLite 3.50.6 üzerinde çalıştırıldı: yeni söz dizimi eski sürümde tanınmaz
CREATE TABLE urun(id INTEGER PRIMARY KEY, ad TEXT, fiyat REAL);
ALTER TABLE urun ALTER COLUMN ad SET NOT NULL;
-- hata: near "ALTER": syntax error
ALTER TABLE urun ADD CONSTRAINT fiyat_pozitif CHECK (fiyat > 0);
-- hata: near "CONSTRAINT": syntax error
REINDEX EXPRESSIONS;
-- hata: unable to identify the object to be reindexed
SELECT json_array_insert('[1,2,3]', '$[1]', 'new');
-- hata: no such function: json_array_insert

REINDEX EXPRESSIONS ve kendi kendini onaran ifade indeksleri

İfade indeksi, bir ifadenin sonucunu veya VIRTUAL hesaplanan bir sütunu indeksler. Bunun doğru çalışması için ifadenin aynı girdiye her zaman aynı çıktıyı vermesi gerekir. Belge, "deterministik" kabul edilen fonksiyonların bile farklı işlemci mimarilerinde, işletim sistemlerinde veya SQLite sürümlerinde çok küçük farklar üretebileceğini anlatır. Örnekler arasında sistemin matematik kütüphanesini çağıran trigonometrik fonksiyonlar, güncellenen bir ICU kütüphanesi, metinden ondalık sayıya dönüşüm rutinlerindeki iyileştirmeler ve kullanımdan kaldırılmış case_sensitive_like pragması sayılır. İndekste saklanan değer ile yeniden hesaplanan değer farklılaştığında indekse "bayat" denir.

Belgeye göre bu durum nadirdir ve gözlenen tek örnek, bir ondalık sayının son basamağında bir birimlik farktır. Eski sürümlerde böyle bir satırı silmek veya güncellemek hata verir ve PRAGMA integrity_check sorunu raporlar. 3.53.0 ile SQLite bu satırlar silinirken veya güncellenirken indeksi kendiliğinden düzeltir; uygulama hiçbir hata görmez. integrity_check yine uyarır, ama fark bir iki birimlikse mesaj indeksin bozuk olduğunu değil, satır için "kesin olmayan bir ondalık değer" sakladığını söyler.

Bayat indeks şüphesi olduğunda bütün indeksleri yeniden kurmak yerine yalnızca ifade indekslerini yeniden kurabilirsiniz. Veritabanında hiç ifade indeksi yoksa komut hiçbir şey yapmaz. 3.53.0 komut satırındaki .indexes --expr ise hangi indekslerin ifade indeksi olduğunu listeler.

sql
-- SQLite 3.53.0 veya sonrası (komut satırı) gerekir
.indexes --expr
REINDEX EXPRESSIONS;

Bu riski tamamen ortadan kaldırmak isteyenler için belgenin önerisi, ifade indeksi yerine STORED hesaplanan bir sütun tanımlayıp indeksi o sütun üzerine kurmaktır. STORED sütunun değeri satır yazılırken hesaplanıp saklandığı için sonraki okumalarda yeniden hesaplanmaz. Bu yöntem eski sürümlerde de çalışır; aşağıdaki örneği 3.50.6 üzerinde çalıştırdık:

sql
-- İfade indeksi yerine STORED hesaplanan sütun ve onun üzerinde indeks
CREATE TABLE doc(
  doc JSON,
  mtime AS (doc->>'mtime') STORED
);
CREATE INDEX doc_mtime ON doc(mtime);
INSERT INTO doc(doc) VALUES ('{"ad":"rapor","mtime":1767225600.5}'),
                            ('{"ad":"not","mtime":1767312000.25}');
SELECT doc->>'ad', mtime FROM doc WHERE mtime > 1767300000;
-- çıktı: not|1767312000.25
EXPLAIN QUERY PLAN SELECT doc->>'ad' FROM doc WHERE mtime > 1767300000;
-- çıktı:
-- QUERY PLAN
-- `--SEARCH doc USING INDEX doc_mtime (mtime>?)

Hesaplanan sütunların ayrıntısı SQLite generated columns, ifade indekslerinin kullanımı partial index ve ifade indeksi yazısında anlatılıyor.

json_array_insert() ve jsonb_array_insert()

Yeni fonksiyonlar json_replace() gibi çalışır, ancak iki farkla: her yol argümanı bir dizi elemanını göstermek zorundadır (yol köşeli parantezle bitmezse hata verilir) ve var olan eleman üzerine yazılmaz; dizi büyütülür ve yeni değer belirtilen konuma eklenir. Yol ve değer çiftleri birden çok kez verilebilir. jsonb_array_insert() sonucu ikili JSONB biçiminde döndürür. Aşağıdaki çıktılar belgedeki örneklerdir:

sql
-- SQLite 3.53.0 veya sonrası gerekir; çıktılar belgedeki örneklerden
SELECT json_array_insert('[1,2,3]', '$[1]', 'new');
-- çıktı: [1,"new",2,3]
SELECT json_array_insert('{"a":[1,2,3]}', '$.a[0]', 'new');
-- çıktı: {"a":["new",1,2,3]}

Dizinin sonuna eleman eklemek için yeni fonksiyona gerek yoktur; json_insert() ile $[#] yolu eski sürümlerde de bunu yapar. Yeni fonksiyonun asıl kazancı dizinin başına veya ortasına ekleme yapabilmesidir. JSON fonksiyonlarının tamamı için SQLite JSON fonksiyonları yazısına bakın.

sql
-- Eski sürümlerde de çalışır: dizinin sonuna eklemek için json_insert ve $[#]
SELECT json_insert('[1,2,3,4]', '$[#]', 99);
-- çıktı: [1,2,3,4,99]
SELECT json_insert('[1,[2,3],4]', '$[1][#]', 99);
-- çıktı: [1,[2,3,99],4]

Komut satırında QRF ve diğer değişiklikler

Komut satırında QRF ve diğer değişiklikler: Etkileşimli oturumların varsayılan çıktı biçimi artık Unicode kutu çizgileriyle..., Tablo biçimli çıktılarda sayılar varsayılan olarak...

3.53.0 ile sorgu sonuçlarını sabit genişlikli yazı tipinde okunaklı biçimlendiren Query Result Formatter (QRF) kütüphanesi eklendi ve komut satırı aracı sonuçları bu kütüphaneyle göstermeye başladı. Sürüm notlarındaki başlıca etkiler şunlardır:

  • Etkileşimli oturumların varsayılan çıktı biçimi artık Unicode kutu çizgileriyle çizilen bir tablodur. Betik (batch) oturumları uyumluluk için eski list biçimini kullanmaya devam eder.
  • Tablo biçimli çıktılarda sayılar varsayılan olarak sağa hizalanır.
  • .mode komutu çok sayıda yeni seçenek kazandı; eski .width gibi komutların yerini bu seçenekler alıyor.
  • Nokta komutlarının sonundaki tırnaksız noktalı virgül artık sessizce yok sayılır. Sürüm notu bunu olası bir uyumsuzluk olarak işaretler.
  • Komut satırında verilen ve .sql veya .txt ile biten, boş olmayan dosya adları betik olarak okunup çalıştırılır.
  • .timer once yalnızca bir sonraki ifadenin süresini ölçer; .progress komutunun yeni --timeout S seçeneği ifadeleri S saniye sonra keser.
  • .indexes komutundaki desen artık tablo adıyla değil indeks adıyla eşleşir ve yeni seçenekler aldı. Komut satırı belgesinin bir bölümü hâlâ eski tablo adı davranışını anlatıyor; kendi sürümünüzde .help indexes ile kontrol edin.
  • .testcase ve .check komutları düzeltildi.
sql
-- SQLite 3.53.0 veya sonrası komut satırı (çalıştırılmadı)
.timer once
SELECT count(*) FROM buyuk_tablo;

Bu değişikliklerin pratik sonucu şudur: etkileşimli oturumda gördüğünüz çıktı ile aynı komutları betikte çalıştırdığınızda aldığınız çıktı artık belirgin biçimde farklıdır. Çıktıyı başka bir programın okuduğu betiklerde biçimi .mode ile açıkça seçin. Biçimlerin tamamı SQLite .mode çıktı biçimleri, nokta komutları SQLite CLI nokta komutları yazısında anlatılıyor.

Ondalık sayılar artık 17 anlamlı basamakla yazılıyor

Bir ondalık sayının metne çevrilmesi, örneğin sorgu sonucunu ekrana yazarken veya CAST(x AS TEXT) yaparken, belirli bir basamak sayısına yuvarlama içerir. 3.51.2 ve öncesinde bu her zaman 15 anlamlı basamaktı. Ondalık sayı belgesine göre yeni algoritma önce 15 basamağa yuvarlar, sonucu tekrar ikili sayıya çevirir ve aynı değere dönmüyorsa 17 basamakla yeniden yuvarlar. Böylece çoğu sayı eskisi gibi görünür, ama metinden geri okunduğunda aynı ikili değeri vermeyen sayılar artık daha uzun yazılır.

Belgedeki örnek 1,23 ile 2,34'ün çarpımıdır. 15 basamakla yuvarlandığında sonuç 2.8782 görünür, ancak bu metin ikili sayıya geri çevrildiğinde orijinal çarpımla aynı değeri vermez. 17 basamakla yuvarlama 2.8781999999999997 üretir ve tam olarak geri dönüşür. Bizim 3.50.6 kurulumumuzda sonuç şu şekilde görünüyor; 3.53 ve sonrasında belgeye göre aynı ifade 17 basamaklı biçimde yazılacaktır:

sql
-- SQLite 3.50.6 üzerinde (15 anlamlı basamak)
SELECT 1.23 * 2.34;
-- çıktı: 2.8782
SELECT round(1.23 * 2.34, 4), printf('%.4f', 1.23 * 2.34);
-- çıktı: 2.8782|2.8782

Ekranda ve raporlarda tutarlı görünüm istiyorsanız değeri round() veya printf() ile kendiniz biçimlendirin; yukarıdaki ikinci satır her iki sürümde de aynı sonucu verir. Eski davranışa dönmek için C arayüzünde SQLITE_DBCONFIG_FP_DIGITS seçeneği, komut satırında ise aşağıdaki komut vardır. Ondalık sayıların genel davranışı SQLite matematik fonksiyonları yazısında.

sql
-- SQLite 3.53.0 veya sonrası komut satırında eski 15 basamak davranışına dönmek
.dbconfig fp_digits 15

Diğer değişiklikler

Diğer değişiklikler: TEMP tetikleyiciler, VACUUM INTO, Sorgu planlayıcı, C arayüzü
  • TEMP tetikleyiciler: Geçici tetikleyicilerin gövdesi artık main şemasındaki tabloları sorgulayabilir ve değiştirebilir.
  • VACUUM INTO: Hedef bir URI dosya adıysa ve reserve=N parametresi (0 ile 255 arası) içeriyorsa, üretilen kopyanın ayrılmış bayt miktarı N olur. Yedekleme kullanımı için yedekleme yazısına bakın.
  • Sorgu planlayıcı: EXCEPT, INTERSECT ve UNION için her zaman sırala-birleştir algoritması kullanılıyor; yıldız şemalarındaki çok yollu birleştirmelerde birleştirme sırası seçimi iyileştirildi; EXISTS ifadelerini birleştirmeye çeviren ve etkisiz birleştirmeleri atlayan optimizasyonlar genişletildi; yalnızca ASC/DESC yönü farklı olan GROUP BY ve ORDER BY tek bir indeksle karşılanabiliyor.
  • C arayüzü: sqlite3_str_truncate(), sqlite3_str_free(), sqlite3_carray_bind_v2(), SQLITE_PREPARE_FROM_DDL, SQLITE_UTF8_ZT, SQLITE_LIMIT_PARSER_DEPTH ve SQLITE_DBCONFIG_FP_DIGITS eklendi; oturum (session) uzantısına değişiklikleri tek tek eklemeyi sağlayan arayüzler geldi.
  • sqlite3_rsync: Ağ üzerinden kopyalama aracına -p ve --port seçeneği eklendi.
  • Platformlar: Windows RT desteği sona erdi; WebAssembly tarafına Web Locks kullanan opfs-wl VFS eklendi.

Yükseltmeden önce kontrol listesi

  • Komut satırı çıktısını ayrıştıran betikleriniz varsa biçimi .mode ile sabitleyin ve nokta komutlarının sonundaki noktalı virgüllere güvenmeyin.
  • Ondalık sayıların metin biçimini karşılaştıran testleriniz varsa 17 basamak değişikliğine göre güncelleyin veya değerleri round() ile biçimlendirin.
  • Uygulamanız eski ve yeni SQLite sürümleriyle aynı dosyayı paylaşıyorsa yeni ALTER TABLE biçimlerini kullanmadan önce tüm taraflardaki sürümü kontrol edin.
  • İfade indeksi kullanıyorsanız yükseltmeden sonra PRAGMA integrity_check çalıştırın; bayat indeks uyarısı alırsanız REINDEX EXPRESSIONS kullanın.
  • WAL kipinde birden çok süreçle yazıyorsanız WAL-reset düzeltmesi için yükseltmeyi öncelikli yapın. Bir sonraki sürümün değişiklikleri SQLite 3.54 yenilikleri yazısında.

Sık Sorulan Sorular

3.53.4 ile 3.53.0 arasında yeni özellik var mı?

Sürüm notlarına göre hayır. 3.53.1, 3.53.2, 3.53.3 ve 3.53.4 yalnızca hata düzeltmeleri içerir. 3.53 serisini kullanacaksanız en son yamayı tercih edin.

Sürümümün WAL-reset hatasından etkilenip etkilenmediğini nasıl anlarım?

SELECT sqlite_version() sonucuna bakın. Belgeye göre 3.7.0 ile 3.51.2 arasındaki sürümler etkilenir; 3.51.3 ve sonrası, ayrıca geri taşıma yaması olan 3.44.6 ve 3.50.7 düzeltmeyi içerir.

Ondalık sayılarım değişti mi?

Saklanan ikili değer değişmedi; değişen yalnızca metne çevrilirken kullanılan basamak sayısıdır. Görüntü bazı sayılarda daha uzun olabilir, ama 17 basamaklı metin orijinal değere tam olarak geri döner.

ALTER TABLE ile her kısıtı ekleyebilir miyim?

Hayır. 3.53.0 ile gelen destek NOT NULL ve CHECK kısıtlarıyla sınırlıdır. Birincil anahtar, UNIQUE veya yabancı anahtar gibi diğer değişiklikler için ALTER TABLE belgesindeki tabloyu yeniden oluşturma yöntemi hâlâ geçerlidir.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: SQLite öğrenme rehberi · SQLite 3.54 yenilikleri · SQLite ALTER TABLE · SQLite .mode çıktı biçimleri · SQLite ifade indeksi · SQLite matematik fonksiyonları