ALTER TABLE ile Tablo Yapısını Değiştirme

Veritabanı yönetiminde en sık karşılaşılan ihtiyaçlardan biri, mevcut tabloların yapısını değiştirmek. Uygulama gereksinimleri değişiyor, yeni özellikler ekleniyor ya da eski tasarım kararları revize edilmek zorunda kalıyor. İşte bu noktada ALTER TABLE komutu devreye giriyor. Bu komut sayesinde sütun ekleyebilir, silebilir, veri tipini değiştirebilir, indeks yönetimi yapabilir ve çok daha fazlasını gerçekleştirebilirsiniz. Bu yazıda MariaDB ve MySQL üzerinde ALTER TABLE komutunu gerçek dünya senaryolarıyla birlikte ele alacağız.

ALTER TABLE Nedir ve Ne Zaman Kullanılır?

ALTER TABLE, var olan bir tablonun yapısını (schema) değiştirmenizi sağlayan DDL (Data Definition Language) komutudur. Dikkat edilmesi gereken kritik nokta şu: Büyük tablolarda ALTER TABLE işlemi ciddi performans sorunlarına yol açabilir. Milyonlarca satır içeren bir tabloda bu komutu çalıştırmadan önce mutlaka planlama yapmalı ve uygun zaman dilimini (bakım penceresi) seçmelisiniz.

ALTER TABLE ile yapabileceğiniz başlıca işlemler:

  • Sütun ekleme ve silme: Yeni alanlar eklemek ya da kullanılmayan alanları kaldırmak
  • Sütun adı ve tip değiştirme: Veri modelini güncellemek
  • Varsayılan değer (DEFAULT) ayarlama: Zorunluluk ve boş değer kurallarını yönetmek
  • İndeks yönetimi: PRIMARY KEY, UNIQUE, INDEX eklemek veya kaldırmak
  • Foreign key (yabancı anahtar) yönetimi: Tablo ilişkilerini düzenlemek
  • Tablonun depolama motorunu değiştirme: MyISAM’dan InnoDB’ye geçiş gibi

Temel Söz Dizimi

ALTER TABLE komutunun genel yapısı oldukça basittir:

ALTER TABLE tablo_adi
    [işlem_türü] [sütun_adı] [veri_tipi] [kısıtlamalar];

Tek bir ALTER TABLE komutuyla birden fazla işlemi aynı anda gerçekleştirebilirsiniz, bu da özellikle büyük tablolarda performans açısından büyük avantaj sağlar. Şimdi her işlem türünü ayrı ayrı inceleyelim.

Sütun Ekleme: ADD COLUMN

Bir tabloya yeni sütun eklemek için ADD COLUMN kullanılır. Yeni sütun varsayılan olarak tablonun en sonuna eklenir, ancak AFTER veya FIRST anahtar kelimeleriyle konumunu belirtebilirsiniz.

-- En sona sütun ekleme
ALTER TABLE kullanicilar
    ADD COLUMN telefon VARCHAR(20) NULL;

-- Belirli bir sütundan sonra ekleme
ALTER TABLE kullanicilar
    ADD COLUMN dogum_tarihi DATE NULL AFTER email;

-- En başa ekleme
ALTER TABLE kullanicilar
    ADD COLUMN uuid CHAR(36) NOT NULL FIRST;

Gerçek dünya senaryosu: Bir e-ticaret platformu düşünün. Başlangıçta siparisler tablosunda kargo takip numarası için alan açmayı unutmuşsunuz. Uygulama canlıya alındıktan sonra bu alanı eklemeniz gerekiyor:

ALTER TABLE siparisler
    ADD COLUMN kargo_takip_no VARCHAR(50) NULL AFTER siparis_durumu,
    ADD COLUMN kargo_firmasi VARCHAR(100) NULL AFTER kargo_takip_no,
    ADD COLUMN kargoya_verilme_tarihi DATETIME NULL AFTER kargo_firmasi;

Dikkat edin, tek bir ALTER TABLE komutuyla üç sütunu aynı anda ekledik. Bu yaklaşım, tablonun yalnızca bir kez kilitlenmesini sağladığı için çok daha verimlidir.

Sütun Silme: DROP COLUMN

Artık kullanılmayan sütunları kaldırmak için DROP COLUMN kullanılır. Bu işlem geri alınamaz, bu yüzden önce yedek almayı ihmal etmeyin.

-- Tek sütun silme
ALTER TABLE kullanicilar
    DROP COLUMN eski_sistem_id;

-- Birden fazla sütun silme
ALTER TABLE urunler
    DROP COLUMN eski_kategori_kodu,
    DROP COLUMN legacy_fiyat,
    DROP COLUMN kullanilmiyor_alan;

Önemli uyarı: Eğer silmek istediğiniz sütun üzerinde bir indeks ya da foreign key kısıtlaması varsa, önce bunları kaldırmanız gerekir. Aksi hâlde MySQL hata verecektir.

-- Önce foreign key'i kaldır, sonra sütunu sil
ALTER TABLE siparis_detaylari
    DROP FOREIGN KEY fk_urun_id,
    DROP COLUMN eski_urun_referans_id;

Sütun Değiştirme: MODIFY ve CHANGE

Mevcut bir sütunun özelliklerini değiştirmek için iki farklı söz dizimi kullanabilirsiniz:

  • MODIFY COLUMN: Sütun adını koruyarak sadece özelliklerini değiştirir
  • CHANGE COLUMN: Hem sütun adını hem de özelliklerini değiştirir
-- VARCHAR(50)'yi VARCHAR(100) yapma (MODIFY ile)
ALTER TABLE kullanicilar
    MODIFY COLUMN ad VARCHAR(100) NOT NULL;

-- Sütun adını değiştirirken tipini de güncelleme (CHANGE ile)
ALTER TABLE urunler
    CHANGE COLUMN urun_fiyat fiyat DECIMAL(10,2) NOT NULL DEFAULT 0.00;

-- NULL kısıtlamasını kaldırma
ALTER TABLE siparisler
    MODIFY COLUMN teslim_adresi TEXT NOT NULL;

Gerçek dünya senaryosu: Bir müşteri yönetim sisteminde telefon numaralarını başta INT olarak tanımlamışsınız (kötü bir karar, biliyoruz). Sonradan uluslararası numaraları da desteklemeniz gerekiyor:

-- Önce mevcut yapıyı kontrol et
DESCRIBE musteriler;

-- INT'ten VARCHAR'a dönüştürme
ALTER TABLE musteriler
    MODIFY COLUMN telefon VARCHAR(20) NULL,
    MODIFY COLUMN faks VARCHAR(20) NULL;

Bu işlemde dikkatli olun: veri tipi değişikliklerinde mevcut veriler dönüştürülmeye çalışılır, eğer dönüşüm mümkün değilse hata alırsınız veya veri kaybı yaşanabilir.

Varsayılan Değer ve NULL Kısıtlamaları

Sütunların varsayılan değerlerini ve NULL kabul edip etmeyeceğini değiştirmek oldukça sık karşılaşılan bir ihtiyaçtır:

-- Varsayılan değer ekleme
ALTER TABLE siparisler
    MODIFY COLUMN siparis_durumu ENUM('beklemede','onaylandi','kargolandi','teslim_edildi')
    NOT NULL DEFAULT 'beklemede';

-- Tarihe otomatik değer atama
ALTER TABLE kayitlar
    MODIFY COLUMN olusturma_tarihi TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    MODIFY COLUMN guncelleme_tarihi TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
    ON UPDATE CURRENT_TIMESTAMP;

İndeks Yönetimi

İndeksler sorgu performansını doğrudan etkiler. ALTER TABLE ile indeks ekleyip kaldırabilirsiniz.

İndeks Ekleme

-- Basit indeks ekleme
ALTER TABLE kullanicilar
    ADD INDEX idx_email (email);

-- Birleşik indeks (composite index)
ALTER TABLE siparisler
    ADD INDEX idx_musteri_tarih (musteri_id, siparis_tarihi);

-- Benzersiz indeks
ALTER TABLE kullanicilar
    ADD UNIQUE INDEX uq_kullanici_adi (kullanici_adi);

-- FULLTEXT indeks (MyISAM veya InnoDB 5.6+)
ALTER TABLE makaleler
    ADD FULLTEXT INDEX ft_icerik (baslik, icerik);

PRIMARY KEY Yönetimi

-- Mevcut primary key'i kaldır ve yenisini ekle
ALTER TABLE eski_tablo
    DROP PRIMARY KEY,
    ADD PRIMARY KEY (yeni_id_sutunu);

-- AUTO_INCREMENT ile birlikte
ALTER TABLE urunler
    MODIFY COLUMN id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    ADD PRIMARY KEY (id);

İndeks Silme

-- İndeks silme
ALTER TABLE kullanicilar
    DROP INDEX idx_email;

-- Foreign key ile birlikte indeks silme
ALTER TABLE siparis_detaylari
    DROP FOREIGN KEY fk_siparis_id,
    DROP INDEX idx_siparis_id;

Foreign Key (Yabancı Anahtar) Yönetimi

Tablolar arası ilişkileri yönetmek için foreign key kısıtlamaları kullanılır:

-- Foreign key ekleme
ALTER TABLE siparisler
    ADD CONSTRAINT fk_musteri_id
    FOREIGN KEY (musteri_id)
    REFERENCES musteriler(id)
    ON DELETE RESTRICT
    ON UPDATE CASCADE;

-- Birden fazla foreign key ekleme
ALTER TABLE siparis_detaylari
    ADD CONSTRAINT fk_sd_siparis
    FOREIGN KEY (siparis_id) REFERENCES siparisler(id) ON DELETE CASCADE,
    ADD CONSTRAINT fk_sd_urun
    FOREIGN KEY (urun_id) REFERENCES urunler(id) ON DELETE RESTRICT;

Gerçek dünya senaryosu: Üretim ortamında foreign key eklerken karşılaşılan en yaygın sorun, mevcut verilerin kısıtlamayı ihlal etmesidir. Önce veri tutarlılığını kontrol edin:

-- Orphan kayıtları bul
SELECT sd.id, sd.siparis_id
FROM siparis_detaylari sd
LEFT JOIN siparisler s ON sd.siparis_id = s.id
WHERE s.id IS NULL;

-- Temizlik sonrası foreign key ekle
ALTER TABLE siparis_detaylari
    ADD CONSTRAINT fk_sd_siparis
    FOREIGN KEY (siparis_id) REFERENCES siparisler(id);

Foreign Key Silme

-- Foreign key adını öğren
SELECT CONSTRAINT_NAME
FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_NAME = 'siparis_detaylari'
AND CONSTRAINT_TYPE = 'FOREIGN KEY';

-- Foreign key kaldır
ALTER TABLE siparis_detaylari
    DROP FOREIGN KEY fk_sd_siparis;

Tablo Motorunu ve Diğer Ayarları Değiştirme

Depolama motorunu değiştirmek, özellikle MyISAM tablolarını InnoDB’ye geçirirken sıkça kullanılan bir işlemdir:

-- Depolama motorunu değiştirme
ALTER TABLE eski_myisam_tablo ENGINE = InnoDB;

-- Karakter setini değiştirme
ALTER TABLE kullanicilar
    CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- AUTO_INCREMENT başlangıç değerini ayarlama
ALTER TABLE siparisler AUTO_INCREMENT = 10000;

-- Hem motor hem karakter seti değiştirme
ALTER TABLE urunler
    ENGINE = InnoDB,
    CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_turkish_ci;

Gerçek dünya senaryosu: Eski bir sistemin veritabanını devralıyorsunuz ve tüm tablolar MyISAM motoruyla oluşturulmuş. Transaction desteği için InnoDB’ye geçmeniz şart. Bunun için toplu işlem yapabilirsiniz:

-- Önce MyISAM tablolarını listele
SELECT TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'veritabani_adi'
AND ENGINE = 'MyISAM';

-- Her tablo için dönüşüm yap (örnek)
ALTER TABLE kullanicilar ENGINE = InnoDB;
ALTER TABLE urunler ENGINE = InnoDB;
ALTER TABLE siparisler ENGINE = InnoDB;

Büyük Tablolarda ALTER TABLE Stratejileri

Milyonlarca satır içeren tablolarda ALTER TABLE işlemi saatlerce sürebilir ve bu süre boyunca tablo kilitlenebilir. Bu durumda bazı stratejiler işinize yarar.

pt-online-schema-change Kullanımı

Percona Toolkit’in pt-osc aracı, tabloyu kilitlemeden yapı değişikliği yapmanızı sağlar:

# Percona Toolkit kurulumu (RHEL/CentOS)
yum install percona-toolkit

# pt-online-schema-change ile ALTER TABLE
pt-online-schema-change 
    --host=localhost 
    --user=root 
    --password=sifre 
    --alter "ADD COLUMN yeni_sutun VARCHAR(100) NULL" 
    D=veritabani,t=buyuk_tablo 
    --execute

gh-ost Kullanımı

GitHub tarafından geliştirilen gh-ost de benzer şekilde çalışır:

# gh-ost ile online schema değişikliği
gh-ost 
    --mysql-host=localhost 
    --mysql-user=root 
    --mysql-password=sifre 
    --database=veritabani 
    --table=buyuk_tablo 
    --alter="ADD COLUMN yeni_alan INT DEFAULT 0" 
    --execute

MariaDB’de Instant ALTER TABLE

MariaDB 10.3.2 ve sonrasında bazı ALTER TABLE işlemleri INSTANT algoritmasıyla anında gerçekleştirilebilir:

-- INSTANT algoritması ile sütun ekleme (çok hızlı)
ALTER TABLE buyuk_tablo
    ADD COLUMN ekstra_bilgi TEXT NULL,
    ALGORITHM=INSTANT;

-- INPLACE algoritması (tablo kilidini azaltır)
ALTER TABLE buyuk_tablo
    ADD INDEX idx_tarih (olusturma_tarihi),
    ALGORITHM=INPLACE,
    LOCK=NONE;

Pratik Bir Senaryo: E-Ticaret Veritabanı Güncellemesi

Gerçek bir örnek üzerinden gidelim. Bir e-ticaret sitesinin urunler tablosuna yeni özellikler eklemeniz, bazı eski alanları kaldırmanız ve indeksler oluşturmanız gerekiyor:

-- Mevcut yapıyı incele
DESCRIBE urunler;
SHOW INDEX FROM urunler;

-- Kapsamlı bir ALTER TABLE işlemi
ALTER TABLE urunler
    -- Eski alanları kaldır
    DROP COLUMN eski_kategori_adi,
    DROP COLUMN legacy_stok_kodu,

    -- Yeni alanlar ekle
    ADD COLUMN marka_id INT UNSIGNED NULL AFTER kategori_id,
    ADD COLUMN vergi_orani DECIMAL(5,2) NOT NULL DEFAULT 18.00 AFTER fiyat,
    ADD COLUMN stok_takip TINYINT(1) NOT NULL DEFAULT 1,
    ADD COLUMN meta_baslik VARCHAR(160) NULL,
    ADD COLUMN meta_aciklama VARCHAR(320) NULL,

    -- Mevcut alanları güncelle
    MODIFY COLUMN fiyat DECIMAL(10,2) NOT NULL DEFAULT 0.00,
    MODIFY COLUMN stok_miktari INT NOT NULL DEFAULT 0,

    -- İndeksler
    ADD INDEX idx_marka (marka_id),
    ADD INDEX idx_fiyat (fiyat),
    ADD FULLTEXT INDEX ft_urun_ara (urun_adi, aciklama),

    -- Foreign key
    ADD CONSTRAINT fk_urun_marka
    FOREIGN KEY (marka_id) REFERENCES markalar(id)
    ON DELETE SET NULL ON UPDATE CASCADE;

Dikkat Edilmesi Gereken Durumlar

ALTER TABLE kullanırken bazı noktalar kritik önem taşır:

  • Her zaman yedek alın: İşlem öncesi mysqldump ile tam yedek almak şart
  • Test ortamında deneyin: Üretim sunucusuna geçmeden önce mutlaka test edin
  • Trafik saatlerini gözetin: Yoğun saatlerde büyük tablolarda ALTER TABLE yapmaktan kaçının
  • Disk alanını kontrol edin: ALTER TABLE işlemi geçici olarak disk alanına ihtiyaç duyabilir
  • Replication etkisini düşünün: Master-slave yapıda ALTER TABLE slave’leri de etkiler
  • ENUM değişikliklerine dikkat: ENUM’a yeni değer eklemek MySQL 5.6+ ve MariaDB’de hızlıdır, ancak mevcut değerlerin sırası değişirse sorun çıkabilir
-- İşlem öncesi yedek almak
mysqldump -u root -p veritabani urunler > urunler_yedek_$(date +%Y%m%d).sql

-- Tablo boyutunu kontrol et
SELECT
    TABLE_NAME,
    ROUND(((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024), 2) AS 'Boyut (MB)',
    TABLE_ROWS
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'veritabani_adi'
AND TABLE_NAME = 'urunler';

Sonuç

ALTER TABLE komutu, veritabanı yöneticisinin araç kutusundaki en güçlü araçlardan biridir. Sütun ekleme ve silmeden indeks yönetimine, foreign key düzenlemesinden motor değişikliğine kadar pek çok işlemi tek bir komutla gerçekleştirebilirsiniz.

Ancak bu güç, sorumluluk gerektirir. Özellikle üretim ortamlarında ve büyük tablolarda dikkatli planlama yapmadan yapılan ALTER TABLE işlemleri uygulama kesintilerine ya da veri kayıplarına yol açabilir. pt-online-schema-change veya gh-ost gibi araçlar, sıfır veya minimum kesinti süreleriyle bu işlemleri gerçekleştirmenizi sağlar.

Tek bir ALTER TABLE komutunda birden fazla değişiklik yapmak, tablonun yalnızca bir kez yeniden oluşturulmasını sağladığı için her zaman tercih edilmesi gereken yaklaşımdır. Yedek almayı ihmal etmeyin, test ortamınızı etkin kullanın ve büyük değişiklikler için mutlaka bakım penceresi planlayın.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir