MariaDB'de bir veritabanını CREATE DATABASE ad;, içindeki tabloyu ise CREATE TABLE ad (sütun tip seçenekler, ...); ile oluşturursunuz. Aynı adlı nesne zaten varsa hata almamak için IF NOT EXISTS, var olanı silip yeniden kurmak için OR REPLACE eklenir; oluşan yapıyı SHOW CREATE TABLE ya da DESCRIBE ile görür, gerektiğinde DROP TABLE ve DROP DATABASE ile kaldırırsınız.

Bu yazı, resmî MariaDB Server belgelerindeki CREATE DATABASE, CREATE TABLE, SHOW CREATE TABLE, DROP TABLE ve DROP DATABASE sayfalarına dayanır. Sütun tiplerinin ayrıntısı, sonradan yapı değiştirme ve indeks konuları ayrı yazılarda; burada bir şemayı sıfırdan güvenli biçimde kurmanın adımlarına odaklanıyoruz. Serinin tamamı için MariaDB öğrenme rehberine, MariaDB'nin ne olduğuna dair genel bilgi için MariaDB nedir yazısına bakabilirsiniz.

Başlamadan önce: bağlanmak ve veritabanı seçmek

SQL komutlarını çalıştırmak için bir istemciyle sunucuya bağlanmanız gerekir. Varsayılan komut satırı istemcisi mariadb programıdır. -u ile MariaDB kullanıcı adını (işletim sistemi kullanıcısı değil), -p ile parola sorulmasını, -h ile sunucu adresini verirsiniz. İstemcinin diğer seçenekleri MariaDB komut satırı istemcisi yazısında anlatılıyor.

bash
mariadb -u root -p -h localhost

Bağlandıktan sonra Basics Guide'daki gibi önce veritabanını oluşturup USE ile varsayılan veritabanı yaparsınız. Sonraki tablo komutları, başka bir veritabanı adı belirtmediğiniz sürece bu veritabanında çalışır.

sql
CREATE DATABASE bookstore;
USE bookstore;

CREATE DATABASE sözdizimi ve seçenekleri

CREATE DATABASE sözdizimi ve seçenekleri: IF NOT EXISTS, OR REPLACE, CHARACTER SET ve COLLATE, COMMENT

Belgedeki sözdizimi kısadır: CREATE [OR REPLACE] {DATABASE | SCHEMA} [IF NOT EXISTS] db_name ve ardından isteğe bağlı karakter seti, collation ve yorum tanımları. CREATE SCHEMA, CREATE DATABASE ile aynı anlama gelir. Komutu çalıştırabilmek için ilgili veritabanında CREATE yetkisine sahip olmanız gerekir; yetkiler GRANT ve REVOKE yazısında ele alınıyor.

  • IF NOT EXISTS: Veritabanı zaten varsa hata yerine bir uyarı (note) üretilir. Kurulum betiklerini tekrar tekrar çalıştırırken işinize yarar.
  • OR REPLACE: Belge bunu DROP DATABASE IF EXISTS ardından CREATE DATABASE kısayolu olarak tanımlar. Yani var olan veritabanı, içindeki tüm tablolarla birlikte silinir.
  • CHARACTER SET ve COLLATE: Veritabanının varsayılan karakter setini ve sıralama kuralını belirler. Bu ayarlar, kendi tanımı olmayan yeni tablolara aktarılır. Türkçe metinler için seçim karakter seti ve collation yazısında anlatılıyor.
  • COMMENT: En fazla 1024 bayt olabilir; aşılırsa 4144 kodlu hata veya uyarı döner. Yorum hem db.opt dosyasına hem de information_schema.schemata tablosuna yazılır.

Belgedeki örnek, aynı komutu farklı biçimlerde art arda çalıştırınca ne olduğunu gösteriyor. İkinci denemede 1007 hatası alınıyor, IF NOT EXISTS ile aynı durum yalnızca bir uyarıya dönüşüyor:

sql
CREATE DATABASE db1;
Query OK, 1 row affected (0.18 sec)

CREATE DATABASE db1;
ERROR 1007 (HY000): Can't create database 'db1'; database exists

CREATE OR REPLACE DATABASE db1;
Query OK, 2 rows affected (0.00 sec)

CREATE DATABASE IF NOT EXISTS db1;
Query OK, 1 row affected, 1 warning (0.01 sec)

SHOW WARNINGS;
+-------+------+----------------------------------------------+
| Level | Code | Message                                      |
+-------+------+----------------------------------------------+
| Note  | 1007 | Can't create database 'db1'; database exists |
+-------+------+----------------------------------------------+

Yorum eklemek için belge şu biçimi verir:

sql
CREATE DATABASE presentations COMMENT 'Presentations for conferences';

Ad seçerken dikkat edilecek kurallar

Veritabanı, tablo, sütun ve indeks adları belgede "identifier" olarak geçer ve en fazla 64 karakter olabilir. Yalnızca harf, rakam, $ ve alt çizgi içeren, ayrılmış sözcük olmayan adları tırnaksız yazabilirsiniz; boşluk veya özel karakter içeren adları ters tırnakla (`ad`) çevirmeniz gerekir. Tamamı rakamdan oluşan adlar ancak tırnak içinde kullanılabilir, adlar boşlukla bitemez. Bir rakamla başlayıp ardından e gelen adlar sayı gibi okunabileceği için belge bunlardan kaçınmayı önerir.

Basics Guide önemli bir platform farkına da dikkat çeker: veritabanı ve tablo adları dizin ve dosyalara karşılık geldiği için Linux'ta büyük ve küçük harfe duyarlıdır, Windows'ta genellikle duyarlı değildir. Sütun adları ise harf büyüklüğüne duyarsızdır. Uygulamanızı farklı sistemlere taşıyacaksanız tablo ve sütun adlarını baştan küçük harfle yazmak, belgede de yaygın bir alışkanlık olarak anılır.

CREATE TABLE ile ilk tablo

CREATE TABLE ile ilk tablo: NULL / NOT NULL, DEFAULT, AUTO_INCREMENT, PRIMARY KEY

En temel biçimde CREATE TABLE, tablo adının ardından parantez içinde sütun, indeks ve kısıt tanımlarını alır. Her sütun bir ad ve bir veri tipiyle başlar, ardından isteğe bağlı seçenekler gelir. Basics Guide'daki kitap tablosu iyi bir başlangıç örneğidir:

sql
CREATE TABLE books (
    isbn CHAR(20) PRIMARY KEY,
    title VARCHAR(50),
    author_id INT,
    publisher_id INT,
    year_pub CHAR(4),
    description TEXT
);

Burada isbn sabit uzunluklu bir metin ve birincil anahtar, title değişken uzunluklu metin, author_id ile publisher_id tamsayı, description ise uzun metin için TEXT tipindedir. Hangi tipin ne zaman seçileceği MariaDB veri tipleri yazısının konusu. Oluşan yapıyı DESCRIBE ile görebilirsiniz; belge şu çıktıyı gösterir:

sql
DESCRIBE books;
+--------------+-------------+------+-----+---------+-------+
| Field        | Type        | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| isbn         | char(20)    | NO   | PRI | NULL    |       |
| title        | varchar(50) | YES  |     | NULL    |       |
| author_id    | int(11)     | YES  |     | NULL    |       |
| publisher_id | int(11)     | YES  |     | NULL    |       |
| year_pub     | char(4)     | YES  |     | NULL    |       |
| description  | text        | YES  |     | NULL    |       |
+--------------+-------------+------+-----+---------+-------+

Çıktıda dikkat edilecek nokta, birincil anahtar sütununun Null değerinin NO olmasıdır: belgeye göre birincil anahtar dolaylı olarak NOT NULL sayılır. Diğer sütunlar için açıkça bir şey söylenmediğinden NULL değere izin verilir.

Sütun seçenekleri

  • NULL / NOT NULL: Varsayılan olarak sütunlar NULL kabul eder. Zorunlu alanlar için NOT NULL yazın.
  • DEFAULT: Satır eklenirken değer verilmezse kullanılacak değerdir. DEFAULT yazmazsanız ve sütun NOT NULL, AUTO_INCREMENT ya da TIMESTAMP değilse, sunucu açık bir DEFAULT NULL ekler. İfadeler parantez içinde verilir ve daha önce tanımlanmış sütunlara başvurabilir; saklı fonksiyon ve alt sorgu kullanılamaz.
  • AUTO_INCREMENT: Yalnızca tamsayı tipli bir sütunda kullanılabilir, sütun bir anahtar olmalıdır ve tabloda en fazla bir tane bulunabilir. Bu tür sütun dolaylı olarak NOT NULL olur.
  • PRIMARY KEY: Tabloda en fazla bir tane olabilen, özel bir benzersiz anahtardır.
  • UNIQUE: Sütundaki değerlerin birbirinden farklı olmasını ister. Sütun NOT NULL değilse birden fazla satırda NULL bulunabilir.
  • COMMENT: Sütun yorumu en fazla 1024 karakterdir ve SHOW FULL COLUMNS ile görülür.

Belge, DEFAULT içinde ifade kullanımına şu örneği verir. İkinci sütun ilkine başvurur, expires sütunu ise bir yıl sonrasını hesaplar:

sql
CREATE TABLE t1(
  a INT DEFAULT (1+1),
  b INT DEFAULT (a+1),
  expires DATETIME DEFAULT(NOW() + INTERVAL 1 YEAR),
  x BLOB DEFAULT USER()
);

Belirleyici olmayan bir fonksiyonu DEFAULT içinde kullanırsanız, belgeye göre bu tabloya yapılan tüm eklemeler replikasyonda satır kipinde (row mode) aktarılır. Replikasyon kullanıyorsanız bu ayrıntı binary log biçimini doğrudan etkiler.

Tablo seçenekleri

Sütun listesinden sonra tablo seçenekleri gelir; eşittir işareti isteğe bağlıdır. En sık kullanılanlar ENGINE, DEFAULT CHARSET, COLLATE, COMMENT ve AUTO_INCREMENT'tir. ENGINE verilmezse varsayılan depolama motoru kullanılır; bu da belgeye göre InnoDB'dir. İstenen motor yüklü değilse ne olacağını NO_ENGINE_SUBSTITUTION SQL kipi belirler ve bu kip varsayılan olarak açıktır. Tablo yorumu en fazla 2048 karakter olabilir. AUTO_INCREMENT tablo seçeneği sayacın başlangıç değerini ayarlar.

Belgedeki şu örnek birkaç şeyi aynı anda gösterir: IF NOT EXISTS, otomatik artan birincil anahtar, tablo için ayrı ve bir sütun için ayrı karakter seti, yer kazanmak için sütunun yalnızca ilk 32 karakterini kapsayan kısmi bir indeks:

sql
CREATE TABLE IF NOT EXISTS test (
a BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(128) CHARSET utf8,
KEY name (name(32))
) ENGINE=InnoDB DEFAULT CHARSET latin1;

İndekslerin ayrıntısı MariaDB indeks oluşturma, yabancı anahtar ve CHECK kısıtları ise foreign key ve CHECK kısıtları yazısında.

IF NOT EXISTS ile OR REPLACE arasındaki fark

Aynı adlı tablo varken CREATE TABLE 1050 hatası verir. IF NOT EXISTS eklerseniz tablo yalnızca yoksa oluşturulur; varsa dokunulmaz ve bir uyarı üretilir. Uyarının metnini SHOW WARNINGS ile görebilirsiniz. Bu seçenek, var olan tablonun yapısını yeni tanımla karşılaştırmaz: tablo farklı sütunlara sahip olsa bile olduğu gibi kalır.

OR REPLACE ise var olan tabloyu yeni tanımla değiştirir. Belge, MariaDB 13.2'den itibaren bu işlemin varsayılan olarak atomik olduğunu, eski tablonun ancak yenisi başarıyla oluşturulduktan sonra silindiğini söyler. Ancak 13.2 bir önizleme sürümüdür; MariaDB 12.3 LTS'te ve belgede sayılan bazı durumlarda davranış DROP TABLE IF EXISTS ardından CREATE TABLE şeklindedir. Bu da şu anlama gelir: yeni tanım bir hatayla başarısız olursa eski tablo da ortadan kalkmış olur. Üretimde veri içeren bir tabloda OR REPLACE kullanmadan önce yedek almanız bu yüzden önemlidir.

Var olan tablodan yeni tablo: LIKE ve SELECT

CREATE TABLE yeni LIKE eski boş bir kopya üretir: sütunlar, indeksler ve tablo seçenekleri aynen alınır. Belgeye göre yabancı anahtar tanımları ile DATA DIRECTORY ve INDEX DIRECTORY seçenekleri kopyalanmaz. Kaynak tablonun geçici olması yeni tabloyu da geçici yapmaz; bunun için CREATE TEMPORARY TABLE ... LIKE yazmanız gerekir. LIKE görünümlerle (view) çalışmaz:

sql
CREATE VIEW v (mycol) AS SELECT 'abc';

CREATE TABLE v2 LIKE v;
ERROR 1347 (HY000): 'test.v' is not of type 'BASE TABLE'

CREATE TABLE ... SELECT ise sorgunun döndürdüğü her alan için bir sütun oluşturup veriyi de taşır. Buradaki kritik nokta, sorgunun yalnızca veri döndürmesidir: indeksler, NOT NULL, DEFAULT, AUTO_INCREMENT ve CHECK gibi özellikler kendiliğinden gelmez, elle tanımlamanız gerekir. İfade seçiyorsanız belge her zaman AS ile takma ad vermenizi önerir. Sorgu sırasında hata olursa tablo hiç oluşturulmaz. Yeni tabloda birincil veya benzersiz anahtar varsa çakışan satırlar için IGNORE (yeni değeri ekleme) veya REPLACE (eskisinin üzerine yaz) seçilebilir. Var olan bir tabloya satır taşımak içinse INSERT ... SELECT kullanılır.

Geçici tablolar

CREATE TEMPORARY TABLE yalnızca o oturumda görünen ve oturum kapanınca silinen bir tablo oluşturur. Farklı oturumlar aynı adla geçici tablo açabilir, birbirlerini etkilemezler. Geçici tablo, aynı veritabanındaki kalıcı bir tabloyla aynı ada sahip olabilir; bu durumda SQL ifadelerindeki ad geçici tabloyu gösterir. Oluşturmak için veritabanında CREATE TEMPORARY TABLES yetkisi gerekir. Motor belirtilmezse default_tmp_storage_engine ayarı kullanılır.

Yapıyı görmek: SHOW CREATE TABLE ve DESCRIBE

DESCRIBE sütunları tablo biçiminde listeler; SHOW CREATE TABLE ise tabloyu yeniden oluşturacak tam ifadeyi verir. Komutu ; yerine \G ile bitirirseniz çıktı dikey gösterilir. Belgedeki örnek:

sql
SHOW CREATE TABLE t\G
*************************** 1. row ***************************
       Table: t
Create Table: CREATE TABLE `t` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `s` char(60) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

Belge iki uyarı yapar. Birincisi, bu çıktı tablonun nasıl tanımlandığını gösterir, gerçek iç yapı biraz farklı olabilir: örneğin HASH olarak tanımlanan bir indeks, motor desteklemediği için aslında BTREE olabilir. İkincisi, indeksler tanımdaki sırayla değil, önce PRIMARY KEY, sonra benzersiz anahtarlar, sonra normal ve tam metin anahtarlar olmak üzere belirli bir düzende listelenir. Ad tırnaklaması sql_quote_show_create değişkenine, bazı ayrıntıların görünüp görünmemesi de etkin SQL kipine bağlıdır.

Silme: DROP TABLE ve DROP DATABASE

Silme: DROP TABLE ve DROP DATABASE: Tablo silinince kullanıcıların o tablo üzerindeki yetkileri otomatik olarak..., Bir yabancı anahtar bu tabloya başvuruyorsa tablo silinemez...

DROP TABLE tablo verisini, tanımını ve tabloya bağlı tetikleyicileri kaldırır. Birden fazla tablo virgülle verilebilir; listedeki bazı tablolar yoksa MariaDB bunları adıyla bildiren bir hata döndürür, ama var olanları yine de siler. IF EXISTS eklenirse olmayan her tablo için yalnızca bir not üretilir. Belgenin vurguladığı diğer noktalar:

  • Tablo silinince kullanıcıların o tablo üzerindeki yetkileri otomatik olarak silinmez.
  • Bir yabancı anahtar bu tabloya başvuruyorsa tablo silinemez; önce yabancı anahtarı kaldırmanız gerekir.
  • Verilen adla bir geçici tablo varsa yalnızca o silinir; geçici tablo yoksa aynı adlı kalıcı tablo silinir. DROP TEMPORARY TABLE yazmak, yanlışlıkla kalıcı tabloyu silmenizi engeller.
  • Başka bir bağlantı tabloyu açık bir transaction içinde kullanıyorsa DROP TABLE, "Waiting for table metadata lock" durumunda bekler. Bu bekleyişleri izlemek için SHOW PROCESSLIST ve KILL yazısına bakabilirsiniz.
  • RESTRICT ve CASCADE sözcükleri yalnızca taşınabilirlik için kabul edilir, MariaDB'de bir etkisi yoktur.

DROP DATABASE veritabanındaki tüm tabloları ve veritabanının kendisini siler; belge "bu komutla çok dikkatli olun" uyarısını açıkça yazar. Örnek çıktılar:

sql
DROP DATABASE bufg;
Query OK, 0 rows affected (0.39 sec)

DROP DATABASE bufg;
ERROR 1008 (HY000): Can't drop database 'bufg'; database doesn't exist

Veritabanını koruyup içindeki bütün tabloları silmek istiyorsanız belge, information_schema.TABLES üzerinden DROP TABLE komutlarını üreten bir sorgu önerir. Sorgu tabloları silmez, yalnızca çalıştırılacak komutların listesini üretir; listeyi gözden geçirip sonra çalıştırırsınız:

sql
SELECT CONCAT('DROP TABLE IF EXISTS `', TABLE_SCHEMA, '`.`', TABLE_NAME, '`;')
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'mydb';
KomutNe yaparDikkat
CREATE DATABASE IF NOT EXISTSYoksa veritabanı oluştururVarsa yalnızca uyarı verir
CREATE OR REPLACE DATABASEÖnce siler, sonra oluştururİçindeki tüm tablolar gider
CREATE TABLE IF NOT EXISTSYoksa tablo oluştururVar olan tablonun yapısını kontrol etmez
CREATE OR REPLACE TABLETabloyu yeni tanımla değiştirir12.3 LTS sürümünde önce silme yapılır
CREATE TABLE ... LIKEBoş yapısal kopyaYabancı anahtarlar kopyalanmaz
CREATE TABLE ... SELECTYapı ve veri kopyasıİndeks ve sütun özellikleri gelmez
DROP TABLETabloyu ve tetikleyicilerini silerYetkiler kalır, işlem geri alınamaz

Sık yapılan hatalar

  • Kurulum betiğinde IF NOT EXISTS'e güvenip yapının güncellendiğini sanmak. Tablo zaten varsa yeni sütunlar eklenmez; yapı değişikliği için ALTER TABLE gerekir.
  • Veri içeren tabloda OR REPLACE kullanmak. 12.3'te eski tablo önce silindiği için yeni tanım başarısız olursa iki tabloyu da kaybedebilirsiniz.
  • CREATE TABLE ... SELECT ile birincil anahtarın da kopyalandığını varsaymak. Sorgu yalnızca veri döndürür; anahtarları ve NOT NULL kurallarını ayrıca tanımlayın.
  • Linux sunucuda tablo adlarını karışık harflerle yazmak. Orders ve orders farklı tablolar olarak görülebilir; adları tutarlı biçimde küçük harfle yazın.
  • Açık bir transaction içinde DDL çalıştırmak. CREATE TABLE ve DROP TABLE örtük commit yapar.
  • DROP DATABASE sonrası yetkilerin de silindiğini düşünmek. Aynı adla yeniden oluşturulan veritabanında eski yetkiler geçerli olabilir; yetkileri ayrıca kaldırın.

Sık Sorulan Sorular

CREATE SCHEMA ile CREATE DATABASE arasında fark var mı?

Hayır. Belgeye göre CREATE SCHEMA, CREATE DATABASE ile eş anlamlıdır; aynı şekilde DROP SCHEMA da DROP DATABASE ile aynıdır.

Tablo oluştururken ENGINE yazmak zorunda mıyım?

Hayır. Yazmazsanız oturum değişkeni default_storage_engine, o da yoksa başlangıç seçeneği, o da yoksa varsayılan motor olan InnoDB kullanılır. Var olan motorları SHOW ENGINES ile listeleyebilirsiniz.

Tabloyu yanlışlıkla sildim, geri getirebilir miyim?

DROP TABLE geri alınabilen bir işlem değildir ve transaction ile korunmaz. Tek yol yedekten dönmektir. Bu yüzden düzenli yedek almanız gerekir; araçlar için mariadb-dump ile yedekleme ve mariadb-backup ile fiziksel yedekleme yazılarına bakın.

Hangi tabloların olduğunu nasıl görürüm?

USE ile veritabanını seçtikten sonra SHOW TABLES tabloları listeler; tek bir tablonun ayrıntısı için DESCRIBE tablo veya SHOW CREATE TABLE tablo kullanılır. Programatik sorgular için information_schema.TABLES tablosu da aynı bilgiyi verir.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: MariaDB öğrenme rehberi · MariaDB veri tipleri · MariaDB ALTER TABLE · INSERT, UPDATE ve DELETE · karakter seti ve utf8mb4 · SQL nedir