VERİ EKLEME
INSERT’Ü KULLANMAK
Insert deyiminin amacı veriyi tabloya yerleştirmektir. Bu nedenle minimal formunda INSERT şu temel elemanlara ihtiyaç duyar:
· İfadeyi başlatıcak olan INSERT emri
· INSERT işlemi için hedef
· VALUES anahtar kelimesi ile belirtilen değerlerin listesi.
· Böylece minimal yapı aşağıdaki gibi olur:
INSERT authors VALUES (‘010-10-1012’, ‘lname’, ‘fname’, ‘5551212’, NULL, NULL, 0)
Tip: Bazı veritabanlarında VALUES sözcüğüne ihtiyaç duymayacaksınızdır. VALUES, SQL3 standartıyla gerekli hale getirilmişti.
NULL değerini, tablonun o alanı NULL’a izin veriyorsa kullanabilirsiniz. Aksi takdirde hata verir.
SQL programcısı hangi sütunların NULL’a izin verdiğini nerden bilecek sorusunun cevabı şöyledir: Eğer veritabanı yönetici araçlarına erişiminiz yoksa veritabanı yöneticisine size söylemesini istemelisiniz. Eğer erişebiliyorsanız, o araçlardan biri size söyleyecektir.
INSERT’teki bir diğer sınırlama da anahtar sınırlaması (key constraints)dır. Anahtar, kayıtları birbirinden ayıran bir ayraçtır (author_id gibi). Buradaki sınırlama ise şöyledir: Eğer bir kayıt ekliyorsak önce authors’a eklersek sorun çıkmaz. Ama önce titleauthor’a ekliyecek olursak authors’ta öyle bir kayıt bulunmadığından hata verecektir. Bu sınırlama, anahtarın birden çok tabloda bulunduğu zamanlar ortaya çıkar.
Tip: Grafik ortamda key’i Database Management sayesinde küçük bir ikonla belirtebiliriz.
Diğer bir sınırlama da kontrol sınırlama (check constraint)dir. Bu sınırlama, girilen değerin check constraints’te belirtilen şekilde olup olmadığına bakar. Ona göre INSERT’ü kabul veya red eder. Constraint expression örneğine bakarsak:
([au_id] like ‘[0-9][0-9][0-9][0-9][0-9][0-9][0-9]’)
Burada, sütun ismini en sola yazıyor, peşine like komutunu ekliyor ve tek tırnak içinde girilmesi gereken ifadeyi belirtiyoruz. (Bu örnekte, 7 haneli, 0 ile 9 arasında değişebilen rakamlardan oluşan sayı girilmesi isteniyor.)
INSERT emri, INTO kullanmaya izin verir. (INSERT INTO) Böylece deyim, okuma açısından daha anlaşılır olur.
Diğer bir yapı ise sütun isimlerini teker teker girmektir. Genel yapı:
INSERT INTO authors (au_id, au_lname, au_fname) VALUES (‘010-10’, ‘lname’, ‘fname’)
Burada, girilmeyen sütunlar Null olmaz. Sütun özelliklerinde bulunan varsayılan değer bölümündeki değer olur. Eğer sütun isimlerini vermezsek ilk değere ilk sütun, ikinci değere ikinci sütun…. a göre yerleştirilir.
Gömülü SQL INSERT’lerde sütun isimlerinin listesini kullanmalıyız.
Not: Eğer INSERT işlemini kullanan bir programa sütun eklemek istersek o sütunu ya nullable (hükümsüz olabilen sütun) yapmalısınız ya da o sütunu varsayılan bir değerle doldurmak lazımdır. Aksi takdirde ya INSERT’e sütunu eklemeliyiz ya da hata mesajıyla karşılaşırız.
Not: Aynı değeri birden çok tabloya eklemek istiyorsanız her biri için ayrı INSERT kullanmalısınız.
Sütun listesini, herhangi bir kişi tablonun tanımlanmasında değişiklikler yaptığında kodun etkilenmemesi için kullanırız.
Verinin tipini değiştirmek için 2 yol vardır: CAST ve CONVERT:
CAST (SahipOlduğunuzVeriTipi AS OlmasınıİstediğinizVeriTipi)
CONVERT (OlmasınıİstediğinizVeriTipi, SahipOlduğunuzVeriTipi, (OpsiyonelStilTanımlayıcı))
Soru: Veriyi eklemeden önce herhangi bir yolla kontrol etmeli miyiz?
Cevap: Veritabanı programlamada bir ana kural vardır:İşe yaramayanı veritabanına koymamak. Kullanıcıdan değerleri aldığında, onların doğru (istenilen) veri tipinde olduğunu ve doğru formatta olduğunu kontrol etmek gerekir. Eğer her defasında yanlış formatta sonuç geliyorsa CAST veya CONVERT kullanırız. Veri doğruluğu için birden çok gereksiz kontroller karışık programlar için kötü bir fikir değildir. Her zaman, özellikle Windows programlarda sizin farkında olmadığınız program boyunca bir yol daha vardır. Yol belki de bütün kontrollere engel olarak veriyi veritabanına sokmaktır. Hatırlarsanız, kötü veriler her veritabanının kullanıcı ömrünü zorlaştırır.
SELECT’İ INSERT’LE KULLANMAK
INSERT’ü kullanırken önce yapmamız gereken tablo oluşturulmamışsa oluşturmanızdır (SQL Server’da Enterprise Manager ile). Diğer husus ise bu türde SELECT * ı kullanmamanızdır. Aşağıdaki örneği incelersek:
INSERT INTO temptable SELECT authors.au_id, au_lname, au_fname, phone, address, city, titles.title_id, title, type, pubdate FROM authors INNER JOIN titleauthor ON authors.au_id = titleauthor.au_id INNER JOIN titles ON titles.title_id = titleauthor.title_id
Burada SELECT * ın kullanılması teknik olarak 2 tane au_id elde etmemize neden olacaktır. (Aynı şekilde title_id de) Bu hatadan kaçınmak için tablonun bütün sütunlarını liste halinde alıyoruz.
Aynı yapıyla INSERT te SELECT içinde WHERE ve HAVING sözcüklerini de kullanabiliriz.
SELECT INTO’YU KULLANMAK
Bazıları tablo oluşturmanız gerektiğini ama henüz tablo oluşturmayı görmediğinizi söyleyebilirler. Aslında, tablo oluşturmak için tablo oluşturmayı bilmenize gerek yoktur. Tek bilmeniz gereken küçük bir hiledir. SELECT deyiminin, tek bir SQL deyiminde kayıtları seçen, tablo oluşturan ve kayıtları tabloya yerleştiren bir şekli vardır. Bu deyim SELECT … INTO dur. Aşağıdaki örneği inceleyelim:
SELECT authors.au_id, au_lname, au_fname, phone, address, city, titles.title_id, title, type, pub_id, pub_date INTO temptable FROM authors INNER JOIN titleauthor ON authors.au_id = titleauthor.au_id INNER JOIN titles ON titles.title_id = titleauthor.title_id
Kabul ediniz ki bu kullanışlı bir hiledir. Burada da SELECT * kullanamayız (belirsizlikten dolayı). INTO sözcüğü INSERT INTO gibidir. Farkı ise tabloyu oluşturmasıdır. FROM, WHERE, HAVING… istediğimizi kullanabiliriz. Ayrıca yeni bir satır da ekleyebiliriz. (…. INTO temptable, 1 AS NewColumn FROM…) Bu örnekte içeriği tüm kayıtlar için 1 olan NewColumn isminde bir sütun oluşturulur.
VERİYİ GÜNCELLEMEK
Bu ünitede tabloda bulunan veriyi değiştirmeyi inceleyeceğiz. Veritabanında hazır yerleştirilmiş bir veriyi değiştirmek için kullanılan SQL emri UPDATE’dir. UPDATE, veriyi değiştirmek için esneklik sağlarken aynı zamanda da tablodaki bütün verileri değiştirmeye gücü yettiğinden tehlikeli bir komuttur. Kritik bir noktayı da vurgulamalıyız ki: WHERE veya HAVING’i kullanmayı unutmamalısınız. Eğer unutursanız tablodaki bütün kayıtlar değiştirilecektir.
UPDATE’İ KULLANMAK
Güncelleme deyimi UPDATE emri ile başlar, güncellenecek tablonun ismiyle devam ettirilir, atama operatörü ve ardından sütuna yerleştirilecek değerle sonlandırılır. Güncelleme için sadece bir tablo kullanabilirsiniz. Buna karşın birden çok sütunu virgüllerle ayırarak aşağıdaki şekilde güncelleyebilirsiniz:
UPDATE authors SET Contract=1, Phone=’’
WHERE SÖZCÜĞÜ EKLEMEK
Eğer veri tabanınızdaki bütün kayıtları güncellemek istemiyorsanız WHERE yapısını kullanmalısınız. Örneğin:
UPDATE authors SET Conract=1 WHERE Zip=’40205’
WHERE yapısını kullanınca kayıtların tanımlanması önem kazanıyor.
Herhangi bir matematiksel veya mantıksal karşılaştırma işlemlerinde WHERE yapısı iyi çalışır. Ayrıca LIKE yapısıyla da kullanabiliriz. Örneğin:
UPDATE authors SET Contract=1 WHERE Zip LIKE ‘402%’
Bu örnekte dizi 402 ile başlar ve diğer karakterler herhangi bir karakter kombinasyonu olabilir (40205, 40213, 402AB).
Tip: Eğer wildcard karakterleri (% gibi) kullanma ihtiyacı duyarsanız, bu karakterleri özel anlam taşımaması için köşeli parantez içinde yazmalısınız. (‘4020[%]’ gibi) Diğer bir örneği incelersek:
UPDATE authors SET Contract=1 WHERE Zip NOT LIKE ‘402%’
Bu örnek NOT sözcüğünün kullanılmasını gösteriyor. Bu, ifadenin tersini alır.
UPDATE authors SET Contract=1 WHERE Zip LIKE ‘[456]0205’
Bu örnek, ilk karakter olarak köşeli parantezler içinde kullanılan karakterlerden birisinin gelmesi gerektiğini gösteriyor. (40205,50205,60205) Başka bir örnek:
UPDATE authors SET Contract=1 WHERE Zip LIKE ‘[^456]0205’
Burada kullanılan ^ tersi anlamındadır. Yani ilk karakter 4,5,6 haricinde başka bir karakter, diğerleri 0205 olmalı anlamındadır.
UPDATE authors SET Contract WHERE Zip LIKE ‘4020_’
Burada, alt çizgi karakteri, bu yere geçerli bir karakter konulacağını gösteriyor. Böylece 4020 ile başlayan bir sonuç istenmiş oluyor.
WHERE yapılarında kullanabileceğimiz diğer ilginç ayar ise IN sözcüğünü kullanmanızdır. IN’i aşağıda da gösterildiği gibi sütun değerlerinin bir listesini belirlemek için kullanırız:
UPDATE authors SET Contract=1 WHERE Zip IN (‘40205’, ‘40213’)
IN, argümanı parantezler arasında virgüllerle ayrılmış bir değerler listesi olarak alır. Belirtilen sütunda IN’den sonra gelen, parantezlerle belirtilen değerler listesi elemanlarının olup olmadığına bakar. Hangi kayıdın sütununda o değerlerden birisini bulursa o kayıdı günceller.
WHERE discounttype LIKE ‘%20!%%’ ESCAPE ‘!’
Bu örnekte ilk ve son %’ler wildcard karakter olarak algılanıyor. ESCAPE karakter olarak belirlenen ! den sonra gelen karakter olan % ise karakter olarak algılanıyor. Yani bu örnekte 20% içeren elamanlar aranıyor.
Tip: Wildcard karakterleri string’inizde ESCAPE yardımıyla harf olarak kullanabilirsiniz. Yani, # , % gibi ifadeler sade şekilde yazılsalar rakam, harf gibi anlamları vardır. Bunları ESCAPE yardımıyla string içinde gerçek harf olarak kullanabiliriz. Burada yapmamız gereken, normal harf olarak kullanacağımız karakterden önce bir ESCAPE karakter kullanmak ve bu ESCAPE karakteri sonda ESCAPE ifadesi ile belirtmektir.
HAVING YAPISI EKLEMEK
Biraz karmaşık gözüken bir örneğe bakarsak:
UPDATE sales SET payterms=’cash only’ FROM (SELECT title_id FROM sales GROUP BY title_id HAVING SUM(qty)>30) AS MySelect WHERE sales.title_id = MySelect.title_id
Bu örnekteki UPDATE’i de SELECT’i de daha önce gördük. Görmediğimiz, bu metodların birbirine bağlanma şekliydi. FROM’la, FROM anahtar sözcüğünü takip eden bilgiye göre sales tablosundan kayıtların bir listesini alıyoruz. Bu kayıt listesine AS yardımıyla sonradan kullanabilmek için isim veriyoruz ve WHERE yapısında bu kayıtları kullanıyoruz. Diğer bir deyişle, sales tablosunun title_id sütunu gruplandırılıp, qty toplamı 30’dan büyük olanlar MySelect tablosu adıyla seçilip, sales tablosundan MySelect’te olanlarının payterm sütunu ‘cash only’ ye setleniyor.
BİRDEN ÇOK TABLO KULLANMAK
UPDATE titles SET ytd_sales=titles.ytd_sales+ SUM(sales.qty) FROM titles, sales WHERE titles.title_id=sales.title_id AND DATEPART(yyy, sales.ord_date)=2000
Bu örnekte birden çok tablodan eleman alıyoruz. (Ama birden çok tabloyu tek UPDATE ile güncelleyemeyiz) Burada dikkat çeken bir konu, WHERE yapısında birden çok olan koşulu AND ifadesi ile birleştirebiliyor olabilmemizdir. Ayrıca DATEPART fonksiyonu da çok kullanışlıdır. Parantez içindeki ilk ifade neyin çekileceği, ikinci ifade hangi sütundan çekileceğini belirtir. Datepart int değer döndürür. (yıl-yy,yyyy. çeyrek-qq,q. ay-mm,m. yılın günü-dy,y. gün-dd,d. hafta-wk, ww. saat-Hh. dakika-min. saniye-ss, milisaniye-Ms.)
Tip: FROM’un içinde SELECT’i kullandığınız zaman, SELECT için ayrı bir WHERE yapısı kullanmamalısınız. Bütün WHERE koşulları tek bir WHERE yapısında FROM sözcüğü ile ilişkili olarak kullanılmadır. Örneğin:
UPDATE authors SET Contract=1 FROM (SELECT authors.au_id, titleauthor.title_id FROM authors INNER JOIN titleauthor ON authors.au_id = titleauthor.au_id) AS MySelect WHERE MySelect.au_id = authors.au_id AND MySELECT.title_id IN (‘BU1111’, ‘PC9999’)
Not: UPDATE’de HAVING veya JOIN kullanmak için FROM (SELECT …) yapısına ihtiyacınız vardır.
VERİYİ SİLMEK
SQL, veriyi silmek için 2 seçenek sunuyor: DELETE ve TRUNCATE TABLE. Herhangi bir geri alma yolu yoktur. Sonuçlar kalıcıdır.
Tip: Veri silme işleminden önce veritabanınızın backup’ını almalısınız.
Silme işlemi için 2 yol var:
DELETE FROM authors
TRUNCATE TABLE authors
Bu iki ifade de tablodaki bütün verileri siler. Tablonun sütun yapısı sabit kalır. Böylece silme işleminden sonra yeni veri rahatlıkla eklenebilir.
Peki, bu iki silme işleminin farkları nelerdir? Öncelikle şunu söyleyebiliriz ki: DELETE’i bütün SQL veritabanları desteklerken TRUNCATE TABLE’ı hepsi desteklemez. (MsSQLServer bir çok durumda TRUNCATE TABLE’ı desteklemesine rağmen bir veritabanından diğerine tablo kopyalarken Data Transformation Services’ı kullanıyorsanız ana veritabanındaki tablonun verilerini silmek için TRUNCATE TABLE’ı kullanmanıza izin vermez)
Bununla birlikte TRUNCATE TABLE yalnızca, tablonun bütün elemanlarını silinecekse kullanılabilir. DELETE ise kayıtlarda seçime olanak sağlar.
WHERE yapısını diğer deyimlerde kullandığımız gibi kullanırız.
Bazı SQL veritabanları, onlardan birisi silindiğinde hepsi silinen ilişkili kayıtları tanımlamanıza izin verir. Bu tür silme işlemine cascading delete adı verilir.
KONTROLLÜ SİLME İÇİN SORGULAMA KULLANMA
DELETE FROM titleauthor WHERE title_id IN (SELECT title_id FROM sales GROUP BY title_id HAVING SUM(qty)>30)
Bu örnekte sorgulama title_author’daki her bir title_id’yi SELECT deyiminin sonucuyla karşılaştırıyor. Ve SELECT deyiminin sonucundaki ifadeyle title_id’si aynı olan kayıtları tablodan siliyor.
Bu SQL yapısı bütün SQL veritabanlarında kullanılır. Microsoft’un Transact SQL’i aşağıdaki yapıyla JOIN’i de kullanıyor:
DELETE titleauthor FROM titleauthor INNER JOIN titles ON titleauthor.title_id = titles.title_id WHERE titles.title_id LIKE ‘%novel%’
Microsoft, toplama fonksiyonları ve gruplandırmaya bu yapıda izin vermiyor. Yani toplama fonksiyonu ya da gruplandırma kullanacaksanız JOIN kullanamazsınız.
Yanlış kayıtları silmemenin en iyi yolu her kayıdın kendine has bir kimlik no’sunun olmasıdır. Diğer bir yol da transaction kullanarak veriyi silmeden önce ne olacağını görebilmektir.
Eğer DELETE’i bir SELECT koşulu ile kullanmayı planlıyorsanız her zaman SELECT INTO’yu kullanın. SELECT INTO, tablo oluşturarak verilerin kopyasını oraya atar. Böylece hangi kayıtların tablodan silindiğini görebilirsiniz.
TRANSACTION’LARI KULLANMAK
TRANSACTION size, kazayla silinen kayıt için bir kurtarma noktası sağlar. Bu kurtarma noktası tam bir geri alma değildir. Çünkü transaction’a tamamlamasını söylediğiniz zaman yaptığınız işlemlerden geri dönemezsiniz. Buna rağmen transaction ne olacağını size gösterir ve buna göre karar vermenize olanak sağlar.
Transaction’lar ya tamamı başarılı ya da tamamı başarısız olması gereken SQL deyim gruplarıdır. Grup, tek bir SQL deyimi kadar küçük olabilir. Transaction işleminde herhangi bir hata oluştuğunda bütün emirler başarısız olur. Hiç hata olmazsa, hepsi başarılı olur. Transaction’ın bir dönüm noktası vardır. Bu noktada hataları kontrol edebilir ve transaction’ı nasıl tamamlayacağınıza karar verebilirsiniz.
Transaction’ı uygulamak veya geri dönmek için başlangıç ve bitiş noktalarını işaretlemek gerekir. Bu amaçla birkaç T-SQL deyimi vardır:
· BEGIN: Başlangıç noktasını belirler.
· COMMIT: Transaction’ı veritabanının geri dönülmeyen kalıcı parçası yapar.
· ROLLBACK: Transaction’ın başından itibaren yapılanları unutmak istediğimizi belirtir.
· SAVE: Kısmi geri almalar sağlamak için özel işaretçiyi belirtir.
BEGIN TRAN: Bir birimin başlangıcı olan işareti gösterir. Bazı sebeplerden dolayı başaramadığımız veya transaction’ın uygulanmamasını istediğimizde bütün veritabanı işlemlerinin geri döndürüleceği noktadır. Yapısı şöyledir:
BEGIN TRAN[SACTION] [transactionName | @transactionVariable]
COMMIT TRAN: Transaction’ın uygulanması, tamamlanmış transaction’ın sonlandırılmasıdır. Bu, transaction’ı kalıcı yapar (sistem hatası olsa bile). Transaction’ın uyguladıklarını geri almanın tek yolu, ilk transaction’ın fonksiyon olarak tersi olan başka bir transaction oluşturmaktır. Yapısı:
COMMIT TRAN[SACTION] [transactionName | @transactionVariable]
ROLLBACK TRAN: Rollback, transaction’ı başa döndürür. Begin’den itibaren yapılan işlemler unutulur. Begin’e dönmenin tek istisnası savepointler kullanmaktır (Begin yerine bu saklı noktalara da dönebilirsiniz). Yapısı:
ROLLBACK TRAN[SACTION] [transactionName | savepointName | @transactionVariable]
SAVE TRAN: Transaction’ı saklamak esasen bir işaret koymaktır. Bu noktadan sonraki işlemleri geri almak isterseniz Rollback’te bu işaretin adını verebilirsiniz. Bir transaction’da birden çok işaret koyabilirsiniz. Yapısı:
SAVE TRAN[SACTION] [savepointName | @savepointVariable]
Bir örnek incelersek:
BEGIN TRAN TranStart
INSERT INTO Orders DEFAULT VALUES
SAVE TRAN FirstPoint
INSERT INTO Orders DEFAULT VALUES
ROLLBACK TRAN FirstPoint
INSERT INTO Orders DEFAULT VALUES
SAVE TRAN SecondPoint
INSERT INTO Orders DEFAULT VALUES
ROLLBACK TRAN SecondPoint
INSERT INTO Orders DEFAULT VALUES
COMMIT TRAN TranStart
Burada Transaction başlatılıyor, bir kayıt ekleniyor ve buraya işaret koyuyor. Sonra bir kayıt daha ekliyor sonra ilk koyduğu işarete geri dönüyor. Ardından yine satır ekliyor ve ikinci bir işaret daha koyuyor. Bir kayıt daha ekleyip ikinci işarete geri dönüyor. Son olarak bir kayıt daha ekliyor ve bu transaction’ı saklıyor, yani veritabanının bir parçası haline getiriyor (değişiklikler kaydediliyor). Burada ROLLBACK deyiminde, saklama noktasının ismi verilmemiş olsa veya begin’deki isim verilmiş olsaydı en başa dönerdi.