Menu

SQLite ATTACH DATABASE: Birden Fazla Dosyada Sorgu

ATTACH DATABASE komutuyla tek bağlantıda birden fazla SQLite dosyasını açıp şema önekleriyle birlikte nasıl sorgulayacağınızı ve işiniz bittiğinde nasıl ayıracağınızı anlatıyoruz.

Bu sayfada çalıştırılabilir editörler var — düzenle, çalıştır ve sonucu anında gör.

Tek Bağlantı, Birden Fazla Dosya

SQLite'ta bir bağlantı tek bir dosyaya mahkum değildir. ATTACH DATABASE ile, halihazırda açtığınız veritabanının yanına başka .db dosyaları da bağlayabilir ve hepsini sanki tek bir veritabanının içindeki şemalarmış gibi sorgulayabilirsiniz. SQLite'ın "tek sunucuda birden fazla veritabanı" mantığına en yakın çözümü budur.

Temel kullanım şöyle:

archive.db dosyası, ana veritabanında olduğu gibi, eğer yoksa otomatik olarak oluşturulur. Bu oturum boyunca archive. ön ekiyle gelen her şey bu ikinci dosyada, main. ön ekiyle gelen (ya da hiç ön ek almayan) her şey ise orijinal veritabanında yaşar.

Her bağlantınızda zaten örtük olarak iki şema bulunur: main (ilk açtığınız dosya) ve temp (geçici tablolar için kullanılan bir karalama alanı). ATTACH ile bunlara yenilerini eklersiniz.

Söz dizimi ve takma adın işlevi

ATTACH DATABASE 'path/to/file.db' AS alias_name;

Bu takma ad (alias), tablolara erişirken kullanacağın şema adıdır. Yalnızca aktif bağlantıya özgüdür — aynı dosyayı bağlayan başka bir bağlantı farklı bir alias seçebilir. Bunu çok yazacağın için kısa ve açıklayıcı bir isim seç (archive, analytics, cache gibi).

Bilmeniz gereken birkaç ufak nokta var:

  • Yol mutlak değilse, sürecin çalışma dizinine göre değerlendirilir.
  • ':memory:' ifadesi, o alias altına yepyeni bir bellek içi (in-memory) veritabanı bağlar.
  • Alias, main veya temp ile çakışamaz ve aynı bağlantıda birden fazla kez kullanılamaz.

Farklı Veritabanları Arasında Join Yapmak

İnsanların ATTACH kullanmasının başlıca sebebi tam da budur. İki dosya aynı bağlantıya bağlandığında, tek bir sorguda bu dosyaların tablolarını join'leyebilirsiniz:

Sorgu planlayıcı, eklenen şemayı main içindeki tablolarla aynı şekilde değerlendirir. Eklenen tablolardaki indeksler kullanılır, EXPLAIN QUERY PLAN veritabanları arasında sorunsuz çalışır. Ortada ağ üzerinden gidip gelen bir istek de yok — iki dosya da aynı süreçte açık duruyor.

Bu yöntem; sıcak veriyi soğuk arşivden ayırmak, kiracı başına ayrı dosyalar tutmak ya da salt okunur bir referans veritabanından sabit verileri çekmek için gerçekten işe yarıyor.

Salt okunur ve bellek içi veritabanı bağlama

İkinci veritabanını yalnızca okumak istiyor, üzerine yazmayı düşünmüyorsanız — örneğin uygulamayla birlikte dağıttığınız sabit bir referans veri kümesi — onu URI kullanarak salt okunur şekilde bağlayabilirsiniz:

URI biçiminin çalışması için SQLite kütüphanesinde SQLITE_OPEN_URI özelliğinin etkin olması gerekir (CLI'da ve çoğu dil bağlamasında zaten açıktır). Bu sayede ref.* üzerinde yapılacak herhangi bir INSERT, UPDATE ya da DELETE işlemi, dosyaya hiç dokunmadan hata fırlatır.

Bellek içi (in-memory) bağlamalar da geçici veri hazırlamak için bir o kadar kullanışlıdır:

scratch veritabanı, bağlantı kapandığında uçup gider. Aslında temp gibi davranır ama ömrünü sen kontrol edersiniz.

Transactions Tüm Bağlı Veritabanlarını Kapsar

Tek bir BEGIN/COMMIT bloğu, hem main üzerindeki hem de eklenmiş (attach edilmiş) tüm şemalardaki yazma işlemlerini birlikte ele alır. Yani ya hepsi birden işlenir ya da hepsi geri alınır — atomiklik dosyalar arasında bile korunur:

Canlı bir tablodaki satırları arşiv dosyasına taşımak, tam da bu garantiye ihtiyaç duyacağınız türden bir işlemdir. Dosyalar arası atomiklik olmadan, işlemin ortasında yaşanacak bir çökme size ya yinelenmiş satırlar bırakır ya da daha kötüsü, satırlarınızın bir kısmını kaybetmenize yol açar.

Şuna da dikkat: bir transaction içinde birden fazla bağlı veritabanına yazılıyorsa, SQLite geçici bir journal dosyası gerektiren daha temkinli bir commit protokolüne geçer. Tek dosyalı commit'lere göre yavaştır ama yine de güvenlidir.

Veritabanı bağlantısını kaldırma (DETACH)

Bağladığınız veritabanıyla işiniz bittiğinde onu çıkarın:

DETACH DATABASE archive;

Dosyanın kendisi diskte olduğu gibi kalır — DETACH yalnızca o bağlantıdaki handle'ı kapatır. Aklınızda tutmanız gereken iki kısıt var:

  • main ve temp veritabanlarını detach edemezsiniz.
  • Aktif bir transaction içinde olan ya da üzerinde açık statement bulunan bir veritabanını detach edemezsiniz.

Detach etmeyi unutursanız da dünyanın sonu değil: bağlantı kapandığında her şey temizlenir.

Sınırlar ve sık karşılaşılan hatalar

Bilmeniz gereken birkaç pratik sınır var:

  • Bağlantı başına varsayılan üst sınır 10 attached veritabanıdır (main ve temp buna dahil değil). Derleme zamanı maksimumu ise 125. Bu sınırı aştığınızda too many attached databases - max 10 hatasını görürsünüz.
  • Her attach edilen dosya bir page cache kullanır. Bir düzine büyük veritabanını attach etmek bedelsiz değildir — RAM tüketimi artar.
  • ATTACH komutu transaction içinde çalıştırılamaz. Onu BEGIN'den önce ya da COMMIT'ten sonra çalıştırın.

Karşılaşmanız muhtemel birkaç hata:

-- Dosya mevcut değil ve dizin yazılabilir değil:
Error: unable to open database: 'missing/path.db'

-- Salt okunur bir eke yazmaya çalıştınız:
Error: attempt to write a readonly database

-- Aynı takma adı iki kez kullandınız:
Error: database archive is already in use

Çoğu hata, okur okumaz "haa, tabii ya" dedirten cinsten. Ama bir tanesi insanı yanıltıyor: "already in use" hatası. ATTACH mevcut bir alias'ın üzerine yazmıyor; önce DETACH etmeniz gerekiyor.

Gerçekçi Bir Senaryo: Sıcak/Soğuk Veri Ayrımı

Şimdi öğrendiklerimizi birleştirelim — bir yıldan eski siparişleri ana veritabanından arşive taşıyan küçük bir iş akışı:

Eski satırlar archive.orders tablosuna taşınır, yeni olanlar ise main içinde kalır. Geçmişe ihtiyaç duyan raporlar iki veritabanı arasında join atabilir; günlük sorgular ise tablo daha küçük kaldığı için main.orders üzerinde hızlı çalışmaya devam eder. Tek bağlantı, iki dosya, tek transaction.

Sırada: Prepared Statements

ATTACH, tek bir bağlantıya daha fazla veriye erişim kazandırmakla ilgilidir. Bundan sonraki konular ise uygulamaların SQLite ile güvenli ve verimli şekilde nasıl konuştuğunu ele alacak — parametre bağlama ve SQL injection'a kapalı sorguların temeli olan prepared statements ile başlıyoruz.

Sıkça Sorulan Sorular

SQLite'ta ATTACH DATABASE ne işe yarar?

ATTACH DATABASE 'file.db' AS alias komutu, mevcut bağlantının içine ikinci bir SQLite dosyasını açar ve ona bir şema adı verir. Bundan sonra ilgili tablolara alias.table_name şeklinde erişebilir, bu tabloları ana veritabanınızdaki tablolarla aynı sorguda JOIN'leyebilirsiniz.

SQLite aynı anda kaç veritabanı bağlayabilir?

Varsayılan olarak SQLite, bağlantı başına main ve temp şemalarına ek olarak en fazla 10 bağlı veritabanına izin verir. Üst sınır 125'tir ve derleme sırasında SQLITE_MAX_ATTACHED ile ayarlanabilir. Limiti aştığınızda too many attached databases hatasını alırsınız.

Bağlı SQLite veritabanlarına tek sorguda erişebilir miyim?

Evet. Bağladıktan sonra her tabloyu kendi şema adıyla niteleyin: SELECT * FROM main.users JOIN archive.orders ON .... JOIN'ler, alt sorgular ve INSERT ... SELECT ifadeleri şemalar arasında sorunsuz çalışır. Üstelik transaction'lar da tüm bağlı veritabanlarını kapsar — yani bir COMMIT tüm dosyalar için atomiktir.

Bir SQLite veritabanını nasıl ayırırım (detach)?

DETACH DATABASE alias komutunu çalıştırmanız yeterli. Dosya disk üzerinde olduğu gibi kalır; DETACH yalnızca mevcut bağlantıdaki tutamacı (handle) kapatır. main veya temp şemalarını ayıramazsınız ve bir transaction'ın ortasındaki veritabanını da ayıramazsınız.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA