Selam dostum bu arşiv içinde NodeJS kullanırken MySQL veritabanını güçlendirmeyi ve temel yapıları öğreneceğiz. Metin bazlı olduğu için dilersen ekran görüntüsü alıp boş olduğun zamanlarda okuyabilirsin. Şimdiden bol şans dilerim. (Arşiv içerisinde bazı bölümler NSFW içeriklidir.)
- Bu soruya verilebilecek fazla cevap yok. NodeJS projeleri için genel olarak en iyi veritabanı MongoDB'dir. Bunun bir kaç sebebi mevcut. Birincisi MySQL lokal veritabanıdır. MongoDB'ye istenilen her yerden ulaşılabilir. (Buna Cloud diyoruz. MySQL Veritabanlarına uzaktan bağlantı kurabilirsiniz fakat bunun maliyeti olur.) MongoDB'de daha fazla anlaşılır olan
schema
yani şema sistemi mevcut. MySQL'da şemalar yerinetable
yani tablo dediğimiz veri tutma birimleri bulunur. MySQL, MongoDB'deki gibi dizi verisi tutamaz (Array
) bundan dolayı MongoDB'ye göre en azından başlangıçta daha zor gelir.
Bu arşivde NodeJS üzerinden MySQL2 kullanan Discord Bot'u yapacağız. Kafa karışıklılığını önlemek için iki adet modülün mevcut olduğunu söylemeliyim. Bunlardan birincisi Legacy yani eski olan MySQL modülü diğeri yenilenmiş MySQL2 modülü.
MySQL kullanabilmek için herhangi bir internet hesabı açmak zorunda değilsiniz.
MySQL Community Server
adı verilen sunucuyu kurmanız yeterli olacak.
Kurulumda dikkat etmeniz gereken fazla bir şey yok. Kurulumda sadece Community Server'i kurmanız gerekiyor. Bilgisayarınızı developer
olarak gösterin ve sadece root
şifresi ayarlayın. Başka bir kullanıcı açmayın.
MySQL'ın kurulumu bittiğinde kendisine özel olan konsolu bilgisayarınıza kurar. Bu konsolu açmak için arama yerine MySQL Command Prompt
kelimelerini girmeniz yeterli olacak. Konsol önünüze geldiğinde sizden giriş bilgilerinizi soracak. (Kurulum yaparken yazdığınız şifre neyse o.) Normal konsoldan giriş yapmak istersen de mysql -u root -p
yazman yeterli.
Şifrenizi girdikten sonra başarılı giriş yaparsanız aşağıdaki ekran gelecektir.
Heyecanlanmanıza hiç gerek yok. Ağlayarak komut yazacağız. Başlamadan önce unutmamanız gereken bir husus var, MySQL Konsol'unda komut girerken yazdığınız querry
'lerin sonunda ;
kullanmak zorundasınız. Kullanmazsak ne olur diye soranlar için MySQL Komut penceresi bir alta kayar ve ikinci satırda komutunuzu girmeniz için size olanak sağlar. Yani sanki VSC'de kod düzenliyor edasıyla alt alta query
girişi yapabilirsiniz.
Eğer ilk satırda ;
kullanılsaydı aşağıdaki satırlara geçmeden işlemi çalıştırırdı. Eğer herhangi bir yanlışlık yaptıysanız ALT + C
kombinasyonu ile mevcut girişi sıfırlayabilirsiniz.
NodeJS'de bağlantı gerçekleştirmeden önce database
oluşturmak zorundasınız. Bunun için şu query
kullanılır:
CREATE DATABASE SanalMafya;
/* Veya */
create database SanalMafya;
/* Veya */
create database Sanal_Mafya;
/* Veya */
CREATE DATABASE SönölMöfyö;
/* Bu şekilde yorum satırı girebileceğinizi de unutumayın he. */
Aman Allah'ım! İlk MySQL query
'ini girdiniz. Hadi çıkan sonuçlara bakalım.
İlk satırda query
'i yazdık. Altta da bir adet yerin değiştirildiğini ve bunun 0.59 saniye
'de yapıldığını görüyorsunuz. Bu yolunu kaybeden Maymun'u mutlu etmek için bütün database
isimlerini sıralatalım.
Üstteki query
sayesinde bulunan bütün database
'leri görebilirsiniz. Sizde çıkan sonuçlar daha düşük olabilir.
Yufka yürekli Rişad'ım sen üzülme. Herkes hata yapar yahu, asıl sorunumuz bu hatayı nasıl düzelteceğimiz olmalı. MySQL bir yapboz gibidir. Bütün query
'ler neredeyse birbiriyle kullanılabilir. Hatalar bizi güçlendirir diyerek size uzak akrabam olan DROP
ile tanıştırmalıyım. DROP
neredeyse her yerde kullanılabilir. Oluşturduğunuz database
'yi komple ortadan kaldırır veya table
'yi siler.
Artık Maymun sonsuza dek kayıp.
Herhangi bir
database
oluşturduktan sonra içinde işlem yapabilmek içindatabase
seçimi yapmak zorundasınız. Bundan dolayıUSE
'yi kullanırız.
Hadi ilk tablomuzu oluşturalım. Tablo oluşturmadan önce aşağıdaki örneğe göz atın.
CREATE TABLE (
numara INT PRIMARY KEY AUTO_INCREMENT NOT NULL,
isim VARCHAR(20) CHARACTER SET utf8 NOT NULL,
soyisim VARCHAR(20) CHARACTER SET utf8 NOT NULL,
yaş INT,
açıklama TEXT CHARACTER SET utf8,
zaman DATETIME DEFAULT (CURRENT_TIME)
);
Hadi en baştan başlayalım. Dedik ki CREATE
yani oluştur daha sonrasında ne oluşturmak istediğimizi yazdık. İki adet parantez açıp sonuna da ;
ekledik. Sıra içini doldurmaya geldi hehe. İlk sırada mevcut olan numara
sırası için dedik ki: sen o tablonun öncelikli anahtarısın (bu şimdilik öğrenmeye değer değil.) ve senin taşıyacağın verinin türü sayı türü olacak (sayı türleri üzerinde ekleme/çıkarma yapılabilir.) özel bir belirteç olan AUTO_INCREMENT
ise her veri girişi olduğu zaman senin üzerine +1
sayı ekle.
Anlamadım moruk ne verisi ne arttırması?: Burayı iyi dinle, Auto Increment yani otomatik artış belirteci her veri girildiği zaman otomatik olarak sıra numarası belirler gibi düşün. Bunu varsayılan olarak bırakırsan her veri arttığı zaman +1 ekler. Bu da sana neyi sağlar?
1- Melisa ARDUÇ
2- Feyza TEN
3- Ali VARSUVAR
Üstte de görüldüğü gibi otomatik sıra oluşturmanı sağlar. Bununla ne yaparım diye düşünenler için yaptığınız ceza sisteminde çok güzel ceza numarası olarak kullanabilirsiniz.
İkinci satırda yer alan isim verisi için de dedik ki sen yirmi haneli string
taşıyabilirsin. Bu ne demek oluyor? Yirmi karakter ve yirmi karakterin altındaki string
verileri taşıyabilirsiniz.
Aslı (dört hane.)
Melih (beş hane.)
Abdülrezzak Kıllıbacak (yirmi bir hane.)
Üstte verilen verilerden sadece Aslı
ve Melih
verisi girilebilir demek oluyor. Yirmi bir haneli veri girişi yapmaya çalışırsanız hata alırsınız. Yirmi bir verilik yer oluşturmak için VARCHAR(21)
yapmanız yeterli.
Character set diye bir şey var bak bana yan yan bakıyor?: Normal VARCHAR
birimleri ve diğer bütün string
verileri sadece İngilizce Latin harfleri ve birimleri desteklediğinden dolayı içerisinde kullanılabilecek karakterleri arttırmak için CHARACTER SET utf8
diyoruz. VARCHAR
'ın özel bir durumu var. Dilerseniz böyle uzatabilirsiniz VARCHAR(18) CHARACTER SET utf8
ya da NVARCHAR(18)
kullanırsınız. İkisi de aynı sonuca çıkar.
Not Null diye bir şey var bana el sallıyor?: not null
seçili sıranın asla boş bırakılamayacağını söyler. Yani boş bırakmaya çalıştığınızda (null/nil
) size hata vererek tabloya girişinize izin vermez. Boş bırakılabilecek (keyfekeder veri ekliyorsanız) not null
kullanmamanız gerekir.
Dördüncü sırada yer alan yaş tablosuna gelecek olursak o tablonun sadece sayı taşıyabileceğini söylemiştik. Diğerlerinden farklı olarak o sıra boş bırakılabilir.
Açıklama verisine gelecek olursak yeni bir ağabey ile sizi tanıştırmak istiyorum. Kendisine TEXT
diyoruz. Aşağıda bir sıralama yapacak olursak:
TINYTEXT = VARCHAR(255) [En fazla 255 Byte yer kaplar.]
TEXT = VARCHAR(65535) [En fazla 64 KB yer kaplar.]
MEDIUMTEXT = VARCHAR(16777215) [En fazla 16 MB yer kaplar.]
LONGTEXT = VARCHAR(4294967295) [En fazla 4 GB yer kaplar.]
Kısacası TEXT
65 bin karaktere kadar destekler. VARCHAR
ile uğraşmanız yerine sizi kurtarır. Fakat neden yine de VARCHAR
kullanılıyor diye sorarsanız kesin olan birimlerde VARCHAR
kullanımı sağlıklıdır. Örnek vermek gerekirse T.C. Numaranızın alabileceği maksimum ve minimum hane değeri bellidir. Yanlış bir değer girildiğinde sizi tablo uyarır. TEXT
biriminin desteği için CHARACTER SET utf8
'i burada da kullandık.
Zaman kavramı MySQL'in desteklediği harika bazı içerikleri sizlere sunar. DATETIME
size zaman verisi tutma olacağı verir. Bu verilerin TIMESTAMP
olmadığını unutmayın. Bu tabloda biz dedik ki, sen bir DATETIME
türüsün. Bu türün alabileceği DEFAULT
yani hiçbir veri girilmezse NULL
'u tercih etmek yerine yerleştireceğin veri şu anın zamanı olsun dedik. Evet, her veri girişinde otomatik olarak zamanı seçecek.
MySQL
DEFAULT
birimlere selam verin! Neredeyse her verideDEFAULT
belirleyebilirsiniz. Örnek vermek gerekirse:
item_name VARCHAR(50) NOT NULL,
item_count INT DEFAULT 0
item_durability DEFAULT 100
item_lore DEFAULT "Şamda Kayısı"
Üstte üç adet DEFAULT
birim verdik. Hadi yorumlayalım fakat ilk başta DEFAULT
tam olarak ne yapar ondan söz edelim. DEFAULT
sayesinde seçili sıraya veri girişi yapmazsanız otomatik olarak DEFAULT
olarak seçili veriyi alır. Yani siz bu üstteki örnekte şu yerleri doldurdunuz diyelim: item_name
'yi "Anka Kuş'u", item_count
'u da bir olarak belirlediniz. İki yeri boş bıraktınız ama o birimlerin DEFAULT
değerleri mevcut. Bundan dolayı veriler sırasıyla şöyle olacak:
item_name | item_count | item_durability | item_lore
Anka Kuşu | 1 | 100 | Şamda Kayısı
Oluşturduğumuz tablolara göz atmak için SHOW TABLES
query
'ini girebilirsiniz.
Nasıl veri tablosu oluşturacağımızı yazdık. Sırada verileri tutmada. MySQL'da
INSERT INTO
adı verilen yeni giriş suretiyle veri ekleme biçimi mevcut. (YaniINSERT INTO
durması belirtilmezse sonsuza dek veri ekleyebilir. Mevcut verinin üzerine yazmaz.) İlk başta nasıl veri tutacağız kısa bir şekilde ona bakalım. Tablomuz aşağıdaki gibi olsun.
CREATE TABLE aptallar (
isim VARCHAR(20) NOT NULL,
ikinci_isim VARCHAR(20),
soyisim VARCHAR(20) NOT NULL,
aptallik_seviyesi INT DEFAULT 0
bu_kisi_vurduruyor_mu BOOLEAN DEFAULT true
);
Bu tabloya veri kayıdını şöyle yapabiliriz:
INSERT INTO aptallar (isim, soyisim, aptallik_seviyesi) VALUES ('Talha','KAVAKLI',100);
Sonuç:
isim | ikinci_isim | soyisim | aptallik_seviyesi | bu_kisi_vurduruyor_mu
Talha | (NULL) | KAVAKLI | 100 | true
Hadi olan bitene göz atalım sevgili Müzmin arkadaşım. INSERT INTO
neydi? INSERT INTO
sevgiydi, kardeşikti. İlk query
'imiz INSERT INTO
oldu. Daha sonrasında aptallar
olarak yazdığımız tabloya verdiğimiz genel isimi belirtiyor. Daha sonrasında hangi verileri eklemek istiyorsak o verileri yazıyoruz. Tabloda toplam beş adet veri olabilir. Biz kayıt yaparken sadece üç veriyi eklemek istedik. Bunları sırasıyla virgül ile yazdık ve VALUES
query
'ini koyduk. Daha sonra da verileri nasıl istiyorsak öyle girdik. Burada ikinci_isim
olmadığı için ve o veri tipine NOT NULL
yazmadığımız için (NULL)
olarak giriş yaptı. BOOLEAN
veri tipi ise dört tip veriyi taşıyabilir bunlar: true
, false
, 0
, 1
. Burada DEFAULT
olarak true (1)
ayarlaması yaptık.
Araya girmek gerekirse size yeni baldızımız olan
TRUNCATE
'yi tanıtmak istiyorum.TRUNCATE
kimsenin sevmediği ama yerini kimsenin tutamadığı baldızımız gibi. Ne demişler baldız baldan tatlıdır.
TRUNCATE
en kısa anlatımla bir tablonun içindeki bütün verileri boşaltmanıza yarar. Hadi test edelim!
Şu anki verilerimiz:
isim | ikinci_isim | soyisim | aptallik_seviyesi | bu_kisi_vurduruyor_mu
Talha | (NULL) | KAVAKLI | 100 | true
Mert | (NULL) | YILMAZ | -100 | false
Bu tablonun ismini hatırlayalım aptallar
. Gireceğimiz query
ise TRUNCATE TABLE aptallar
. Bunun sonucu aşağıda yer alıyor:
isim | ikinci_isim | soyisim | aptallik_seviyesi | bu_kisi_vurduruyor_mu
Tablo tamamen boşaldı fakat tablodaki veri türleri hala duruyor. Bu test yaptıktan sonra eski haline getirmek için muhteşem bir çözümdür.
Uzman Sude yanıtlıyor: TRUNCATE
işlemi tablodaki her şeyi sıfırladığı gibi AUTO_INCREMENT
verisini de sıfırlar. Bu da ne ola ki?
/* Buradaki bilgiler ekstra bilgidir. Öğrenmek zorunda değilsin. */
/* AUTO_INCREMENT neydi? Her veri girişinde kendisini arttıran bir sayı tablosuydu değil mi?
Aşağıdaki gibi bir örnek verebiliyorduk hatırladıysan: */
pid | isim | ikinci_isim | soyisim | aptallik_seviyesi | bu_kisi_vurduruyor_mu
1 | Talha | (NULL) | KAVAKLI | 100 | true
2 | Mert | (NULL) | YILMAZ | -100 | false
/* Burada biz 2. PID değerini sildik diyelim: */
pid | isim | ikinci_isim | soyisim | aptallik_seviyesi | bu_kisi_vurduruyor_mu
1 | Talha | (NULL) | KAVAKLI | 100 | true
/* Sonuç ne oldu? Üstteki gibi tek bir veri kaldı değil mi? Hadi şimdi bir veri ekleyelim: */
pid | isim | ikinci_isim | soyisim | aptallik_seviyesi | bu_kisi_vurduruyor_mu
1 | Talha | (NULL) | KAVAKLI | 100 | true
3 | Miaf | (NULl) | (NULL) | -100 | false
/* O da ne? Biz ikinci veriyi silmiştik? Ne yani AUTO_INCREMENT eski veriyi hatırlıyor ve
üzerine kayıt yapmıyor mu? Evet öyle. Bu hafızayı sıfırlamak için de TRUNCATE kullanılabilir. */
INSERT INTO
'nun veri değiştirme yapamayacağını söylemiştik. Hadi bunu örneklerle pekiştirelim. Aşağıda bir tablo örneği var:
memurun_ismi_soyismi | memurun_bodrosu | memurun_pozisyonu | aylık_kesinti
Melih Şam | 1000 | İnsan Kaynakları | 50
Damla | 4500 | CEO | 130
Bu tabloya birinci sıradaki aynı girişi yaparsak ne olur?
INSERT INTO memurlar (memurun_ismi_soyismi, memurun_bodrosu, memurun_pozisyonu, aylık_kesinti) VALUES ('Melih Şam', 1000, 'İnsan Kaynakları', 50)
Sonuç:
memurun_ismi_soyismi | memurun_bodrosu | memurun_pozisyonu | aylık_kesinti
Melih Şam | 1000 | İnsan Kaynakları | 50
Damla | 4500 | CEO | 130
Melih Şam | 1000 | İnsan Kaynakları | 50
Ağlak çocuğumuz Melih'in aylık aldığı maaşı düşürmemiz lazım. Tek başına bütün İnsan Kaynakları'nı sömürüyor köpek. Ne yapmalıyız?
UPDATE memurlar SET memurun_bodrosu = 500;
Sonucumuz ne olacak?
memurun_ismi_soyismi | memurun_bodrosu | memurun_pozisyonu | aylık_kesinti
Melih Şam | 500 | İnsan Kaynakları | 50
Damla | 500 | CEO | 130
Cafer bez getir! Bizim CEO'nun da maaşı 500'e düştü. Bizi öpmeden önce bu durumu düzeltmeliyiz ama ilk başta neden oldu bu?
Üstteki durumla karşılaşmanızın nedeni çok basit. Çünkü verinin değişmesini istedik ama kimin değişmesi gerektiğini istemedik.
WHERE
kullanmadığımız için herkesin verisi değişti. Hadi bunu düzeltelim:
UPDATE memurlar SET memurun_bodrosu = 500 WHERE memurun_ismi_soyismi = 'Melih Şam';
Sonuç:
memurun_ismi_soyismi | memurun_bodrosu | memurun_pozisyonu | aylık_kesinti
Melih Şam | 500 | İnsan Kaynakları | 50
Damla | 4500 | CEO | 130
Tabloyu tümden silme yolunu göstermiştik. Bu sefer tek bir sütunu nasıl silebileceğinizi göstereceğim.
DELETE FROM memurlar WHERE memurun_ismi_soyismi = 'Melih Şam'
Üstteki query
'i çalıştırdığımız zaman sonuç aşağıdaki gibi olacak:
memurun_ismi_soyismi | memurun_bodrosu | memurun_pozisyonu | aylık_kesinti
Damla | 4500 | CEO | 130
Hep birlikte oğlumuz
SELECT
'i kızımızFROM
'a istiyoruz. Şampanya, patla! Bir veriyi nasıl çekeceğimizi öğrenelim. Bencallback
'ları çok sevdiğim için MySQL2'de callback kullanıyorum. Kullandığımız tablo yukardaki memurlarla ilgili olan tablo olacak.
SELECT * FROM memurlar;
Basit bir soru olan SELECT *
bütün her şeyi seçmek için kullanılır. Memur tablosunda bulunan bütün sonuçları bize verir. Sonucumuz şu olur:
memurun_ismi_soyismi | memurun_bodrosu | memurun_pozisyonu | aylık_kesinti
Damla | 4500 | CEO | 130
Peki spesifik verileri çekmek için ne yapabiliriz? Ya da sadece istenileni nasıl çekeriz? Bu da oldukça basit. Her şeyi seçmek için *
kullanmamanız ve isteğinizi yazmanız yeterli.
SELECT aylık_kesinti FROM memurlar;
Sonucumuz:
aylık_kesinti
130
Daha da özel veri çekmek için ne yapıyoruz altan? WHERE
kullanıyoruz müzmin! Hadi başka bir veritabanına geçelim.
suclu_ismi | suc_orani | en_sonuncu_sucu
Aether | 100 | Sanal mafya.
Ozzy | 78 | Bot yapmak.
Shinoa | 100 | Gay olmak.
Damla | 35 | Harika biyografi yazmak.
Ada | (NULL) | (NULL)
Şimdi SELECT * FROM suclular;
yaptığımızda çıkan sonuç üstteki sonuç. Bu sonuçları daraltmaya geçmeden önce size üstteki örneği pekiştirmek amacıyla SELECT suclu_ismi FROM suclular
yapmak istiyorum.
suclu_ismi
Aether
Ozzy
Shinoa
Damla
Ada
Bu sonuçları bir kişiye ait olmasını isterseniz? WHERE
buradaydı değil mi?
SELECT * FROM suclular WHERE suclu_ismi = 'Ozzy';
Çıkan sonuç:
suclu_ismi | suc_orani | en_sonuncu_sucu
Ozzy | 78 | Bot yapmak.
İlk başta bir bağlantı sağlamalıyız. Bu bağlantı için MySQL2 modülünü kullanacağız. Aşağıda bağlantı için örnek verdim. (Chalk mevcut.)
const con = (global.con = mysql.createConnection({
host: localhost,
user: "root",
password: "1234",
database: "test_database",
}));
con.connect(err => {
if (err) throw err;
console.log(chalk.bgWhite.black(`[${moment().format('YYYY-MM-DD HH:mm:ss')}]`) + chalk.cyan(` Successfully connected to MySQL database.`));
});
Başarılı bir şekilde bağlantı gerçekleştirilirse konsola pozitif mesaj atacak. Global hale getirdiğimiz bu komut sayesinde her yerde tanımlama yapmadan kullanabiliriz. (Methodları göstermez.)
Bu sorunun cevabı oldukça basit.
con.query()
direk olarakquery
komutları girmenize yardım eder. Örnek vermek gerekirse,con.query("CREATE DATABASE OlumNedirKi")
gibi.
Çok basit bir not alma komutu yaratmaya ne dersin? Hadi yapalım! Ama yapmadan önce bir tablo oluşturalım.
CREATE TABLE Notes (
note_author VARCHAR(18) NOT NULL,
note_description TEXT CHARACTER SET utf8 NOT NULL,
note_time DATETIME DEFAULT (CURRENT_TIME)
);
(1-) if (!args[0]) return message.channel.send("Bir içerik girmek zorundasın!")
(2-) con.query(`SELECT * FROM Notes WHERE note_author = '${message.author}'`, async (err, rows) => {
(3-) if (err) throw err;
(4-) if (rows.length < 1) {
(5-) con.query(`INSERT INTO Notes (note_author, note_description) VALUES ('${message.author.id}','${args.join(" ")}')`)
(6-) } else {
(7-) con.query(`UPDATE Notes SET note_description = '${args.join(" ")} WHERE note_author = '${message.author.id}''`)
}
})
Gözünüz korktu mu? Korktuysa hiç korkmasına gerek yok tek tek bütün numaralı yerleri anlatacağım.
1- Burada hiçbir not içeriği girmediysen komutu çalıştırma dedik.
2- Burada o üyenin bütün notlarını çekmeye çalışıyoruz.
3- Herhangi bir hata varsa onu konsola at diyoruz.
4- Eğer o SELECT
aramasından çıkan sonuçların toplamı birden düşükse 5- satırı çalıştır diyoruz.
5- Üyenin hiçbir notu olmadığı için yeni bir not oluşturmak zorundayız değil mi? O halde INSERT INTO
ile oluşturuyoruz.
6- Şimdi de eğer üyenin notu varsa 7- satırı çalıştır diyoruz.
7- Adamın eski notunun olduğunu bildiğimiz için o notu düzenlemesini istiyoruz.
Bir tablonuz var ama içindeki verilerinizi kaybetmeden tablonuza yeni kolonlar eklemek, değiştirmek veya silmek istiyor olabilirsiniz. Bunun için
ALTER TABLE
yardıma koşuyor.
Aşağıda örnek bir kolon verdik. Hemen göz atalım.
kitap_numarasi | kitap_sahibi | kutuphane_karti
0065 | Melis SEZEN | TEK_GIRIS
0031 | Yasin SEVGİM | COKLU_GIRIS
Üstte sadece üç adet kolonun olduğunu görüyorsunuz. Bu tablonun adı: KUTUPHANE
. Yeni eklenen kolonlar her zaman en sona eklenir.
ALTER TABLE KUTUPHANE ADD kutuphane_gecerliligi TEXT CHARACTER SET utf8 NOT NULL;
Sonucumuz:
kitap_numarasi | kitap_sahibi | kutuphane_karti | kutuphane_gecerliligi
0065 | Melis SEZEN | TEK_GIRIS | (NULL?)
0031 | Yasin SEVGİM | COKLU_GIRIS | (NULL?)
Üstte görüldüğü gibi yeni bir kolon ekleyebildik. Fakat burada bir problem mevcut, kutuphane_gecerliligi
kolonunu NOT NULL
olarak belirlediğimiz için burada NULL
ifadelerine kesin olarak veri atanmalı.
Uyarı: DEFAULT
değerler için NULL
almadan otomatik olarak yerleştirme yapar.
Üstte eklediğimiz kutuphane_gecerliligi
kolonunu silmek için aşağıdaki ifadeyi kullanmak yeterli.
ALTER TABLE KUTUPHANE DROP COLUMN kutuphane_gecerliligi
Halihazırda olan bir kolonun yeni veri tipine geçmesi için aşağıdaki query
çalıştırılmalı:
ALTER TABLE KUTUPHANE MODIFY COLUMN kutuphane_gecerliligi BOOLEAN DEFAULT true
Veri tipini belirlerken en sonda kullandığınız içerikler genelde kural belirleyicilerdir. Toplam yedi adet kural belirleyici vardır.
- NOT NULL: Bu verinin
NULL
olmadığının kuralını belirler. - UNIQUE: Herkes "yünik" kardeşim. Unique olarak belirlenen bir veriden bir tane daha olamaz. Bu karışıklıkların önüne geçmek için iyi bir yol.
- PRIMARY KEY: Bu ibne, en iyisi benim diyenler için var. Bir veri tipinde kullanılabilen ilk anahtar kuralı
UNIQUE
veNOT NULL
'un birleşimidir. - FOREIGN KEY: İleri düzeye başladığınız zaman öğreneceğiniz yabancı anahar kuralı iki tabloyu birbirine bağlamanızı sağlar. Mesela tek bir silme işlemi yaparken iki yerden otomatik olarak silmek gibi. (Örnek: T.C. ile ilgili kişilerin bilgilerinin bulunduğu bir veritabanı ve kişilerin işledikleri suçlarla ilgili veritabanı yarattınız diyelim. T.C.'den birisini atarken tek bir T.C.'yi silmeniz iki veritabanından bu bilgileri kaldırmasına sebep olacak.)
- CHECK: Koşul yaratmanızı sağlar. Mesela bir veri tipini yaş olarak kaydettiniz ve kaydedilecek yaşların muhakkak 18'den büyük olmasını istiyorsanız.
- DEFAULT: Üstte bir çok defa anlatılan varsayılan değer kuralı.
- CREATE INDEX: Bu ibneyi ben bile çözemedim. İndeks yaratmanıza sebep oluyor. Daha hızlı veri çekmek ve akış sağlamak için gerekli olduğunu bilmeniz yeterli. İndeksler insanlar tarafından görülemez.
MySQL saat biçimi tutmak için harika yollardan birisi. Bir sürü saat tutabileceğiniz tip var ve oldukça sağlam çalışıyorlar. Hadi onları inceleyelim.
DATE formatı: YYYY-MM-DD
DATETIME formatı: YYYY-MM-DD HH:MI:SS
TIMESTAMP formatı: YYYY-MM-DD HH:MI:SS
YEAR formatı: YYYY or YY
Bir şeyi söylemeyi unutmuş olabilirim.
TIMESTAMP
bildiğinizTIMESTAMP
'lardan değil. Evet o bakire deği- ay pardon yanlış yere girdik.TIMESTAMP
o karışık3131313131313131
biçimindeki saatlerden değil. MySQL'daTIMESTAMP
olarak saat saklamanız mümkün değil. Bundan dolayı kayıt ederken muhakkak tarih kayıt etmelisiniz.
Peki TIMESTAMP
ile DATETIME
arasındaki fark ne? MySQL zamanları tutmayı şundan dolayı hedefler: her veri değiştiğinde bu verinin ne zaman değiştiğini tespit etmek için. Sizin amacınız farklı olabilir siz zaman verilerini direk depolamak isteyebilirsiniz. Bu gibi durumlarda DATETIME
kullanmanız gerekiyor.
TIMESTAMP
ise dönüştürülme için gereklidir. UTC Tipi kayıt yapıldığı için TIMESTAMP
kayıtları kullanıcıdan kullanıcıya değişiklilik gösterebilir. Bu ne demek oluyor?
Örnek bir TIMESTAMP: 15 Mayıs 1990 GMT+1 Orta Avrupa Pasifik Saati
Biz Türkiye'den görüntülemek isteseydik bu TIMESTAMP
bize göre değişecek.
Bizim öğrendiğimiz kısıtlı veri tiplerini biliyorsunuz. (
BOOLEAN, TEXT, VARCHAR, INT
gibi.) Hadi derinlere dalalım.
CHAR(karakter?) => VARCHAR(karakter?)
- Bildiğiniz üzere VARCHAR(18) kullanmıştık. Bu neydi? İçine en fazla 18 hanelik verilerin
girebileceğini anlattık. CHAR aslında VARCHAR ile aynı ama bazı farklılıkları var.
CHAR kullanabilmek için sabit uzunluğa ihtiyacınız vardır. Yani siz T.C. ile ilgili bir
veritabanı oluşturdunuz diyelim, T.C.'lerin uzunluğu değişebilir mi? Hayır değişemez. Bundan
dolayı CHAR(11) yapmanız daha mantıklı. Ama isim verilerini tutarken isimler değişkenlik
gösterebilir değil mi? Bundan dolayı VARCHAR kullanmanız gerekir.
CHAR, VARCHAR'a göre %50 daha hızlıdır.
CHAR SMA (static memory allocation) kullanır. VARCHAR DMA (dynamic memory allocation) kullanır.
CHAR'ın tutabileceği en büyük karakter 225'tir. VARCHAR ise 65,535 karakter tutabilir. (En çok)
BINARY(karakter?) = VARBINARY(karakter?)
- CHAR ve VARCHAR ile aynı gibi düşünebilirsiniz. Tek farkları BINARY taşıyabilmeleri.
TINYBLOB => MEDIUMBLOB => BLOB(karakter?) => LONGBLOB
- BLOB'ları taşımak için kullanılır. TINYBLOB 225 Byte yere kadar taşıma yapabilir.
MEDIUMBLOB'lar 16,777,215 Byte'ya kadar taşıma yapabilir. Bu sayı LONGBLOB'da 4,294,967,295
Byte'ya kadar çıkar. (BLOB'lar Binary şeklindeki Objelerdir.)
ENUM(değer1, değer2, değer3 ...)
- Önceden girilen değerlerin seçilebileceği ENUM seçeneklerde kullanılır. Değer olarak belirt-
ilmeyen değer girişinde boş değer girilir. 65535'e kadar değer destekler.
SET(değer1, değer2, değer3 ...)
En fazla 64 değer alabilen SET veri tipinde hiçbir değer seçilmeyebilir ya da birden çok değer
seçilebilir.
BIT(büyüklük?)
1 ila 64 arasındaki BIT'leri tutabilir.
TINYINT(sayı?) => SMALLINT(sayı?) => MEDIUMINT(sayı?) => INT(sayı?) => BIGINT(sayı?)
TINYINT en fazla -128 ila 127 sayılarını (ve arasındakini) tutabilir.
SMALLINT en fazla -32768 ila 32767 sayılarını (ve arasındakini) tutabilir.
MEDIUMINT en fazla -8388608 ila 8388607 sayılarını (ve arasındakini) tutabilir.
INT en fazla -2147483648 ila 2147483647 sayılarını (ve arasındakini) tutabilir.
BIGINT en fazla -9223372036854775808 ila 9223372036854775807 sayılarını (ve arasındakini)
tutabilir.
INT(sayı?) === INTEGER(sayı?)'dır.
BOOL = BOOLEAN
0 veya 1 olarak veri tutar. (true/false.)
İleri düzey bilgi: BOOLEAN veriler 0 veya 1 olabilir desek de, 1'den büyük değerleri alırsa
1'e eşit yani true olarak görülür. Sadece 0 değeri false değer alabilir.
Allah'ın unuttuğu diğer veri tipleri ve ananızın ağlayacağı diğer türler: FLOAT(),
DOUBLE(), DOUBLE PRECISION(), DEC() veya DECIMAL().
ALLAHIN BELASI UNSIGNED ve ZEROFILL'in anlatımı aşağıda.
Anlaması kıt arkadaşlarımız için kısa özet:
ZEROFILL
varsa sadeceTINYINT
değerler için varolabilir. Bu ne demek?ZEROFILL
sadeceTINYINT
için çalışır demek. Peki ne iş yapıyor? Sayının sonuna ne kadar sıfır isterseniz herhangi bir veri girişinde o kadar sıfır ekliyor.UNSIGNED
ise masum görünebilir bu sayının sadecePOSITIVE
değerler alabileceğini gösterir.UNSIGNED
her türlüINTEGER
değerde kullanılabilir. Bununla da kalmaz yukardaki öğrendiğiniz bütün sayıların alabileceği değerlerin amına koyar.
UNSIGNED
Değerleri:
TINYINT
: 0 ila 255 arası.
SMALLINT
: 0 ila 65535 arası.
MEDIUMINT
: 0 ila 16777215 arası.
INT
: 0 ila 4294967295 arası.
BIGINT
: 0 ila 18446744073709551615 arası.
Diğer dillerde 18446744073709551615 sayısının okunuşu. NEDEN BÖYLE BİR SAYI VAR AMINA
KODUKLARIM BU KADAR BÜYÜK SAYIYI NE YAPIYORSUNUZ?
TÜRKÇE: on sekiz kentrilyon dört yüz kırk altı katrilyon yedi yüz kırk dört trilyon yetmiş üç
milyar yedi yüz dokuz milyon beş yüz elli bir bin altı yüz on beş.
LEHÇE: osiemnaście trylionów czterysta czterdzieści sześć biliardów siedemset czterdzieści
cztery biliony siedemdziesiąt trzy miliardy siedemset dziewięć milionów pięćset
pięćdziesiąt dwa tysiące osiemset siedem. (Bu ne amına koyayım.)
İNGİLİZCE: eighteen quintillion four hundred forty-six quadrillion seven hundred forty-four
trillion seventy-three billion seven hundred nine million five hundred fifty-two thousand
eight hundred seven.
Veritabanlarınızı güvenli çözümlerden birisi olan
BACKUP
ile koruyun. Kısa anlatımlaBACKUP
yedek alma işlemidir. Sonundaki uzantısı.bak
olarak bitmek zorunda olduğunu unutmayın.
BACKUP DATABASE testDB TO DISK = 'D:\backups\testDB.bak';
Seçtiğiniz yere anında yedek alacaktır. (Uzun veritabanlarında işlem sürer.) Bu tüm BACKUP
alınması anlamına gelir. DIFFERENTIAL
biçimde almak isteyenleri aşağıya beklerim. (Bu ne lan? Diyenleri görüyorum. DIFFERENTIAL Backup
türü diğer aldığınız yedekleme ile şu anki veritabanını karşılaştırır ve sadece değişikliklerin yedeklerini alır.)
BACKUP DATABASE testDB TO DISK = 'D:\backups\testDB.bak' WITH DIFFERENTIAL;