DDL ve Tablo Oluşturma

BLP 1005 — Veritabanı Yönetim Sistemleri

Öğr. Gör. Oktay Cesur

2026-10-13

Ele Alınacak Temel Sorular

  • Tasarlanan bir veri modeli doğrudan sunucuya neden veri alamaz?
  • Veri Tanımlama Dili (DDL) nedir ve neyi amaçlar?
  • Kavramsal modeldeki nitelikler SQL tanımlayıcılarına nasıl dönüştürülür?
  • Tablo ve sütun adlandırmasında neden küçük harf ve ASCII standardı zorunludur?
  • Veri tipi seçimi iş kurallarıyla nasıl ilişkilendirilir?
  • Sayısal karakterler içeren her alan neden sayısal tip (INT) yapılmaz?
  • Çalışma alanı (şema/veritabanı) nasıl açılır ve neden etkin kılınmalıdır?
  • Tablo sütunları ve kısıtları (constraints) hangi sözdizimiyle tanımlanır?
  • NULL değeri ne anlama gelir; sıfır veya boş metinden farkı nedir?
  • AUTO_INCREMENT ile birincil anahtar arasındaki kesin mekanizma ayrımı nedir?
  • PRIMARY KEY ile UNIQUE kısıtları arasındaki yapısal farklar nelerdir?
  • Çoka çok (N:M) ilişki fiziksel bağlantı tablosuna ve yabancı anahtara nasıl dönüştürülür?
  • Tablolar hangi sırayla oluşturulmalıdır ve sıra ihlalinde hangi hata ile karşılaşılır?
  • Oluşturulan tabloların sütun yapısı ve kısıtları (DESCRIBE, SHOW CREATE TABLE) ile nasıl doğrulanır?
  • Kısıtların çalıştığı kasıtlı hata denemesiyle (ERROR 1452) nasıl kanıtlanır?
  • Değişen kurumsal ihtiyaçlarda tablo yapısı veriler kaybedilmeden (ALTER TABLE) nasıl genişletilir?

Tasarlanan Şemadan Fiziksel Veritabanına: Neden Doğrudan Veri Eklenemez?

Önceki Adımlarda Ne Yaptık?

  • İş kurallarını inceleyip varlıkları, nitelikleri ve ilişkileri belirledik.
  • Varlık-İlişki modelini kurarak kütüphane senaryomuzu kavramsal düzeyde ayrıştırdık.
  • 1NF, 2NF ve 3NF normalizasyon kurallarını işleterek veri anomalilerini giderdik.
  • MySQL sunucusu ve MySQL Workbench çalışma ortamı arasındaki bağlantıyı doğruladık.

Doğrudan Veri Eklemeye Çalışırsak Ne Olur?

  • Tasarım kağıt üzerinde veya E-R diyagramında tamamlanmış olsa bile sunucuda henüz fiziksel bir karşılık yoktur.
  • Sunucuya bağlanıp doğrudan INSERT komutu çalıştırmak sonuç vermez.
  • Mekanik Engel: Sunucu hafızasında;
    • uye veya kitap adında hangi tabloların bulunduğu,
    • Bu tablolarda hangi sütunların yer aldığı,
    • Hangi sütuna hangi tür verilerin yazılabileceği,
    • Satırların hangi kısıt ve kurallarla denetleneceği henüz tanımlı değildir.

Fiziksel İskelet İhtiyacı: Veri Tanımlama Dili (DDL)

  • Verilerin kaydedilebilmesi için öncelikle veritabanının fiziksel iskeleti (şeması) kurulmalıdır.
  • Veri Tanımlama Dili (Data Definition Language - DDL): İlişkisel veritabanlarında tabloları, sütunları, veri tiplerini ve kısıtları tanımlamak, değiştirmek veya silmek için kullanılan komut kümesidir.
  • DDL komutları verilerin kendisiyle değil; verilerin içinde yaşayacağı yapısal düzenle ilgilenir.

Kavramsal Modelden SQL Tanımlayıcılarına: Adlandırma Nasıl Kurulmalıdır?

Sözel Nitelikten SQL Tanımlayıcısına (Identifier) Geçiş

  • Kavramsal modelde nitelikler sözel iş kurallarından gelir: “Üye Numarası”, “İletişim Bilgisi”, “Demirbaş Numarası”.
  • Veritabanı yönetim sistemine aktarılırken bu kavramlar birer SQL tanımlayıcısına (identifier) dönüşür.

Üç Temel Adlandırma Kuralı

1. Karakter ve Harf Standardı:
   - Yalnızca küçük harfli ASCII (a-z), rakamlar (0-9) ve alt çizgi (_) kullanılır.
   - Türkçe karakterler (ç, ğ, ı, ö, ş, ü) ve boşluk kesinlikle kullanılmaz.

2. Görsel Ayrım:
   - SQL dilinin anahtar sözcükleri BÜYÜK HARFLE yazılır: CREATE, TABLE, INT, PRIMARY KEY.
   - Kullanıcı tanımlı nesne adları küçük harfle yazılır: uye, kitap, ad_soyad.

3. Anlamlılık:
   - Belirsiz kısaltmalar (u_no, tar1, bilgi) yerine nesneyi açıkça ifade eden adlar seçilir.

Mekanik Gerekçe: İşletim Sistemi ve Dosya Sistemi Farkları

  • Linux dosya sistemleri büyük/küçük harf duyarlıdır (case-sensitive).
  • Windows dosya sistemleri büyük/küçük harf duyarsızdır (case-insensitive).
  • MySQL, veritabanı ve tablo adlarını doğrudan disk üzerindeki dizin ve dosya adlarıyla eşleştirir (lower_case_table_names).
  • Küçük harf ve ASCII standardı, kodların işletim sistemleri arasında taşınırken nesne erişim hatası vermesini engeller.

Kütüphane Niteliklerinin Dönüşüm Tablosu

Kavramsal Nitelik SQL Tanımlayıcısı Gerekçe
Üye Numarası uye_numarasi Küçük harf ASCII, alt çizgi, anlamlı ad
Ad Soyad ad_soyad Boşluksuz, alt çizgili, Türkçe karaktersiz
Demirbaş Numarası demirbas_numarasi Açıklayıcı kimlik tanımlayıcısı
Alış Tarihi alis_tarihi ASCII standartlaştırması (s harfi)
İade Tarihi iade_tarihi Zaman olayını gösteren net tanımlayıcı

Veri Tipi Seçimi: İş Kuralı Depolama Türünü Nasıl Belirler?

Veri Tipi Ne İşe Yarar?

  • Sunucuya o sütunda ne tür değerlerin saklanabileceğini bildirir.
  • Depolama için ayrılacak bellek ve disk alanını sınırlar.
  • Girilebilecek verilerin sınırlarını ve geçerlilik kurallarını belirler.

Ezber Liste Değil, Üç Temel Soru

                    [ Sütunun Temsil Ettiği Bilgi ]
                                   │
         ┌─────────────────────────┼─────────────────────────┐
         ▼                         ▼                         ▼
   1. Aritmetik?             2. Uzunluk?                3. Zaman?
   Matematiksel işlem        Sabit mi, değişken mi?     Takvim ve gün farkı
   yapılacak mı?             Boyut sınırı nedir?        hesabı var mı?

MySQL Temel Veri Tipleri Sınıflandırması

  • Sayısal Tipler:
    • INT: Standart 4 bayt tamsayı. Sayaçlar, miktarlar ve matematiksel işleme girecek tamsayılar için kullanılır.
    • DECIMAL(M, D): Kesin basamaklı sayısal değerler. M toplam basamak sayısı (hassasiyet), D virgülden sonraki basamak sayısıdır (ölçek). Kayan noktalı (FLOAT, DOUBLE) yuvarlama hatalarına izin vermez; finansal ve parasal tutarlar için zorunludur.
  • Metinsel Tipler:
    • VARCHAR(N): Değişken uzunluklu metin (N en fazla karakter sayısı). Bellekte yalnızca girilen karakter kadar (artı 1–2 bayt uzunluk bilgisi) yer tutar; disk tasarrufu sağlar.
    • TEXT: Boyutu önceden kestirilemeyen uzun açıklamalar ve gövdeler için kullanılır.
  • Tarih ve Zaman Tipleri:
    • DATE: YYYY-MM-DD biçiminde takvim tarihi saklar. 30 Şubat gibi geçersiz tarihlerin girilmesini engeller; tarihler arası gün farkı hesaplamaya olanak tanır.

Sayısal Görünen Her Değer Sayı mıdır?

En Sık Düşülen Tasarım Tuzağı

  • Yalnızca rakamlardan oluşan her veriyi sayısal (INT) veri tipiyle tanımlamaya çalışmak.

Temel Karar Ölçütü

  • “Bu değer üzerinde matematiksel hesaplama (toplama, çıkarma, ortalama alma) yapılması anlamlı mıdır?”

Karşılaştırmalı Örnek Analizi

[ Alan: demirbas_numarasi ]                [ Alan: uye_numarasi ]
- Kurum kodları: '1001', '1002'            - Sistem sıra sayacı: 1, 2, 3...
- İki demirbaşı toplamak anlamsızdır.      - Birer birer artan sıra numarasıdır.
- Aritmetik ortalama alınamaz.             - Sayısal dizi takibi yapılır.
- Başındaki sıfırlar kritiktir ('0042').   - Başında sıfır barındırmaz.
- Harfli koda geçilebilir ('KTP-101').     - Sayısal kimlik üretimidir.
             │                                          │
             ▼                                          ▼
     VARCHAR(20) SEÇİLİR                            INT SEÇİLİR

Sayısal Alanlara INT Vermenin İki Büyük Tehlikesi

  1. Baştaki Sıfırların Kaybı: Telefon numarası (05551112233) veya kurum kodu (0042) INT yapılırsa, sunucu baştaki sıfırları otomatik olarak düşürür (5551112233 ve 42 kalır); veri bozulur.
  2. Biçimlendirme ve Kod Esnekliğinin Yitirilmesi: Kurum kodlama sistemine tire, boşluk veya harf eklediğinde (KTP-2026-0042) INT tipine bu değerler kaydedilemez.

Tasarım İlkesi: Üzerinde aritmetik hesaplama yapılmayacak olan; kimlik, kod, telefon veya etiket işlevi gören nitelikler sayısal değil, metinsel (VARCHAR) tanımlanmalıdır.

Çalışma Alanını Açmak: Şema Oluşturma ve Etkin Kılma

Şema (Veritabanı) Çatısı Neden Zorunludur?

  • Tablolar sunucu boşluğunda kendi başına açılamaz; mutlaka mantıksal bir veritabanı (şema) çatısı altında yer almalıdır.

1. Şemayı Oluşturmak: CREATE DATABASE

CREATE DATABASE IF NOT EXISTS kutuphane;
  • IF NOT EXISTS Mekanizması: kutuphane adında bir veritabanı sunucuda zaten varsa komut hata vermez ve yürütmeyi durdurmaz; nesne yoksa oluşturur, varsa mevcut yapıya dokunmadan geçer.
  • Betiklerin hata vermeden tekrar tekrar çalıştırılabilmesini (idempotency) garanti eder.

2. Şemayı Etkin Kılmak: USE

USE kutuphane;
  • Bir MySQL sunucusunda onlarca bağımsız veritabanı bulunabilir.
  • USE komutu, bundan sonra gönderilecek komutların hangi veritabanı çatısı altında yürütüleceğini oturum düzeyinde kilitler.

Etkin Şema Seçilmezse Ne Olur?

ERROR 1046 (3D000): No database selected
  • Hatanın Analizi: Sunucu tablo yapısında veya SQL sözdiziminde bir hata bulmamıştır; yalnızca tablonun hangi veritabanı çatısı altına yerleştirileceğini bilemediği için işlemi durdurmuştur.

Tek Tablo Yapısını Kurmak: Sütunlar ve Kısıtlar

CREATE TABLE Genel Sözdizim İskeleti

CREATE TABLE tablo_adi (
    sutun_adi veri_tipi sutun_kisiti,
    ...
    tablo_kisitlari
);

Kısıtlar (Constraints) Ne İşe Yarar?

  • Tabloya yalnızca veri tipi tanımlamak yetmez; iş kuralını güvenceye alan kurallar da eklenir.
  • Kısıtlar, geçersiz verilerin veritabanına girmesini donanım ve yazılım düzeyinde engelleyen mekanik denetim bekçileridir.

Temel Sütun Kısıtları

  • NOT NULL: Bir sütunun boş (tanımsız) bırakılmasını kesin olarak yasaklar. Veri girişi sırasında geçerli bir değer verilmezse sunucu ekleme işlemini reddeder.
  • UNIQUE: Sütundaki değerlerin tüm tablo boyunca benzersiz olmasını şart koşar. İki farklı satır aynı değeri taşıyamaz.
  • DEFAULT: Satır eklenirken değer belirtilmemişse sunucunun otomatik atayacağı varsayılan değeri belirler.
    • Örnek: kayit_tarihi DATE DEFAULT (CURRENT_DATE) (Parantez kullanımı zorunludur ve fonksiyonel varsayılan değer mekanizması MySQL 8.0.13+ gerektirir).
  • AUTO_INCREMENT: MySQL’e özgü sayaç mekanizmasıdır. Yeni satır eklendiğinde değeri otomatik olarak bir önceki değerin bir fazlası olacak şekilde üretir.

NULL Kavramı: Sıfır veya Boş Metinden Farkı Nedir?

NULL Neyi İfade Eder?

  • Sayı doğrusundaki sıfır (0) sayısı değildir.
  • Bellekte tanımlı sıfır uzunluklu boş metin ('') değildir.
  • NULL: Değerin “bilinmediği”, “henüz girilmediği” veya “bu kayıt için uygulanamaz olduğu” anlamına gelen bir tanımsızlık durumudur.

Karşılaştırma Matrisi

Kavram Tür Anlamı Mantıksal ve Aritmetik Durum
Sıfır (0) Sayısal Kesin bir büyüklük (miktar yokluğu) Değer tanımlıdır; matematiksel işlemlere normal biçimde girer.
Boş Metin ('') Karakter Bilinen, tanımlı boş karakter dizisi Değer tanımlıdır; uzunluğu 0 olan bir metindir.
NULL Tanımsız Bilinmeyen / Henüz gerçekleşmemiş Değer tanımsızdır; herhangi bir aritmetik işlemde sonuç yine NULL üretir.

İş Kuralı Yansıması

  • Kütüphaneye kaydolan bir üyenin adı ve soyadı mutlaka bilinmek zorundadır.
  • Bu nedenle ad_soyad alanı NOT NULL tanımlanır:
ad_soyad VARCHAR(100) NOT NULL
  • Adı bilinmeyen bir kişi veritabanına kaydedilemez; sunucu işlemi anında reddeder.

Birincil Tablomuz: uye Tablosunun Oluşturulması

Senaryonun İlk Bağımsız Tablosu

  • Kütüphanemizin üye varlığını fiziksel tabloya dönüştüren DDL komutunu yazalım:
CREATE TABLE uye (
    uye_numarasi INT AUTO_INCREMENT,
    ad_soyad VARCHAR(100) NOT NULL,
    eposta VARCHAR(100) UNIQUE,
    kayit_tarihi DATE DEFAULT (CURRENT_DATE),
    PRIMARY KEY (uye_numarasi)
);

Kod ile İş Kuralı Eşleşmesi

uye_numarasi INT AUTO_INCREMENT  ──> Otomatik artan tamsayı sayaç (1, 2, 3...)
ad_soyad VARCHAR(100) NOT NULL   ──> İsimsiz üye kaydedilemez (Zorunlu alan)
eposta VARCHAR(100) UNIQUE       ──> İki üyeye aynı e-posta atanamaz (Tekillik)
kayit_tarihi DATE DEFAULT (...)  ──> Değer girilmezse günün takvim tarihi basılır
PRIMARY KEY (uye_numarasi)       ──> Tablonun tekil kimlik omurgası ilan edilir
  • PRIMARY KEY (uye_numarasi): Tablo kısıtı olarak tanımlanmıştır; uye_numarasi sütununun hem tekil olduğunu hem de asla NULL alamayacağını sunucuya bildirir.

İkinci Bağımsız Tablomuz: kitap Tablosunun Oluşturulması

İkinci Varlığımız: kitap

  • Modelimizdeki kitap varlığını temsil eden fiziksel tabloyu kuralım.
  • Bu tabloda birincil anahtar otomatik artan bir sayaç değil; kurumun belirlediği metinsel demirbaş kodudur.
CREATE TABLE kitap (
    demirbas_numarasi VARCHAR(20) NOT NULL,
    baslik VARCHAR(200) NOT NULL,
    yazar VARCHAR(100),
    PRIMARY KEY (demirbas_numarasi)
);

Kod ile İş Kuralı Eşleşmesi

  • demirbas_numarasi VARCHAR(20) NOT NULL: Kurumun fiziki kitaplara yapıştırdığı etiket kodu (KTP-101). Açıkça NOT NULL belirtilmiştir.
  • baslik VARCHAR(200) NOT NULL: Başlığı olmayan bir kitap kütüphaneye kaydedilemez; zorunlu alandır.
  • yazar VARCHAR(100): Bu sütunda bilerek NOT NULL kullanılmamıştır. Anonim veya derleme eserlerde yazar bilgisi bilinmeyebilir; yazar hücresinin NULL kalmasına izin verilir.
  • PRIMARY KEY (demirbas_numarasi): Sayaç mekanizması olmaksızın metinsel bir sütunun tablonun birincil anahtarı olabileceğini somutlaştırır.

AUTO_INCREMENT ile Birincil Anahtar Aynı Şey midir?

Yaygın Bir Kavram Yanılgısı

  • AUTO_INCREMENT özelliğinin bir sütunu kendiliğinden birincil anahtar yaptığını varsaymak.

İki Kavramın Kesin Mekanik Ayrımı

+------------------------------------+------------------------------------+
|          AUTO_INCREMENT            |            PRIMARY KEY             |
+------------------------------------+------------------------------------+
| Yalnızca bir DEĞER ÜRETİM          | Mantıksal bir KİMLİK KURALIDIR.    |
| mekanizmasıdır.                    |                                    |
| Boş bırakılan alana ardışık sayı   | Satırı diğer tüm satırlardan       |
| yazmaktan ibarettir.               | tekil olarak ayırt eder.           |
| Tek başına tekillik veya anahtar   | Kesinlikle boş (NULL) değer        |
| garantisi taşımaz.                 | kabul etmez.                       |
+------------------------------------+------------------------------------+

Mekanik Kanıt

  • Bir sütun AUTO_INCREMENT olmadan da birincil anahtar olabilir: kitap tablosundaki demirbas_numarasi sütununda hiçbir sayaç yoktur; değerler dış dünyadan gelir (KTP-101), buna rağmen tablonun geçerli birincil anahtarıdır.
  • MySQL Kuralları:
    • Bir tabloda en fazla bir adet AUTO_INCREMENT sütun bulunabilir.
    • Bu sütunun mutlaka bir anahtar veya indeks kapsamında tanımlanması zorunludur.
  • Sonuç: Otomatik sayaç birincil anahtar olmanın nedeni değil; yalnızca tamsayı kimlik üretimini kolaylaştıran bir araçtır.

UNIQUE ile PRIMARY KEY Arasındaki Fark Nedir?

İki Kısıtın Ortak Noktası

  • Hem PRIMARY KEY hem de UNIQUE kısıtları verilerin tekilliğini denetler; sütunda mükerrer kayıt bulunmasını engeller.

İki Kritik Yapısal Fark

1. Sayı Sınırı:
   - Bir tabloda YALNIZCA BİR ADET PRIMARY KEY tanımlanabilir.
   - Aynı tabloda BİRDEN ÇOK sütun bağımsız olarak UNIQUE kısıtı alabilir.
   (Örnek: uye tablosunda PRIMARY KEY uye_numarasi iken; eposta alanı da UNIQUE'tir.)

2. NULL Değer Kabulü:
   - PRIMARY KEY sütunları kesinlikle NULL kabul etmez (örtük NOT NULL kuralı).
   - UNIQUE sütunlar (açıkça NOT NULL yazılmadıkça) NULL değer kabul edebilir.

InnoDB Depolama Motorunda UNIQUE ve NULL Davranışı

  • MySQL InnoDB motorunda UNIQUE olarak tanımlı bir sütuna birden fazla satırda NULL yazılabilir.
  • Gerekçe: İlişkisel teoride her NULL, “bilinmeyen” ayrı bir durum kabul edilir ve iki bilinmeyen birbirine eşit sayılamaz.

E-R Dönüşümündeki Rolü

  • Varlık-İlişki modelindeki 1:1 ilişkilerin fiziksel şemaya dönüştürülmesinde anahtar rol oynar.
  • 1:1 ilişkide yabancı anahtar alanına tekillik şartı koymak için UNIQUE kısıtı kullanılır.

İlişkiyi Koda Dökmek: Yabancı Anahtar ve odunc Tablosu

N:M İlişkiden İki 1:N İlişkiye Geçiş

  • E-R modelleme aşamasında üyeler ile kitaplar arasındaki N:M ödünç ilişkisini iki adet 1:N ilişkiye ayırmıştık.
  • Araya odunc adında bir bağlantı tablosu yerleştirdik.

odunc Bağlantı Tablosunun DDL Komutu

CREATE TABLE odunc (
    odunc_id INT AUTO_INCREMENT,
    uye_numarasi INT NOT NULL,
    demirbas_numarasi VARCHAR(20) NOT NULL,
    alis_tarihi DATE NOT NULL,
    iade_tarihi DATE,
    PRIMARY KEY (odunc_id),
    CONSTRAINT fk_odunc_uye FOREIGN KEY (uye_numarasi) REFERENCES uye (uye_numarasi),
    CONSTRAINT fk_odunc_kitap FOREIGN KEY (demirbas_numarasi) REFERENCES kitap (demirbas_numarasi)
);

Tablodaki Kritik Kararların Analizi

  • odunc_id: Her ödünç hareketini tekil olarak ayırt eden bağımsız yapay birincil anahtardır.
  • alis_tarihi DATE NOT NULL: Ödünç alma anında kitabın teslim tarihi zorunludur.
  • iade_tarihi DATE: Bilerek NOT NULL yapılmamıştır. Kitap alındığı anda henüz iade edilmemiştir; teslim tarihi bilinmez. Kitap teslim edilene kadar hücrede NULL değeri duracaktır.
  • CONSTRAINT ... FOREIGN KEY ... REFERENCES: Referans bütünlüğünü fiziksel kurala bağlar; girilen anahtarın ana tabloda var olmasını şart koşar.

Fiziksel Şema ve Yabancı Anahtar Köprüleri

+------------------------------------+       +------------------------------------+
|                uye                 |       |               kitap                |
+------------------------------------+       +------------------------------------+
| PK  uye_numarasi : INT (AI)        |       | PK  demirbas_numarasi: VARCHAR(20) |
|     ad_soyad     : VARCHAR(100) NN |       |     baslik           : VARCHAR(200)|
|     eposta       : VARCHAR(100) UQ |       |     yazar            : VARCHAR(100)|
|     kayit_tarihi : DATE (DF:CURDATE)|      +------------------------------------+
+------------------------------------+                         ▲
                  ▲                                            │
                  │ [REFERENCES]                               │ [REFERENCES]
                  │                                            │
+-----------------┴────────────────────────────────────────────┴------------------+
|                                      odunc                                      |
+---------------------------------------------------------------------------------+
| PK  odunc_id          : INT (AUTO_INCREMENT)                                    |
| FK  uye_numarasi      : INT NOT NULL ────────────────────────┘                  |
| FK  demirbas_numarasi : VARCHAR(20) NOT NULL ───────────────────────────────────┘
|     alis_tarihi       : DATE NOT NULL                                           |
|     iade_tarihi       : DATE (NULL kabul eder)                                  |
+---------------------------------------------------------------------------------+

Veri Tipi Uyumu Zorunluluğu

  • odunc.uye_numarasi (INT) ile uye.uye_numarasi (INT) veri tipi tam eşleşmelidir.
  • odunc.demirbas_numarasi (VARCHAR(20)) ile kitap.demirbas_numarasi (VARCHAR(20)) birebir aynı tip ve uzunlukta olmalıdır.
  • Tip veya boyut uyuşmazlığı durumunda MySQL InnoDB kısıt motoru hata üretir (ERROR 3780 / 1215).

Tablolar Hangi Sırayla Oluşturulmalıdır?

Komutlar Rastgele Sırada Çalıştırılabilir mi?

  • DDL betikleri hazırlanırken komutların yazılış sırası rastgele belirlenemez.
  • FOREIGN KEY kısıtı, hedef tablonun ve hedef sütunun veritabanında zaten var olmasını şart koşar.

Hatalı Sıra Denemesi: odunc Tablosunu İlk Sırada Çalıştırmak

ERROR 1824 (HY000): Failed to open the referenced table 'uye'
  • Hatanın Mekanik Sebebi: MySQL sunucusu REFERENCES uye (uye_numarasi) satırına geldiğinde katalogda uye adında bir tablo arar. Tabloyu bulamadığı anda işlemi derhal durdurur.
HATALI SIRA:                                 DOĞRU SIRA:
┌───────────────────────────────┐            ┌────────────────────────────────────────┐
│ 1. Adım: odunc oluşturulur    │            │ 1. Adım: uye ve kitap tabloları        │
│    (REFERENCES uye)           │            │    oluşturulur (Bağımsız ana tablolar) │
│               │               │            │    [BAŞARILI: Tablolar katalogda]      │
│               ▼               │            └───────────────────┬────────────────────┘
│ [ ERROR 1824: Failed to open  │                                │
│   the referenced table 'uye' ]│                                ▼
└───────────────────────────────┘            ┌────────────────────────────────────────┐
                                             │ 2. Adım: odunc tablosu oluşturulur     │
                                             │    (Bağımlı çocuk tablo)               │
                                             │    [BAŞARILI: Referanslar bağlandı]    │
                                             └────────────────────────────────────────┘

Kesin İnşa Kuralı: Referans verilen (ana / parent) tablolar, referans veren (bağımlı / child) tablolardan önce oluşturulmalıdır.

Doğrulayalım: Tablo Sütun Yapısını İnceleme (DESCRIBE)

Şema Yapısını Doğrulama: DESCRIBE

  • DDL komutları çalıştırıldıktan sonra tabloların hedeflenen sütun ve kısıt düzeninde kurulup kurulmadığı bağımsız olarak incelenir:
DESCRIBE uye;

Sunucunun Döndürdüğü Katalog Çıktısı

Field Type Null Key Default Extra
uye_numarasi int NO PRI NULL auto_increment
ad_soyad varchar(100) NO NULL
eposta varchar(100) YES UNI NULL
kayit_tarihi date YES curdate() DEFAULT_GENERATED

Çıktının Sütun Sütun Analizi

  • Null: uye_numarasi ve ad_soyad alanlarında NO yazar; bu alanların boş bırakılamayacağı (NOT NULL) doğrulanır.
  • Key: uye_numarasi sütununda PRI (PRIMARY KEY), eposta sütununda UNI (UNIQUE) işareti yer alır; tekillik kurallarının kataloğa işlendiği görülür.
  • Extra: uye_numarasi alanında auto_increment ibaresi yer alır; sayacın devrede olduğu doğrulanır.
  • Default & Extra: kayit_tarihi alanında curdate() ve DEFAULT_GENERATED ibareleri yer alır; MySQL 8.0.13+ fonksiyonel varsayılan değer mekanizmasının başarıyla çalıştığı kanıtlanır.

Doğrulayalım: Yabancı Anahtarlar ve Tam Tanım (SHOW CREATE TABLE)

Bağlantı Tablosunu İnceleme: DESCRIBE odunc

DESCRIBE odunc;
Field Type Null Key Default Extra
odunc_id int NO PRI NULL auto_increment
uye_numarasi int NO MUL NULL
demirbas_numarasi varchar(20) NO MUL NULL
alis_tarihi date NO NULL
iade_tarihi date YES NULL

Çıktıdaki Kritik İşaretler

  • Key = MUL: uye_numarasi ve demirbas_numarasi alanlarında MUL (multiple) işareti belirir. Bu sütunların başka tablolara bağlanan yabancı anahtarlar olduğunu veya tekil olmayan indeksler taşıdığını gösterir.
  • Null = YES: iade_tarihi sütununda boş bırakılmaya (kitap teslim edilene kadar NULL kalmasına) izin verildiği doğrulanır.

Tam Tanımı Doğrulama: SHOW CREATE TABLE

SHOW CREATE TABLE odunc;
  • Tablonun sunucu hafızasında saklanan eksiksiz DDL ifadesini döndürür.
  • Kısıt adlarının (CONSTRAINT fk_odunc_uye), InnoDB motorunun (ENGINE=InnoDB) ve karakter setinin eksiksiz tanımlandığını belgeler.

Doğrulayalım: Kısıtın Çalıştığını Kasıtlı Hata ile Test Etmek

Kısıtlar Süs mü, Yoksa Aktif Bekçi mi?

  • Tanımladığımız FOREIGN KEY kısıtının gerçekten çalışıp çalışmadığını test etmek için kasıtlı olarak kural dışı bir kayıt ekleme denemesi yapalım.

Kasıtlı Hata Senaryosu

  • Veritabanında henüz hiçbir üye kaydı bulunmamaktadır (uye tablosu tamamen boştur).
  • odunc tablosuna sistemde var olmayan 999 numaralı üye için ödünç kaydı eklemeyi deneyelim:
INSERT INTO odunc (uye_numarasi, demirbas_numarasi, alis_tarihi)
VALUES (999, 'KTP-101', '2026-10-01');

Sunucunun Döndürdüğü Hata İletisi

ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails
(`kutuphane`.`odunc`, CONSTRAINT `fk_odunc_uye` FOREIGN KEY (`uye_numarasi`) REFERENCES `uye` (`uye_numarasi`))

Hata İletisinin 4 Aşamalı Anatomisi

1. Cannot add or update a child row  ──> Bağımlı (çocuk) tabloya satır eklenemez / güncellenemez.
2. a foreign key constraint fails    ──> Yabancı anahtar kısıtı ihlal edilmiştir.
3. CONSTRAINT fk_odunc_uye           ──> İhlal edilen kısıtın açık adıdır.
4. REFERENCES uye (uye_numarasi)     ──> uye tablosunda 999 numaralı bir anahtar bulunamamıştır.

Kanıtlanan Mekanizma: Kısıtlar kağıt üzerinde kalan birer etiket değildir; her INSERT ve UPDATE işleminde sunucu tarafından aralıksız denetlenen aktif güvenlik bariyerleridir.

Değişen Gereksinimler: ALTER TABLE ile Tabloyu Genişletme

Değişen Kurumsal İhtiyaç

  • Veritabanı kurulup canlı kullanıma açıldıktan sonra kütüphane yönetiminden yeni bir talep geldi:
  • Görevliler ödünç alma işlemine özel durum notu eklemek istemektedir (“Kitabın 12. sayfasında çizikler var” gibi).

Yanlış Refleks vs Doğru Mekanizma

YANLIŞ VE YIKICI YOL:                              DOĞRU VE KORUYUCU YOL:
┌───────────────────────────────────────┐          ┌──────────────────────────────────────┐
│ DROP TABLE odunc;                     │          │ ALTER TABLE odunc                    │
│ -- Sütunu ekleyip baştan oluştur        │          │ ADD notlar VARCHAR(255);             │
│                                       │          │                                      │
│ SONUÇ: O güne kadar kaydedilmiş tüm   │          │ SONUÇ: Mevcut hiçbir ödünç verisi    │
│ ödünç geçmişi kalıcı olarak yok olur    │          │ silinmez; yeni sütun tabloya eklenir │
└───────────────────────────────────────┘          └──────────────────────────────────────┘

Şemayı Genişletmek: ALTER TABLE Komutu

ALTER TABLE odunc ADD notlar VARCHAR(255);

DESCRIBE odunc ile Değişikliği Doğrulama

Field Type Null Key Default Extra
odunc_id int NO PRI NULL auto_increment
uye_numarasi int NO MUL NULL
demirbas_numarasi varchar(20) NO MUL NULL
alis_tarihi date NO NULL
iade_tarihi date YES NULL
notlar varchar(255) YES NULL
  • Null = YES: Zorunluluk belirtilmediği için var olan eski kayıtlar bozulmaz; önceden eklenmiş satırlarda bu alan güvenle NULL kalır.

Kaynak Notu: Standartlar ve Tasarım Çıkarımları

MySQL 8.0 Referans Standartları

  • Bu sunumdaki DDL komutları, temel veri tipleri ve InnoDB kısıt motoru davranışları güncel MySQL 8.0 standartlarına dayanır.
  • DATE DEFAULT (CURRENT_DATE) fonksiyonel varsayılan değer mekanizması, parantezli sözdizimi ile MySQL 8.0.13 ve üzeri sürümleri gerektirir.
  • Eski Access / Jet SQL diyalektine özgü tipler (NUMBER, MEMO), tarih sınırlayıcıları (#tarih#) ve büyük harfli tanımlayıcılar dersimizin MySQL standardı ve Türkçe tanımlayıcı politikası gereği bilinçli olarak dışarıda bırakılmıştır.

Kaynaktan Devralınan İki Kalıcı Tasarım Mantığı

1. Birincil Anahtar Tasarım Kararıdır:
   - Birincil anahtarın adı ve tipi mutlak bir kural değil; kurumun gereksinimlerine göre
     şekillenen bir mühendislik kararıdır.
   - Sayısal sayaç (uye_numarasi INT) ile metinsel doğal kod (demirbas_numarasi VARCHAR)
     ihtiyaca göre seçilir.

2. Şemalar Artımlı Genişletilir:
   - Değişen kurumsal ihtiyaçlar çalışan sisteme yıkıcı silmelerle değil;
     veriyi koruyan artımlı şema dönüşümleriyle (ALTER TABLE) yansıtılır.

Sık Yapılan Hatalar: DDL ve Tablo Tasarımı Yanılgıları (1/2)

1. AUTO_INCREMENT Mekanizmasını Birincil Anahtar ile Özdeşleştirmek

  • Yanılgı: PK’nın mutlaka otomatik artan bir sayaç olması gerektiğini düşünmek.
  • Doğrusu: PK’yı belirleyen tekillik ve NOT NULL’dır; metinsel kodlar da (VARCHAR) geçerli PK’dır.

2. Sayısal Karakterler İçeren Her Alana INT Atamak

  • Yanılgı: Rakamlardan oluşan her veriyi matematiksel büyüklük zannetmek.
  • Doğrusu: Aritmetik yapılmayacak kod/kimlik alanları VARCHARdır; INT baştaki sıfırları siler.

3. NULL Değerini Sıfır veya Boş Metin ile Aynı Görmek

  • Yanılgı: NULL’ı sayısal sıfır (0) ya da boş metin ('') sanmak.
  • Doğrusu: NULL “henüz bilinmiyor” demektir; sıfır ve boş metin ise tanımlı değerlerdir.

Sık Yapılan Hatalar: DDL ve Tablo Tasarımı Yanılgıları (2/2)

4. UNIQUE Kısıtının Birincil Anahtar Yerine Geçeceğini Varsaymak

  • Yanılgı: Sütun UNIQUE ise ayrıca PK belirlemeye gerek olmadığını düşünmek.
  • Doğrusu: Tabloda tek bir PRIMARY KEY olur ve asla NULL almaz; UNIQUE alanlar birden çok olabilir ve NULL kabul edebilir.

5. Bağımlı Tabloyu Referans Verdiği Tablodan Önce Oluşturmaya Çalışmak

  • Yanılgı: Tablo oluşturma sırasının rastgele olabileceğini varsaymak.
  • Doğrusu: FOREIGN KEY, hedef tablonun önceden var olmasını şart koşar; önce ana, sonra bağımlı tablo kurulur.

6. Tablo Yapısını Değiştirmek İçin Tabloyu Silip Baştan Oluşturmak

  • Yanılgı: Yeni sütun eklemek için DROP TABLE yoluna gitmek.
  • Doğrusu: DROP TABLE tüm veriyi geri dönüşsüz siler; genişletme ALTER TABLE ile yapılır.