Python sqlite3 ile veritabanı oluşturmak ve sorgulamak için önce bir SQLite dosyasına bağlantı açar, ardından tabloyu SQL ile kurar, verileri parametrelerle eklersin. SQLite ayrı bir sunucu süreci gerektirmeden verileri tek bir disk dosyasında tutabildiği için temel bir kitap listesi uygulaması Python koduyla kurulabilir.
Bu yazıda bağlantı, tablo, parametreli sorgu ve sonuç okuma adımlarını aynı örnek üzerinden ilerleteceğiz.
SQLite veritabanı dosyası nasıl açılır?
SQLite veritabanı dosyası, sqlite3.connect() çağrısıyla açılır ve dosya mevcut değilse bu çağrı yeni bir veritabanı dosyası oluşturabilir. sqlite3 modülü Python standart kütüphane belgelerinde yer alır. Bu nedenle ilk adım olarak import sqlite3 kullanılır. Modül kullanılan Python dağıtımında bulunmuyorsa dağıtım sağlayıcısının belgeleri kontrol edilmelidir.
import sqlite3
connection = sqlite3.connect("kitaplar.db")
cursor = connection.cursor()
print("SQLite bağlantısı açıldı.")
connection değişkeni ile veritabanı dosyası arasında açık bir bağlantı kurulur. Bu nesne, işlemleri yönetmek ve gerektiğinde commit() ya da close() çağrıları yapmak için kullanılır. Göreli bir dosya yolu olan kitaplar.db, Python dosyasını çalıştırdığın geçerli çalışma klasöründe aranır.
cursor ise SQL komutlarını çalıştıran ve sorgulardan dönen satırları okumaya yarayan nesnedir. connection.cursor() ile oluşturulur. Kısaca bağlantı veritabanıyla iletişimi temsil eder, cursor ise bu iletişim üzerinden CREATE TABLE, INSERT ve SELECT gibi SQL komutlarını yürütür.
Bağlantı nesnesini with connection: biçiminde kullanırsan, blok normal tamamlandığında açık işlem için commit, yakalanmamış bir hata oluştuğunda rollback uygulanır. Bu kullanım bağlantıyı kendiliğinden kapatmaz. İşin sonunda connection.close() çağrısı yapılmalıdır. Python temellerini pekiştirmek için ücretsiz Sıfırdan Temel Python video eğitimi içindeki değişken, fonksiyon ve dosya işlemleri konularından yararlanabilirsin.
Tablo ve parametreli veriler nasıl oluşturulur?

kitaplar tablosu, sütunları ve temel kısıtları belirleyen bir CREATE TABLE komutuyla oluşturulur. id sütunu her kitap için kimlik görevi görür, INTEGER PRIMARY KEY ifadesi bu alanı birincil anahtar yapar. baslik ve yazar sütunlarındaki TEXT NOT NULL kısıtı ise bu alanların boş bırakılmamasını ister.
cursor.execute("""
CREATE TABLE IF NOT EXISTS kitaplar (
id INTEGER PRIMARY KEY,
baslik TEXT NOT NULL,
yazar TEXT NOT NULL
)
""")
kitap = ("Dönüşüm", "Franz Kafka")
cursor.execute(
"INSERT INTO kitaplar (baslik, yazar) VALUES (?, ?)",
kitap
)
aranan_yazar = "Franz Kafka"
cursor.execute(
"SELECT baslik FROM kitaplar WHERE yazar = ?",
(aranan_yazar,)
)
bulunan_kitaplar = cursor.fetchall()
connection.commit()
print(bulunan_kitaplar)
İlk execute() çağrısı tabloyu oluşturur. IF NOT EXISTS, aynı tablo daha önce oluşturulmuşsa bu komutun hata vermesini önler. İkinci execute() çağrısındaki soru işaretleri, Python değişkenlerinin SQL metnine güvenli biçimde bağlanacağı yer tutuculardır.
Parametreleri f-string ile SQL metnine birleştirmek yerine ? kullanmak önemlidir. Örneğin kullanıcıdan gelen ' OR 1=1 -- gibi bir metin doğrudan f-string içine yerleştirilirse sorgunun yapısını değiştirmeye çalışabilir. Parametreli kullanımda bu değer SQL komutu olarak yorumlanmaz, aranacak veri olarak ele alınır. Bu yaklaşım SQL enjeksiyonu riskini azaltır.
(aranan_yazar,) ifadesindeki virgül gereklidir. Virgül olmazsa parantez yalnızca normal gruplama işareti olur ve tek elemanlı tuple oluşmaz. fetchall() sorgu sonucundaki tüm satırları liste olarak döndürür; her satır burada bir tuple biçimindedir. Son olarak commit(), yapılan veri değişikliğini açık işlemden çıkarıp veritabanına kaydetmek için kullanılır.
SELECT sonuçları nasıl okunur ve bağlantı kapatılır?

SELECT sorgusunun ürettiği satırlar cursor üzerinden okunur, iş tamamlandığında veritabanı bağlantısı close() ile kapatılır. Belirli bir yazarı ararken değeri SQL metnine doğrudan eklemek yerine ? yer tutucusu kullanmak daha güvenli ve düzenli bir yöntemdir. Python’un sqlite3 belgelerinde bu yaklaşım parametre bağlama olarak açıklanır.
import sqlite3
conn = sqlite3.connect("kitaplar.db")
cursor = conn.cursor()
yazar = "George Orwell"
cursor.execute(
"SELECT baslik, yazar FROM kitaplar WHERE yazar = ? ORDER BY id",
(yazar,)
)
ilk_kitap = cursor.fetchone()
kalan_kitaplar = cursor.fetchall()
print("İlk kitap:", ilk_kitap)
print("Kalan kitaplar:", kalan_kitaplar)
conn.close()
fetchone() sonuç kümesindeki sıradaki tek satırı döndürür. Varsayılan ayarda bu satır, SELECT içinde istediğin sütun sırasına göre değerler taşıyan bir tuple olur. İki kayıt bulunduğunda ilk çağrı ("1984", "George Orwell") benzeri bir tuple döndürür.
Ardından çağrılan fetchall() ise artık okunmamış kalan satırları liste olarak verir. Bu nedenle yukarıdaki örnekte ikinci kitap liste içinde tek bir tuple olarak bulunur. Hiç sonuç yoksa fetchone() değeri None, fetchall() ise boş liste döndürür. Bu değerleri kontrol ederek ekrana “kayıt bulunamadı” mesajı yazabilirsin.
SELECT işlemi veriyi değiştirmediği için bu örnekte commit() çağrısı gerekmez. INSERT, UPDATE veya DELETE sonrasında değişiklikleri kalıcı hâle getirmek için commit() kullanılmalıdır. close() ise bağlantıyı sonlandırır ve kullanılmayan veritabanı kaynaklarının serbest bırakılmasını sağlar.
Bağlantı nesnesi with bloğunda kullanıldığında normal çıkışta açık işlem commit edilir, işlenmeyen bir hata oluştuğunda rollback yapılır. Ancak with bloğu bağlantıyı kendiliğinden kapatmaz; bu yüzden işlem sonunda ayrıca conn.close() çağrılmalıdır.
Kitap listesi uygulaması nasıl çalışır?
Tek dosyalık bu örnek, veritabanını açar, tabloyu oluşturur, kitapları parametreli olarak ekler ve seçilen yazara ait kitapları ekrana yazdırır.
import sqlite3
conn = sqlite3.connect("kitaplar.db")
cursor = conn.cursor()
try:
cursor.execute("""
CREATE TABLE IF NOT EXISTS kitaplar (
id INTEGER PRIMARY KEY,
baslik TEXT NOT NULL,
yazar TEXT NOT NULL,
UNIQUE (baslik, yazar)
)
""")
kitaplar = [
("1984", "George Orwell"),
("Hayvan Çiftliği", "George Orwell"),
("Kürk Mantolu Madonna", "Sabahattin Ali"),
]
cursor.executemany(
"INSERT OR IGNORE INTO kitaplar (baslik, yazar) VALUES (?, ?)",
kitaplar
)
conn.commit()
secilen_yazar = "George Orwell"
cursor.execute(
"SELECT baslik FROM kitaplar WHERE yazar = ? ORDER BY id",
(secilen_yazar,)
)
print(f"{secilen_yazar} kitapları:")
for (baslik,) in cursor.fetchall():
print(baslik)
except sqlite3.Error:
conn.rollback()
raise
finally:
conn.close()
connect() çağrısı kitaplar.db dosyasına bağlantı açar. Cursor, CREATE TABLE, INSERT ve SELECT komutlarını çalıştırır. UNIQUE (baslik, yazar) kısıtı aynı kitap ve yazar ikilisinin tekrar eklenmesini önler. Bu nedenle betiği yeniden çalıştırdığında INSERT OR IGNORE mevcut kayıtları ikinci kez eklemez.
executemany(), kitap listesindeki her tuple değerini ? yer tutucularına bağlayarak ekler. INSERT işleminden sonra commit() değişiklikleri kaydeder. SELECT sorgusundaki yazar değeri de parametre olarak gönderilir; fetchall() sonuçları alır ve döngü yalnızca kitap başlıklarını yazdırır. Bir veritabanı hatasında rollback uygulanır, finally bloğunda bağlantı kapatılır.
Betik temiz bir veritabanında çalıştırıldığında çıktı şu şekilde olur:
George Orwell kitapları:
1984
Hayvan Çiftliği
sqlite3 kullanımında hangi hatalara dikkat edilir?
sqlite3 ile çalışırken en sık karşılaşılan sorunlar, işlemi kaydetmeyi unutmak, sorguya değerleri güvensiz biçimde eklemek ve sorgu sonucunun boş olabileceğini hesaba katmamaktır. Aşağıdaki kontrol listesi, kitap listesi gibi küçük uygulamalarda hatayı daha hızlı teşhis etmene yardımcı olur.
commit()çağrısını kontrol et.INSERT,UPDATEveyaDELETEsonrasında işlemi kaydetmezsen değişiklikler açık işlem içinde kalabilir. Bağlantıyı kapatmadan öncebaglanti.commit()çağır veya işlemi birwithbloğuyla yönet.- SQL cümlesini f-string ile oluşturma.
f"SELECT ... WHERE ad = '{kitap_adi}'"biçimi, özel karakterlerde sorgu hatalarına ve dışarıdan gelen verilerde SQL injection riskine yol açabilir. Bunun yerine?yer tutucusu kullan:"SELECT * FROM kitaplar WHERE ad = ?". - Tek elemanlı parametrede virgülü unutma.
("Python",)bir elemanlı tuple oluşturur.("Python")ise parantez içindeki normal bir metindir ve sorguya parametre olarak verildiğinde beklenmeyen sonuç veya parametre sayısı hatası oluşturabilir. fetchone()sonucunu kontrol et. Sorgu eşleşen kayıt bulamazsa sonuçNoneolabilir. Bu değeri kontrol etmedensatir[0]yazmakTypeErrorhatasına neden olabilir. Kayıt varsa alanları okumak, yoksa uygun bir mesaj göstermek daha güvenlidir.- Bağlantıyı açık bırakma. İşin bittiğinde
baglanti.close()çağır. Bağlantının ne zaman kapatıldığı belli olmayan kodlarda kaynak yönetimi zorlaşır ve kaydedilmemiş işlemlerle ilgili sorunlar ortaya çıkabilir.
with sqlite3.connect(...) as baglanti: biçimi, bağlantıyı bir işlem bağlamı olarak kullanır. Blok istisnasız tamamlanırsa açık işlem commit edilir; blok içinde yakalanmadan yükselen bir istisna olursa işlem rollback edilir. Python'ın sqlite3 belgeleri bağlantı nesnesinin bu davranışını açıklar.
with sqlite3.connect("kitaplar.db") as baglanti:
baglanti.execute(
"INSERT INTO kitaplar (ad) VALUES (?)",
("Python'a Giriş",)
)
baglanti.close()
Burada with bloğu commit ve rollback yönetimini üstlenir, ancak bağlantıyı otomatik olarak kapatmaz. Bu nedenle bloktan sonra açıkça close() çağırmak gerekir. Kısa bir işlem grubunda commit ve rollback davranışını düzenlemek için with kullanabilirsin. Bağlantının ömrünü kendin yönetmek istediğin basit betiklerde ise açıkça commit() ve close() çağırmak daha anlaşılır olabilir. Python temellerini gözden geçirmek için Python bilgi testi ile ön kontrol yapabilirsin.
Sık Sorulan Sorular
sqlite3 kullanmak için Python’a ayrıca paket yüklemek gerekir mi?
Çoğu Python kurulumunda sqlite3 modülü ayrıca paket yüklemeden kullanılabilir. import sqlite3 çalışmıyorsa kullandığın Python dağıtımının kurulum belgelerini kontrol etmen gerekir.
commit() çağrılmazsa eklenen kitaplar neden kaybolabilir?
commit() çağrılmazsa ekleme işlemi veritabanına kalıcı olarak yazılmadan açık işlem içinde kalabilir. Bağlantı kapatıldığında veya program hata verdiğinde bu işlem geri alınabileceği için eklenen kitaplar daha sonra görünmeyebilir.
fetchone() ile fetchall() arasındaki fark nedir?
fetchone() sonuç kümesinden bir satır okur ve eşleşen satır yoksa None döndürür. fetchall() ise kalan tüm satırları liste olarak döndürür ve hiç sonuç yoksa boş liste verir.
SQL sorgusuna f-string ile değer eklemek neden güvenli değildir?
f-string, Python değerini SQL metninin içine doğrudan yerleştirir ve özel karakterlerin sorguyu bozmasına veya kötü amaçlı girdilerin SQL olarak yorumlanmasına neden olabilir. Değerleri ? yer tutucuları ve ayrı parametreler olarak göndermek daha güvenlidir.
with sqlite3.connect(...) bağlantıyı otomatik olarak kapatır mı?
with sqlite3.connect(...) bağlantıyı otomatik olarak kapatmaz; başarılı işlemde commit, istisna durumunda rollback yönetimi yapar. Bağlantıyı kapatmak için bloktan sonra close() çağırmalısın.
Bu kontrolleri alışkanlık hâline getirdiğinde sqlite3 ile yazdığın küçük uygulamalarda veri kaybı, güvensiz sorgu ve boş sonuç kaynaklı hataları daha kolay önleyebilirsin.