PRAGMA, SQLite'a özgü bir SQL komutudur: kütüphanenin çalışma biçimini değiştirmek (yabancı anahtar denetimi, günlük kipi, önbellek boyutu gibi) veya tablolarda tutulmayan iç bilgileri (sütun listesi, dosya boyutu, bütünlük durumu) sorgulamak için kullanılır. Değer okumak için PRAGMA ad;, değiştirmek için PRAGMA ad = deger; yazılır. Diğer veritabanlarıyla uyumlu değildir ve bilinmeyen bir pragma adı hata vermeden yok sayılır.

Bu yazıda sözdizimini, pragmaların SELECT içinde tablo gibi kullanılabilen fonksiyon biçimini, hangi ayarların dosyada kalıcı hangilerinin yalnızca bağlantıya özel olduğunu ve en sık kullanılan pragmaları gruplar hâlinde ele alıyoruz. Belirli pragmaların derin anlatımı ilgili yazılarda: journal_mode ve checkpoint, synchronous, cache_size ve mmap_size, foreign_keys, user_version ile şema göçü ve auto_vacuum.

PRAGMA'yı diğer SQL komutlarından ayıran özellikler

PRAGMA'yı diğer SQL komutlarından ayıran özellikler

PRAGMA, SELECT veya INSERT ile aynı arayüzden gönderilir ama belgeler birkaç önemli farkın altını çizer. Birincisi, SQLite'a özgüdür ve başka bir veritabanı motorunda çalışmaz. İkincisi, gelecekteki sürümlerde bazı pragmalar kaldırılabilir veya yenileri eklenebilir; geriye uyumluluk garantisi yoktur. Üçüncüsü ve pratikte en tehlikelisi, bilinmeyen bir pragma için hata üretilmez; yazım hatası yaparsanız SQLite sizi uyarmaz. Dördüncüsü, bazı pragmalar işini ifade derlenirken (prepare) yapar, bazıları çalıştırılırken (step); hangisinin ne zaman çalıştığı pragmaya ve sürüme göre değişir. Bu yüzden pragmaların önüne EXPLAIN koymak tutarlı sonuç vermez.

Sözdizimi: eşittir, parantez ve boolean değerler

Bir pragma ya hiç argüman almaz ya da tek bir argüman alır. Argüman parantez içinde veya eşittir işaretinden sonra yazılabilir; iki biçim aynı sonucu verir. Boolean argümanlarda 1, yes, true, on açık; 0, no, false, off kapalı anlamına gelir ve anahtar kelimeler tırnak içinde de yazılabilir. Bir ayar sorgulandığında çoğu pragma anahtar kelimeyi değil sayısal karşılığını döndürür.

sql
PRAGMA foreign_keys;            -- sorgulama
-- çıktı: 0
PRAGMA foreign_keys = ON;       -- eşittir biçimi
PRAGMA foreign_keys;
-- çıktı: 1
PRAGMA foreign_keys = 'no';     -- tırnaklı anahtar kelime
PRAGMA foreign_keys;
-- çıktı: 0
PRAGMA foreign_keys(1);         -- parantez biçimi
PRAGMA foreign_keys;
-- çıktı: 1

PRAGMA foreign_kyes = ON;       -- yazım hatası: hiçbir uyarı yok, hiçbir şey olmaz

Son satırdaki yazım hatası en sık karşılaşılan tuzaktır: foreign_kyes diye bir pragma olmadığı için komut sessizce hiçbir şey yapmaz ve yabancı anahtar denetiminin açık olduğunu sanarak devam edersiniz. Önemli bir ayarı değiştirdikten sonra aynı pragmayı argümansız çalıştırıp değeri okumak bu hatayı yakalamanın en kolay yoludur. Hangi pragmaların tanındığını PRAGMA pragma_list; ile görebilirsiniz; liste derleme seçeneklerine göre değişir.

Şema adı öneki

Bir pragmanın önüne isteğe bağlı olarak şema adı yazılabilir: main, temp veya ATTACH ile bağlanmış bir veritabanının adı. Şema adı yazılmazsa main kastedilir. Bazı pragmalarda şema adının anlamı yoktur ve yok sayılır; belgelerde şema adının anlamlı olduğu pragmalar schema. önekiyle gösterilir. Bazı ayarlarda ise şema adı verilmezse ayar bütün bağlı veritabanlarına uygulanır; örneğin journal_mode ve mmap_size böyledir. Birden çok dosyayla çalışmak ATTACH DATABASE yazısında anlatılıyor.

sql
ATTACH ':memory:' AS arsiv;
PRAGMA database_list;
-- çıktı:
-- 0|main|
-- 2|arsiv|

PRAGMA arsiv.user_version = 3;
PRAGMA arsiv.user_version;
-- çıktı: 3
PRAGMA user_version;            -- şema adı yoksa main kastedilir
-- çıktı: 0

Pragma fonksiyonları: SELECT içinde pragma

Sonuç döndüren ve yan etkisi olmayan pragmalar, adlarının başına pragma_ eklenmiş tablo değerli fonksiyonlar olarak da kullanılabilir. Pragma argümanı fonksiyonun argümanı olur. Bu biçimin avantajı, sonucun bir tablo gibi işlenebilmesidir: yalnızca istediğiniz sütunları seçebilir, WHERE ile süzebilir, birleştirme yapabilir ve toplama fonksiyonları kullanabilirsiniz. Bu özellik 3.16.0 sürümünde eklendi.

sql
CREATE TABLE urun(id INTEGER PRIMARY KEY, ad TEXT NOT NULL, fiyat REAL DEFAULT 0, stok INTEGER);
CREATE INDEX urun_ad ON urun(ad);

PRAGMA table_info(urun);
-- çıktı:
-- 0|id|INTEGER|0||1
-- 1|ad|TEXT|1||0
-- 2|fiyat|REAL|0|0|0
-- 3|stok|INTEGER|0||0

SELECT name, type FROM pragma_table_info('urun') WHERE "notnull" = 0 AND pk = 0;
-- çıktı:
-- fiyat|REAL
-- stok|INTEGER

SELECT m.name AS tablo, ii.name AS sutun
  FROM sqlite_schema AS m,
       pragma_index_list(m.name) AS il,
       pragma_index_info(il.name) AS ii
 WHERE m.type = 'table';
-- çıktı: urun|ad

Son sorgu, belgelerdeki örneğe dayanarak şemadaki bütün tabloların indekslenmiş sütunlarını tek seferde listeler: sqlite_schema tablolardan, pragma_index_list her tablonun indekslerinden, pragma_index_info her indeksin sütunlarından gelir. notnull bir SQL anahtar kelimesi olduğu için sütun adı olarak çift tırnakla yazıldığına dikkat edin. Fonksiyon biçimi yalnızca yerleşik pragmalar için vardır; değer atayan veya başka bir yan etkisi olan pragmalar bu biçimde kullanılamaz. Şema sorgulamanın diğer yolları tabloları listeleme yazısında.

Kalıcı ayarlar ve bağlantıya özel ayarlar

Kalıcı ayarlar ve bağlantıya özel ayarlar: user_version, application_id, journal_mode = WAL, page_size, auto_vacuum

Pragma ayarlarının bir kısmı veritabanı dosyasının içine yazılır ve dosyayı kim açarsa açsın geçerli olur. Büyük kısmı ise yalnızca o bağlantı için geçerlidir ve bağlantı kapanınca kaybolur. Bu ayrımı bilmemek, "ayarı yaptım ama uygulamada çalışmıyor" sorununun en yaygın nedenidir:

sql
-- sqlite3 ayar.db : ilk oturum
PRAGMA user_version = 7;        -- dosya başlığına yazılır
PRAGMA cache_size = -64000;
PRAGMA foreign_keys = ON;
PRAGMA busy_timeout = 5000;
-- çıktı: 5000

-- sqlite3 ayar.db : ikinci oturum
PRAGMA user_version;
-- çıktı: 7
PRAGMA cache_size;
-- çıktı: -2000
PRAGMA foreign_keys;
-- çıktı: 0
PRAGMA busy_timeout;
-- çıktı: 0

user_version, veritabanı başlığının 60. baytındaki bir tamsayıdır ve SQLite bu değeri kendisi hiç kullanmaz; uygulamanın şema sürümünü tutmak için idealdir. cache_size, foreign_keys ve busy_timeout ise yeni bağlantıda varsayılan değerlerine döndü. Belgeler cache_size için bunu açıkça söyler: değişiklik yalnızca o oturum boyunca sürer.

PragmaKapsamNot
user_version, application_idDosyada kalıcıUygulamaya ayrılmış başlık alanları
journal_mode = WALDosyada kalıcıDiğer günlük kipleri kalıcı değildir
page_sizeDosya oluşurken veya VACUUM ileWAL kipindeyken değiştirilemez
auto_vacuumDosyada kalıcıDolu dosyada NONE ile diğer kipler arası geçiş VACUUM ister
foreign_keysBağlantıya özelVarsayılan kapalı; her bağlantıda açın
busy_timeoutBağlantıya özelVarsayılan 0, yani beklemeden hata
cache_size, temp_storeBağlantıya özelYeniden açılışta varsayılana döner
synchronousBağlantıya özelŞema başına ayarlanır
query_only, trusted_schemaBağlantıya özelGüvenlik amaçlı

Sık kullanılan pragmalar

Şema bilgisi

table_info(tablo) her sıradan sütun için sıra, ad, tip, NOT NULL, varsayılan değer ve birincil anahtar içindeki konum bilgisini verir; görünümlerde de çalışır ama üretilmiş (generated) ve gizli sütunları göstermez, onlar için table_xinfo kullanılır. table_list 3.37.0 sürümünden beri şema adı, tablo adı, nesne türü, sütun sayısı, WITHOUT ROWID ve STRICT bilgisini tek satırda döndürür. index_list, index_info, index_xinfo ve foreign_key_list indeks ve yabancı anahtar ayrıntılarını verir. Belgeler table_info çıktısındaki cid sütununa "sonuç kümesindeki sıra" dışında bir anlam yüklenmemesi gerektiğini not eder.

Bütünlük denetimi

integrity_check veritabanını baştan sona denetler ve sorun yoksa tek satırda ok döndürür. quick_check aynı işi UNIQUE kısıtlarını ve indeks içeriğinin tabloyla uyumunu denetlemeden yapar; belgelere göre bu sayede O(NlogN) yerine O(N) sürede biter. foreign_key_check ise yabancı anahtar ihlallerini satır satır listeler. Bozulma şüphesinde ne yapılacağı bozuk veritabanı kurtarma yazısında.

sql
PRAGMA query_only = 1;
INSERT INTO urun(ad) VALUES ('kalem');
-- hata: attempt to write a readonly database
PRAGMA query_only = 0;

PRAGMA integrity_check;
-- çıktı: ok
PRAGMA quick_check;
-- çıktı: ok
PRAGMA foreign_key_check;       -- sorun yoksa satır döndürmez

query_only açıkken CREATE, DELETE, DROP, INSERT veya UPDATE denemeleri salt okunur hatasıyla reddedilir. Belgeler bunun gerçek bir salt okunurluk olmadığını, checkpoint ve COMMIT'in hâlâ çalışabildiğini belirtir; rapor üreten bir betiğin yanlışlıkla veri değiştirmesini önlemek için kullanışlı bir emniyet kemeridir.

Performans ve depolama

journal_mode, synchronous, cache_size, temp_store, mmap_size ve page_size performansı en çok etkileyen ayarlardır ve her birinin güvenlik açısından bir bedeli vardır; ayrıntılar performans ayarları yazısında. auto_vacuum, incremental_vacuum, freelist_count ve page_count dosya boyutu yönetimiyle ilgilidir. optimize ve analysis_limit sorgu planlayıcısının istatistiklerini yönetir; bkz. ANALYZE yazısı.

Güvenlik

trusted_schema, görünümlerin, tetikleyicilerin ve CHECK, DEFAULT, üretilmiş sütun, ifade indeksi gibi şema ifadelerinin güvenlik denetiminden geçmemiş SQL fonksiyonlarını ve sanal tabloları çalıştırıp çalıştıramayacağını belirler. Geriye uyumluluk için varsayılan değeri açıktır, ancak belgeler her bağlantıda açılır açılmaz kapatılmasını önerir ve çoğu uygulamanın bundan etkilenmeyeceğini belirtir. Güvenilmeyen dosyalarla çalışırken kullanılacak diğer ayarlar güvenlik ayarları yazısında.

Sürüm ve uygulama kimliği

user_version uygulamanın kendi şema sürümü içindir; application_id ise dosyanın hangi uygulamaya ait olduğunu belirten bir tamsayı tutar. schema_version SQLite'ın şema her değiştiğinde kendisinin artırdığı bir sayaçtır ve belgelerde test amaçlı pragmalar arasında yer alır; uygulama kodunda değiştirmeyin. data_version, başka bir bağlantının veritabanını değiştirip değiştirmediğini anlamak için aynı bağlantıda iki farklı anda okunup karşılaştırılır.

Uygulamalı örnek: bağlantı açılış betiği

Bağlantıya özel ayarlar her bağlantıda yeniden yapılmalıdır. Programlama dilinizin bağlayıcısında bağlantıyı açtıktan hemen sonra çalıştıracağınız kısa bir betik bu işi standart hâle getirir. Aşağıdaki satırların her biri belgelerdeki bir öneriye dayanır; uygulamanızın ihtiyacına göre seçin:

sql
-- Bir web uygulamasının her bağlantıyı açtıktan sonra çalıştırabileceği ayarlar
PRAGMA foreign_keys = ON;        -- bağlantıya özel, varsayılan kapalı
PRAGMA busy_timeout = 5000;      -- kilitli veritabanında 5 saniyeye kadar bekle
PRAGMA trusted_schema = OFF;     -- belgelerin her bağlantı için önerdiği ayar
PRAGMA journal_mode = WAL;       -- dosyada kalıcı; tekrar çalıştırmak zararsız
PRAGMA synchronous = NORMAL;     -- WAL ile önerilen denge
PRAGMA optimize = 0x10002;       -- uzun ömürlü bağlantının açılışında

Bu betikte iki ayrım önemlidir. journal_mode = WAL dosyada kalıcı olduğu için aslında bir kez yeterlidir; her açılışta çalıştırmak yalnızca kipin doğru olduğunu doğrular. optimize = 0x10002 uzun ömürlü bağlantılar içindir; her istekte açılıp kapanan kısa bağlantılarda bunun yerine bağlantı kapanmadan önce argümansız PRAGMA optimize; çalıştırın. Bağlantı açma yöntemi diller arasında değiştiği için Python, Node.js ve PHP PDO yazılarımıza bakabilirsiniz.

Kullanımdan kaldırılmış ve test amaçlı pragmalar

Belgelerdeki listede bazı pragmalar kullanımdan kaldırılmış olarak işaretlidir: count_changes, data_store_directory, default_cache_size, empty_result_callbacks, full_column_names, short_column_names, temp_store_directory ve case_sensitive_like. Bunlar yalnızca eski uygulamalar için tutulur ve SQLITE_OMIT_DEPRECATED ile derlenmiş kütüphanelerde hiç bulunmayabilir. parser_trace ve vdbe_ ile başlayan pragmalar yalnızca hata ayıklama derlemelerinde vardır. schema_version, stats ve writable_schema ise SQLite'ı test etmek için tasarlanmıştır; özellikle writable_schema yanlış kullanıldığında veritabanını kolayca bozabilir. legacy_file_format artık hiçbir şey yapmaz.

Sık yapılan hatalar

Sık yapılan hatalar: Yazım hatasını fark etmemek, Bağlantıya özel ayarı bir kez yapıp unutmak, İşlem içinde journal_mode değiştirmeye çalışmak, Dönen değeri kontrol etmemek
  • Yazım hatasını fark etmemek: Bilinmeyen pragma sessizce yok sayılır; ayarı değiştirdikten sonra okuyun.
  • Bağlantıya özel ayarı bir kez yapıp unutmak: foreign_keys ve busy_timeout her yeni bağlantıda yeniden ayarlanmalıdır.
  • İşlem içinde journal_mode değiştirmeye çalışmak: Belgelere göre günlük kipi bir işlem açıkken değiştirilemez.
  • Dönen değeri kontrol etmemek: journal_mode değişemediğinde eski kipi döndürür.
  • Pragma çıktısını kalıcı bir arayüz sanmak: Sütunlar sürümlerle genişleyebilir; table_list belgesi ileride yeni sütunlar ekleneceğini açıkça belirtir.

Sık Sorulan Sorular

Bir pragmanın mevcut değerini nasıl öğrenirim?

Argümansız çalıştırın: PRAGMA cache_size;. Fonksiyon biçimini destekleyenlerde SELECT * FROM pragma_cache_size; de aynı değeri döndürür.

Pragma ayarlarını kalıcı yapmanın genel bir yolu var mı?

Hayır. Yalnızca dosya başlığında saklanan ayarlar kalıcıdır. Diğerleri için uygulamanızın bağlantı açılış kodunda pragmaları çalıştırmanız gerekir.

PRAGMA komutları işlem içinde çalışır mı?

Çoğu çalışır, ama bazı pragmalar işlem açıkken değiştirilemez; journal_mode bunun belgelenmiş örneğidir. Ayarları bağlantı açıldıktan hemen sonra, herhangi bir işlem başlamadan yapmak en güvenlisidir.

Pragma listesinin tamamını nerede bulurum?

Resmî PRAGMA sayfası her pragmayı ayrı ayrı açıklar. Kendi derlemenizde tanınanları PRAGMA pragma_list; listeler.

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 performans ayarları · SQLite WAL modu · SQLite tabloları listeleme · SQLite şema göçü ve user_version · SQLite güvenlik ayarları