Bölüm 10: Veri Tabanı
Çoktan Seçmeli · Veri Tabanı Kavramı
Soru 1: Dosya mı, Veri Tabanı mı?
Bir okulun not kayıtları CSV dosyasında tutuluyor. Aynı anda birçok öğretmenin not girmeye başlamasıyla en çok hangi sorun veri tabanına geçmeyi gerektirir?
B: Düz dosyada iki program aynı anda yazarsa biri ötekinin değişikliğini ezebilir ya da dosya yarım kalabilir; veri tabanı kilitleme ve işlemlerle (ya hepsi ya hiçbiri) bunu yönetir. Dosyalar da kalıcıdır; CSV Java'dan BufferedReader ile okunabilir ve 1 MB gibi bir sınır yoktur.
Çoktan Seçmeli · Veri Tabanı Kavramı
Soru 2: Tablo, Satır, Birincil Anahtar
ogrenciler(no INTEGER PRIMARY KEY, ad TEXT, bolum TEXT) tablosu için hangisi doğrudur?
C: Satır bir varlığın (bir öğrenci) bütün bilgisidir, sütun bir özelliğidir (ad TEXT). Birincil anahtar her satırı benzersiz tanımlar: aynı no ile ikinci satır reddedilir. Benzersizlik başka sütunlara kendiliğinden geçmez; bunun için UNIQUE kısıtı yazılır. Java benzetmesi: tablo ≈ sınıf, sütun ≈ alan, satır ≈ nesne.
Çoktan Seçmeli · SQLite
Soru 3: SQLite'ın Özellikleri
SQLite için hangisi doğrudur?
D: SQLite gömülü ve sunucusuzdur: projeye tek bir sürücü jar'ı eklenir, jdbc:sqlite:okul.db dosyayı yoksa oluşturur. Bellekte geçici veri tabanı yalnızca jdbc:sqlite::memory: ile açılır. Aynı anda tek yazıcıya izin verdiği için çok kullanıcılı büyük sistemlerde MySQL, PostgreSQL gibi sunucu tabanlı sistemler tercih edilir.
Adım Adım Çalıştırma · SQL Temelleri
Soru 4: SQL Komutları ve id
Boş bir veri tabanında bu SQL komutları sırayla çalışıyor. Her komuttan sonra tablo nasıl olur, son SELECT ne döndürür?
Tablo oluştu; üç sütun, hiç satır yok.
id verilmedi: INTEGER PRIMARY KEY en büyük id + 1 = 1 atar.
defter id 2, silgi id 3 alır.
WHERE fiyat < 20 iki satırı seçer (10 ve 5); ikisi de iki katına çıkar. defter (25) değişmez.
id = 3 olan silgi silinir.
En büyük id artık 2: cetvel id 3'ü alır. Silinen satırın numarası yeniden kullanıldı (AUTOINCREMENT yazılsaydı 4 olurdu).
SELECT yalnızca okur; üç satır döner.
CREATE TABLE urun (id INTEGER PRIMARY KEY, ad TEXT, fiyat INTEGER); INSERT INTO urun(ad, fiyat) VALUES ('kalem', 10); INSERT INTO urun(ad, fiyat) VALUES ('defter', 25); INSERT INTO urun(ad, fiyat) VALUES ('silgi', 5); UPDATE urun SET fiyat = fiyat * 2 WHERE fiyat < 20; DELETE FROM urun WHERE id = 3; INSERT INTO urun(ad, fiyat) VALUES ('cetvel', 15); SELECT * FROM urun;
Çoktan Seçmeli · SQL Temelleri
Soru 5: Süz, Sırala, Sınırla
ogrenci(ad, puan) tablosunda (Ece, 85), (Can, 70), (Ada, 85), (Efe, 65), (Naz, 92) var. Sorgu hangi adları hangi sırayla döndürür?
SELECT ad FROM ogrenci WHERE puan >= 70 ORDER BY puan DESC, ad LIMIT 3;
A: WHERE puan >= 70 Efe'yi eler. ORDER BY puan DESC büyükten küçüğe sıralar: Naz (92), sonra 85'teki iki kişi; eşitlikte ikinci ölçüt ad artan sırada: Ada, Ece. LIMIT 3 ilk üç satırı alır, Can (70) dışarıda kalır.
Çıktı Sorusu · SQL Temelleri
Soru 6: Toplama Fonksiyonları
ogrenci(ad, puan) tablosunda (Ece 85, Can 70, Ada 85, Efe 65, Naz 92) satırları var. Bu sorgu hangi dört değeri döndürür?
SELECT COUNT(*), AVG(puan), MAX(puan), MIN(puan) FROM ogrenci WHERE puan < 90;
Cevabı göster
4 | 76.25 | 85 | 65
WHERE önce satırları süzer: 92 puanlı Naz elenir, 4 satır kalır (85, 70, 85, 65). Toplama fonksiyonları bu satırlar üzerinde çalışır: COUNT 4, AVG = 305 / 4 = 76.25, MAX 85, MIN 65. Sonuç tek satırdır.
Çoktan Seçmeli · JDBC
Soru 7: Kaynakların Kapanma Sırası
try (Connection conn = ...; Statement st = conn.createStatement(); ResultSet rs = st.executeQuery(sql)) { ... } bloğu bitince kaynaklar hangi sırayla kapanır?
B: try-with-resources kaynakları açıldıkları sıranın tersiyle kapatır; blok istisnayla bitse de kapatma yapılır. ResultSet, Statement'a; Statement, Connection'a bağlı olduğu için bu sıra doğal olanıdır. Kapatılmayan bağlantılar SQLite dosyasını kilitli bırakabilir.
Çıktı Sorusu · Temel İşlemler
Soru 8: execute Metotlarının Dönüş Değerleri
t(id INTEGER PRIMARY KEY, ad TEXT) tablosu boş. Program ne yazdırır?
int a = st.executeUpdate(
"INSERT INTO t(ad) VALUES ('x'), ('y'), ('z')");
int b = st.executeUpdate(
"UPDATE t SET ad = 'w' WHERE id > 1");
int c = st.executeUpdate(
"DELETE FROM t WHERE ad = 'q'");
boolean d = st.execute("SELECT * FROM t");
System.out.println(a + " " + b + " " + c + " " + d);Cevabı göster
3 2 0 true
- Tek INSERT üç satır ekler;
executeUpdateetkilenen satır sayısını döndürür: 3 (id 1, 2, 3). id > 1iki satırı seçer: 2.- 'q' adlı satır yok: hata olmaz, 0 döner. Silme mesajını bu sayıya göre vermek bu yüzden doğrudur.
executesonuç kümesi üreten komut için true, öteki komutlar için false döndürür.
Adım Adım Çalıştırma · Temel İşlemler
Soru 9: ResultSet ile Ortalama
kisiler tablosu şekildeki gibi. Program ne yazdırır? Ok, sonuç kümesindeki imleci gösterir.
Sorgu çalışır: yas > 20 Ali'yi eler, kalanlar yaşa göre sıralanır. İmleç ilk satırdan önce bekler.
rs.next() imleci 1. satıra taşır, true döner.
Sütunlar adıyla okunur; sayaç ve toplam güncellenir.
İkinci satır.
Üçüncü satır.
Başka satır yok: rs.next() false, döngü biter.
77 / 3; (double) olmasaydı tam sayı bölmesi 25 verirdi. Blok bitince rs ve st kapanır.
String sql = "SELECT ad, yas FROM kisiler "
+ "WHERE yas > 20 ORDER BY yas";
try (Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(sql)) {
int n = 0, toplam = 0;
while (rs.next()) {
String ad = rs.getString("ad");
int yas = rs.getInt("yas");
n++;
toplam += yas;
System.out.println(ad + " " + yas);
}
System.out.println(n + " kişi, ortalama "
+ (double) toplam / n);
}Hata Bulma · Temel İşlemler
Soru 10: Üç Hata
kisiler(id, ad, soyad, yas) tablosuyla çalışan bu satırların her biri bir SQLException fırlatıyor. Nedenlerini ve düzeltmelerini yazın.
ResultSet rs = st.executeQuery(
"SELECT ad FROM kisiler");
rs.next();
String ad = rs.getString(0); // 1
st.executeQuery("INSERT INTO kisiler(ad, soyad, yas) "
+ "VALUES ('Ece', 'Er', 20)"); // 2
st.executeUpdate("INSERT INTO kisiler(ad, soyad, yas) "
+ "VALUES (Bora, 'Er', 20)"); // 3Cevabı göster
getString(0): sütun numaraları 1'den başlar. İleti:column 0 out of bounds [1,1]. DoğrusugetString(1)ya dagetString("ad").- INSERT sonuç kümesi döndürmez:
query does not return ResultSet. INSERT, UPDATE, DELETE içinexecuteUpdatekullanılır. (SQLite sürücüsüyle denemede satır yine de eklendi.) Boratırnaksız yazıldığı için sütun adı sanılır:no such column: Bora. Metin değerler tek tırnak içinde yazılır; en iyisiPreparedStatementvesetString.
Çoktan Seçmeli · PreparedStatement
Soru 11: Yer Tutucuların Sırası
conn.prepareStatement("UPDATE kisiler SET yas = ? WHERE ad = ? AND soyad = ?") ile Ece Demir'in yaşı 25 yapılacak. Hangi çağrılar doğrudur?
C: ?'ler SQL metnindeki sıralarına göre 1'den başlayarak numaralanır: önce SET'teki yaş, sonra WHERE'deki ad ve soyad. 0 indisi geçersizdir. Her ? tek bir değerdir; ad ve soyadı tek parametrede birleştirmek eşleşmeyi bozar. Sonra executeUpdate() parametresiz çağrılır.
Çıktı Sorusu · PreparedStatement
Soru 12: Sayısal Enjeksiyon
k2 tablosunda id'si 1, 2, 3 olan üç satır var. Kullanıcı silinecek kayıt numarası olarak 0 OR 1=1 yazıyor. Önce PreparedStatement, sonra birleştirilmiş SQL çalışıyor. Hangi iki sayı yazdırılır?
String girdi = "0 OR 1=1";
try (PreparedStatement ps = conn.prepareStatement(
"DELETE FROM k2 WHERE id = ?")) {
ps.setString(1, girdi);
System.out.println(ps.executeUpdate());
}
System.out.println(st.executeUpdate(
"DELETE FROM k2 WHERE id = " + girdi));Cevabı göster
0 3
PreparedStatement'ta girdi yalnızca bir değerdir: id = '0 OR 1=1' hiçbir satırla eşleşmez, 0 satır silinir.
Birleştirmede girdi SQL'in parçası olur: DELETE FROM k2 WHERE id = 0 OR 1=1. 1=1 her satırda doğru olduğu için tablonun tamamı silinir: 3. Enjeksiyon için tırnak gerekmez; sayısal alanlar da korunmalıdır. Girdi her zaman ? ve setXxx ile verilmelidir.
Kod Yazma · PreparedStatement
Soru 13: Soyada Göre Ortalama Yaş
static double ortalamaYas(Connection conn, String soyad) throws SQLException metodunu yazın: verilen soyadlı kişilerin yaş ortalamasını AVG ile bulup döndürsün; girdi SQL metnine eklenmesin, açılan kaynaklar kapansın. kisiler tablosunda Ali Kaya 19, Ece Demir 24, Can Kaya 31, Naz Demir 22 varken "Kaya" ve "Yok" için ne döner?
Cevabı göster
static double ortalamaYas(Connection conn, String soyad) throws SQLException { String sql = "SELECT AVG(yas) FROM kisiler WHERE soyad = ?"; try (PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, soyad); try (ResultSet rs = ps.executeQuery()) { return rs.next() ? rs.getDouble(1) : 0; } } }
"Kaya": (19 + 31) / 2 = 25.0. "Yok": eşleşen satır olmasa da AVG tek satır döndürür, değeri NULL'dır; getDouble NULL için 0.0 verir (ayırt etmek gerekirse rs.wasNull()). Bağlantı metodun parametresidir; onu açan kod kapatır.
Çoktan Seçmeli · MySQL
Soru 14: SQLite'tan MySQL'e
SQLite ile çalışan bir JDBC programı MySQL sunucusuna taşınacak. Genellikle neler değişir?
D: JDBC arayüzleri aynıdır; çok biçimlilik sayesinde gerçek nesneyi sürücü sağlar. Değişenler: jdbc:mysql://localhost:3306/testdb gibi adres, getConnection(url, kullanici, sifre) ve mysql-connector-j jar'ı. Temel SQL (CREATE, INSERT, SELECT…) büyük ölçüde aynıdır; küçük farklar (ör. otomatik artan anahtar sözdizimi) olabilir.
Çoktan Seçmeli · İşlemler
Soru 15: ACID
“Bir havale commit edildikten bir saniye sonra elektrik kesilse bile, sistem yeniden açıldığında havale yapılmış görünür.” Bu cümle ACID'in hangi özelliğidir?
A: Kalıcılık: commit edilen değişiklik kalıcı depolamaya yazılmıştır, kaybolmaz. Bölünmezlik işlemin ya tamamının ya hiçbirinin uygulanması; tutarlılık işlem sonunda kısıtların (ör. bakiye ≥ 0) sağlanması; yalıtım eş zamanlı işlemlerin birbirinin yarım hâlini görmemesidir.
Adım Adım Çalıştırma · İşlemler
Soru 16: UNIQUE Hatası ve rollback
uye(id INTEGER PRIMARY KEY, email TEXT UNIQUE) tablosu boş. Üç e-posta tek bir işlem içinde ekleniyor. Program ne yazdırır, tabloda kaç satır kalır? Kesikli satırlar henüz commit edilmemiştir.
İşlem başlar: bundan sonraki değişiklikler commit'e kadar geçicidir.
a@x eklenir (id 1), henüz kalıcı değil.
b@x eklenir (id 2).
a@x ikinci kez: UNIQUE constraint failed: uye.email. SQLException fırlar; commit satırına gelinmez.
rollback(): işlemdeki iki ekleme de geri alınır.
finally auto-commit'i yeniden açar. Tabloda 0 satır: ya hepsi ya hiçbiri.
conn.setAutoCommit(false); String sql = "INSERT INTO uye(email) VALUES(?)"; try (PreparedStatement ps = conn.prepareStatement(sql)) { for (String e : new String[] {"a@x", "b@x", "a@x"}) { ps.setString(1, e); ps.executeUpdate(); } conn.commit(); System.out.println("kaydedildi"); } catch (SQLException ex) { conn.rollback(); System.out.println("geri alındı"); } finally { conn.setAutoCommit(true); }
Çıktı Sorusu · İşlemler
Soru 17: İşlem Olmadan
uye(id INTEGER PRIMARY KEY, email TEXT UNIQUE) tablosu boş ve bağlantı varsayılan ayarda (auto-commit açık). Kod çalıştıktan sonra tabloda kaç satır kalır, neden?
String sql = "INSERT INTO uye(email) VALUES(?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
for (String e : new String[] {"a@x", "b@x", "a@x"}) {
ps.setString(1, e);
ps.executeUpdate();
}
} catch (SQLException ex) {
System.out.println("hata");
}Cevabı göster
2 satır (a@x ve b@x). Auto-commit açıkken her executeUpdate kendi başına kalıcı olur: ilk iki ekleme hemen yazılır, üçüncüsü UNIQUE yüzünden reddedilir ve geri alınacak bir işlem yoktur. Liste “ya hepsi ya hiçbiri” yerine yarım kalır. setAutoCommit(false), commit() ve hata durumunda rollback() ile tablo boş kalırdı. Birlikte anlam taşıyan komutlar (havale, sipariş ve kalemleri) bu yüzden tek işlemde yürütülür.