Professional Documents
Culture Documents
1
sistemleri, veri kümelerinin düzenli biçimde tutulduğu ve bu verilerin çeşitli yazılımlar
aracılığıyla yönetildiği ortamlardır.
Bu derste “veri tabanı programlama” konusunda bazı ileri konulara yer verilmektedir. Veri
tabanı programlama, özellikle uygulama geliştiricilerin başvurdukları bir yoldur. Bir takım
veri tabanı nesneleri bu yolla tanımlanarak, farklı programlarda yeniden
kullanılabilmektedir. Özellikle fonksiyonlar, yordamlar ve paketlerin yaratılması önem
taşımaktadır.
Veri tabanı programlama, veri tabanı bağımlıdır. Bunun anlamı, her veri tabanı yazılımının
kendi özel programlama dili bulunmaktadır. Bu derste, ORACLE veri tabanı göz önüne
alınmış ve onun PL/SQL veri tabanı programlama dili üzerinde durulmuştur.
İleri veri tabanı kavramlarını anlayabilmek için, öncelikle standart veri tabanı dili olan
SQL’i iyi bilmek gerekiyor. Bunu sağlamak için dersin ilk dört bölümü SQL’e ayrılmıştır.
Kalan bölümlerde ise PL/SQL ile veri tabanı programlaması işlenmektedir.
Bu bölümde;
anlatılmaktadır.
Bölüm Hedefi
Bu bölümde veri tabanı sistemlerine kısa bir giriş
yapılarak, SQL yapısal programlama dilinin esasları
üzerinde durulacak ve aşağıda sıralanan konular
incelenecektir:
2
• Karşılaştırma işleçleri
• Mantıksal işleçlerin kullanımı
• İşleçlerin işlem sırası
• Verinin sıralanması
3
1.1.2 Sıralı Dosyalar
Klasik bilgisayar dosyaları birbirinden bağımsız; muhasebe, stok, pazarlama, üretim ve
diğer uygulamalarda kullanılmak üzere hazırlanır. Bu dosyalar, sıralı ya da doğrudan
erişim yöntemleri kullanılarak işlenir. Sıralı erişimde, dosyanın tüm kayıtları tek tek
taranarak istenilen kayıtlara ulaşılır. Doğrudan erişim yönteminde ise, kayıtlar tek tek
sırayla okutulmaz, istenilen kayıda doğrudan erişerek işlenir.
Sıralı dosyalar, bir başka deyişle ardışık dosyalar, içerdiği kayıtlara birinci kayıttan
başlamak üzere sırayla erişim yapmak üzere tasarlanmış dosyalardır. Bu tür dosyaların
kayıtlarına ardışık olarak erişilebilmesine karşılık, kayıtlar fiziksel olarak ardışık
olmayabilir. Sıralı dosyaların herbir kayıtına ardışık olarak erişilmesi bazı durumlarda
yararlı olmasına rağmen, bazı uygulamalarda sorunlar yaratır.
Örneğin; okuldaki tüm öğrencilerin tümü listelenecek ise, kayıtlara peşpeşe erişim söz
konusudur. Bu durumda dosyanın sıralı olarak tasarlanmış olması sorun yaratmaz. Ancak
sadece birkaç öğrencinin listelenmesi isteniliyorsa, tüm öğrencilerin okunarak bu listenin
elde edilmesi uygun bir yöntem olmayacaktır. Söz konusu öğrencilere doğrudan erişilmesi
en uygun yoldur.
4
Doğrudan erişimli dosyaların en tanınmışı, indeksli dosyalar olarak bilinir. İndeksli
dosyalar veya bir başka deyişle indeks sıralı dosyalar, veri dosyasından ayrı olarak bir
indeks dosyasının oluşturulması ile birlikte hazırlanır. Bir dosya için oluşturulan indeks;
söz konusu dosyanın anahtarları ile bu anahtarların disk üzerinde bulunduğu adresi içerir.
Anahtar alan, erişimde kulanılmak üzere seçilen alan olarak değerlendirilir.
Örneğin; öğrenci dosyasında, öğrenci numarasını içeren alanının indeks alanı olarak
tasarlandığını varsayalım. Herhangi bir öğrencinin bilgilerine ulaşmak söz konusu
olduğunda; bu numara önce indeks üzerinde aranılarak bulunur ve söz konusu kayıda
ilişkin adres bilgisi elde edilerek, bu adrese doğrudan erişilir.
5
Veri Tabanı Yönetim Sistemleri (VTYS) yaklaşımında veri girişi ve depolanması, veriye
erişen uygulama programlarından bağımsızdır. Klasik dosya kullanımında ise, kayıt
desenleri ve dosya yapılarında ortaya çıkabilecek en ufak bir değişiklik bile uygulama
programlarının değişmesine ve yeniden derlenmesine neden olmaktadır.
Veri tabanı sistemleri bilgisayar sistemlerinin önemli bir bileşeni olarak değerlendirilir.
Veri tabanı yönetim sistemleri (VTYS), birbirleriyle ilişkili veri ve programlar
topluluğundan oluşmaktadır. Veri topluluğu bir “veri tabanı” olarak değerlendirilir. Veri
tabanı bir kuruluşa ilişkin bilgilerin yer aldığı ortamdır. Veri tabanı sistemleri, veri
kümelerinin düzenli biçimde tutulduğu ve bu verilerin çeşitli yazılımlar aracılığıyla
yönetildiği ortamlardır.
6
7
8
1.4 Veri Modelleri
Veri Tabanı Yönetim Sistemleri belirli bir veri modeline dayanır. Bir veri tabanı yapısının
temelini veri modeli kavramı oluşturmaktadır. Veriyi mantıksal düzeyde düzenlemek için;
kullanılan kavramlar, yapılar ve işlemler topluluğuna “Veri Modeli” denir.
Şu ana dek birçok veri modeli geliştirilmiştir. Başlıca veri modelleri yandaki animasyonda
yer almaktadır.
Sayılan bu veri modellerinin ilk ikisi şu anda kullanılmamaktadır. En yaygın kullanılanı ise,
İlişkisel Veri Modelidir. Günümüzde kullanılan VTYS’lerin hemen hemen tümü ilişkisel veri
modeline dayalıdır. Son zamanlarda ortaya çıkan Nesneye Yönelik Veri Modeli, İlişkisel
Veri Modeli ile birlikte bazı VTYS’lerde kullanılmaktadır.
9
1.5.1 Sorgulama İşlemleri
SQL'de sorgulama işlemleri, SELECT deyimi yardımıyla yerine getirilir. SELECT deyimi
temel olarak üç farklı işlemi yerine getirmek için kullanılır:
SELECT [DISTINCT] { * |
sütun, ....}
FROM tablo;
Tanım içinde bazı SQL anahtar kelimelerine yer verilmektedir. Bu anahtar kelimeler, SQL
'in kendi özel kelimeleridir ve aynen bu şekilde ifade edilmelidir.
10
Çift kayıtları önleyen anahtar
DISTINCT
kelimedir.
Tanımdaki her bir işaretin veya farklı gösterimin hangi anlama geldiğini aşağıdaki
tablodan görebilirsiniz.
11
1.5.1.3 Tablonun Tüm Satırlarını Seçmek
Bir tablonun tüm sütunlarını seçmek söz konusu ise, SELECT deyimi içinde sütun isimleri
yerine; * işareti kullanılır.
Örnek
12
Bölümün bulunduğu
Konumu
yerin adıdır.
Bu tablonun içerdiği tüm verileri görüntülemek istiyoruz. Bunun için aşağıda belirtilen
SELECT deyimi düzenlenir:
SELECT * FROM
BÖLÜM;
13
Örnek
14
1.5.2 Aritmetik İfadeler
Aritmetik ifadeler; sütun isimleri, sabit sayısal değerler ve aritmetik işleçlerden oluşur.
Örneğin, bir tablonun ÜCRET isimli sütunundaki sayısal değeri 12 ile çarpmak için,
ÜCRET*12
biçiminde bir ifade tanımlanabilir. SELECT deyimi içinde bir ifade tanımlandığında, bu
ifade ayrı bir sütun biçiminde yaratılmış olacaktır.
Örnek
15
! Aritmetik İşleçleri ve anlamlarını tekrar görmek için TEKRAR düğmesine
tıklayınız.
Örnek
16
PERSONEL tablosunun, PERSONEL ve ÜCRET isimli iki sütunu listelenecektir. Burada
ÜCRET, aylık ücret rakamını içermektedir. Yıllık ücrete 500 değerini eklemek istiyoruz.
Söz konusu hesaplamayı sağlayan ifade şu şekilde olacaktır;
12*ÜCRET+500
Buna göre * işlecinin önceliğinden dolayı önce 12 ile ÜCRET çarpılacak ve bulunan
değere 500 eklenecektir. Amacımıza uygun SELECT deyimi şu şekilde olabilir;
! Aritmetik İşleçlerin işlem sırasını tekrar görmek için TEKRAR düğmesine tıklayınız.
17
1.5.2.2 Aritmetik İfadelerde Parantezlerin Kullanımı
Parantezler, aritmetik ifadeler içinde diğer tüm işleçlere göre bir önceliğe sahiptir. Önce
parantez içindeki işlemler gerçekleştirilir.
Örnek
Önceki kısımdaki örnekte 12*ÜCRET+500 biçiminde bir tanım yaparak, yıllık ücrete zam
yapmıştık. Bu kez aylık ücrete 500 zam yapmak istiyoruz. Amacımıza uygun ifade şu
şekilde olabilir:
12*(ÜCRET+500)
Bu durumda, ücret sütununun içerdiği değere 500 eklenir ve bulunan değer 12 ile
çarpılır. Amacımıza uygun SELECT deyimi şu şekilde olabilir;
18
SELECT PERSONEL_NO, ADI, 12*(ÜCRET+500)
FROM PERSONEL;
Örnek
19
Eğer bir aritmetik ifade içinde NULL değer içeren bir sütun varsa, ifade ne olursa olsun o
satırlarla ilgili sonuç da NULL olarak elde edilir. KOMİSYON isimli sütunun NULL değerler
içerdiği bilinmektedir. O halde;
deyimi çalıştırıldığında, tanımlanan aritmetik ifade her satır için NULL değerler
üretecektir. NULL ile yapılan hesaplamalara dikkat ediniz. Örneğin,
12*7000+NULL → NULL
olduğu unutulmamalıdır.
20
Örnek
PERSONEL tablosunun PERSONEL sütunu için İSİM, ücret sütunu için AYLIK_ÜCRET
takma isimlerini atayacağız. Ayrıca yıllık ücreti hesaplayarak bu sütuna da
YILLIK_ÜCRET takma ismini vermek istiyoruz. Amacımıza uygun SELECT deyimi şu
şekilde olabilir;
21
1.5.4 Sütun İçeriklerini Birleştirme
Sütunların içerdikleri değerleri, birbiriyle ya da bir başka karakter dizisi ile birleştirerek
yeni değerler elde edilebilir. Birleştirme işleci olarak (||) simgesi kullanılabilir. Bu işlecin
kulllanımı veri tabanlarında farklılık gösterebilir. Örneğin, ORACLE veri tabanında (||); MS
Access veri tabanında ise (&) işleci aynı amaçla kullanılır.
Örnek
Personel adı ve görev bilgisini birleştirerek, iki sütun bilgisi arasına "-" işaretini
yerleştirmek ve tek sütun biçiminde görüntülemek istiyoruz. SELECT deyimini ORACLE
veri tabanı için şu şekilde düzenleyebiliriz;
Aynı amaca SELECT deyimini MS Access veri tabanında şu şekilde kullanarak ulaşabiliriz;
22
1.5.5 Aynı Değere Sahip Satırlar
Bir SELECT deyimi çalıştırıldığında, aynı değerlere sahip satırların görüntülenmesi
engellenemez. Örneğin,
SELECT BÖLÜM_NO
FROM PERSONEL;
Örnek
23
PERSONEL tablosunun BÖLÜM_NO sütunundaki verileri tekrarlatmadan listelemek
istiyoruz. Bunun için aşağıda belirtilen yol izlenir;
Tablonun belirli kısımlarını seçmek için WHERE sözcüğü kullanılır. Bu sözcük SELECT
deyimi içinde aşağıda gösterildiği biçimde yer alır. WHERE sözcüğü içinde tanımlanan
koşul; sütun içindeki değerleri, literal değerleri, aritmetik ifadeleri veya fonksiyonları
içerebilir.
24
Örnek
PERSONEL tablosu içinde yer alan personel arasında görevi MEMUR olanları seçerek
listelemek istiyoruz. Amacımıza uygun SELECT deyimi şu şekilde düzenlenebilir;
SELECT ADI,GÖREVİ,BÖLÜM_NO
FROM PERSONEL
WHERE GÖREVİ='MEMUR';
25
! Karşılaştırma İşleçlerini ve anlamlarını tekrar görmek için 'TEKRAR'
düğmesine tıklayınız.
Örnek
Ücreti 2500'den daha az ya da eşit olan personeli seçerek listelemek istiyoruz. Amacımıza
uyan SELECT deyimi şu şekildedir;
SELECT ADI,GÖREVİ,ÜCRET
FROM PERSONEL
WHERE ÜCRET<=2500;
26
1.5.6.2 Diğer Karşılaştırma İşleçleri
Şu ana kadar öğrendiğimiz karşılaştırma işleçleri dışında, bazı özel amaçlarla
kullanılabilecek başka karşılaştırma işleçleri de bulunmaktadır. Aşağıdaki etkileşimli
listeden bu işleçleri ve anlamlarını görebilirsiniz.
27
1.5.6.2.1 BETWEEN … AND ... İşleci
Bu işleç; iki değer arasında kalan satırları belirlemek ve bir alt değer ile bir üst değer
arasında kalan değerleri seçmek için kullanılabilir.
Örnek
Ücreti 3000 ile 5000 arasında olan personeli listelemek için SELECT deyimi şu şekilde
kullanılabilir;
SELECT ADI,ÜCRET
FROM PERSONEL
WHERE ÜCRET BETWEEN 3000 AND 5000;
28
1.5.6.2.2 IN İşleci
Sütun değerlerinin, bir listedeki değerler ile karşılaştırılması söz konusu ise, SELECT
deyimi ile birlikte IN işleci kullanılır. Liste içindeki değerler birbirlerinden virgüllerle
ayrılır. IN işleci herhangi bir veri türü için kullanılabilir. Karakter ve tarih veri türleri,
tırnak işareti arasında yer almalıdır.
IN( liste)
Örnek
Görevi MEMUR veya PAZARLAMACI olan tüm personeli listelemek istiyoruz. Bunun için IN
işlecini kullanabiliriz.
SELECT ADI,GÖREVİ
FROM PERSONEL
WHERE GÖREVİ IN('MEMUR', 'PAZARLAMACI');
29
1.5.6.2.3 LIKE İşleci
WHERE sözcüğü ile, bir sütunun değerini tam olarak değil, sadece bir kısmını belirterek
arayabiliriz. Örneğin, adı "A" harfi ile başlayan personeli aramak gibi. Bu tür amaçlar için
LIKE işleci kullanılabilir. Bu operatör ile birlikte, farklı amaçlar için (%) veya (_)
işaretleri kullanılabilir.
Bunlardan (%) işareti, bu işaretten önce ya da sonra gelen karakterler için arama
yapılacağını belirtir. Örneğin, "A" harfi ile başlayanlar, 'A%' biçiminde; "S" harfi ile
bitenler, '%S' biçiminde ifade edilir. (_) işareti ise herhangi bir tek karakteri simgeler.
LIKE ile birlikte kullanılan (%) işareti yerine, MS Access'de (*) işareti kullanılır.
LIKE ( kural)
Örnek
Adı "A" harfi ile başlayan tüm personeli listelemek istiyoruz. Amacımıza uygun SELECT
deyimi şu şekilde düzenlenebilir;
30
1.5.6.2.4 IS NULL İşleci
NULL değeri; var olmayan, atanamayan ve bilinmeyen bir değer olduğu için NULL ile ilgili
karşılaştırmalarda (=) işleci kullanılamaz. Bunun yerine, sütun değerlerinin NULL olup
olmadığını denetlemek için IS NULL işleci kullanılır.
Örnek
31
Yukarıdaki sorgulamanın sonucunu görmek için linke tıklayınız
32
1.5.6.3.1 AND İşleci
AND işleci; iki koşulun yandaki doğruluk değeri tablosuna göre TRUE veya FALSE
değerinin döndürülmesini sağlar. Eğer, her iki koşulun doğruluk değeri TRUE ise istenen
seçme işlemi gerçekleşir.
Örnek
Ücreti 2000'e eşit veya daha büyük ve işi MEMUR olan personeli listelemek istiyoruz.
Amacımıza uygun SELECT deyimi, şu şekilde olabilir;
Eğer belirli bir personelin ücreti 2000'e eşit veya daha fazla ise; ÜCRET>=2000 koşulu
doğru olacaktır. Yani TRUE değerini döndürür. Aynı personelin görevi memur ise yani,
GÖREVİ='MEMUR' koşulu doğru ise, bu koşul da TRUE değerini döndürür. Böylece her iki
koşul için TRUE değerlerine sahip olan personel isimleri listelenir.
33
1.5.6.3.2 OR İşleci
OR işleci; iki koşulun yandaki doğruluk değeri tablosuna göre TRUE veya FALSE
değerinin döndürülmesini sağlar. Eğer, her iki koşulun doğruluk değeri TRUE ise istenen
seçme işlemi gerçekleşir.
Örnek
Komisyon alan veya görevi MEMUR olan personeli listelemek istiyoruz. Amacımıza uygun
SELECT deyimi şu şekildedir;
34
1.5.6.3.3 NOT İşleci
NOT işleci; bir koşulun doğruluk değeri TRUE ise FALSE; FALSE ise TRUE değerini
döndürmesini sağlar. Bu işleç IN, LIKE, NULL ve BETWEEN işleçleriyle birlikte
kullanılabilir.
Örnek
Mesleği MEMUR, ŞEF veya PAZARLAMACI olmayan personeli listelemek için aşağıdaki
SELECT deyimi kullanılabilir;
35
1.5.6.3.4 İşleçlerin İşlem Sırası
WHERE sözcüğü içinde yer alan işleçler, yanda gösterilen sıraya göre işlem görürler. Bu
işleçlerin dışında, parantezler de kullanılabilir. Parantezler tüm işleçlere göre bir önceliğe
sahiptir. Yani öncelikle parantez içindeki işlemler yapılır, ardından da yandaki tabloya
göre işlem sırası uygulanır.
Örnek 1
36
WHERE GÖREVİ='MEMUR'
OR GÖREVİ='ŞEF'
AND ÜCRET>3000;
İşleçlerin öncelik sırasını göz önüne alarak değerlendirme yapmamız gerekiyor. AND
işleci OR dan daha öncelikli olduğu için, AND işlecini ilgilendiren koşulu öncelikle
değerlendirmemiz gerekiyor. Ardından geriye kalan koşulu göz önüne alıyoruz. O halde
aşağıda belirtildiği biçimde iki koşuldan söz edilebilir;
Bu iki koşulu öncelik sıralarını göz önüne alarak birleştirirsek, şöyle bir seçme işlemiyle
karşılaşırız;
"Görevi ŞEF olanlar ve ücreti 3000'den fazla olanlar veya görevi MEMUR olanların seçimi"
Örnek 2
Görevi; ŞEF veya MEMUR olanlar ve ücreti 3000'den fazla olanların seçimini yapacak
SELECT deyimini yazınız.
37
Örnek 1
Personeli işe giriş tarihine göre sıralamak istiyoruz. Bunun için SELECT deyimi şu şekilde
düzenlenebilir;
38
Örnek 2
Bu kez personeli ücretine göre her bölüm içinde sıralamak istiyoruz. Bu durumda,
bölümleri ve ücretleri birlikte sıralamız söz konusudur. SELECT deyimi şu şekilde
düzenlenebilir;
39
40
41
42
43
44
45
46
FONKSİYONLARIN KULLANIMI VE
GRUPLAMA İŞLEMLERİ
Bu bölümde;
• Fonksiyon
• SQL Fonksiyonları
• Tek Satır Fonksiyonları
• İç İçe Fonksiyonlar
• Grup Fonksiyonları
• Gruplama İşlemleri
anlatılmaktadır.
Bölüm Hedefi
Bu bölümde aşağıda belirtilen konular ele alınarak
incelenecektir:
• Fonksiyon nedir ?
• SQL fonksiyonları
• İç içe fonksiyonlar
• Grup fonksiyonları
• Gruplama işlemleri
47
2.2 SQL Fonksiyonları
SQL fonksiyonları iki ana grup altında incelenmektedir:
48
Tek satır fonksiyonları, tablonun bir satırı için uygulanır ve her satır için bir sonuç üretilir.
Çoklu satır fonksiyonları ise, bir grup satıra uygulanır ve sonuç buna göre elde edilir.
Burada anlatılan SQL standart ANSI SQL 'dir. Ancak bazı fonksiyonları tüm veri
tabanlarının desteklemediğini göreceksiniz. ANSI SQL'in tüm özelliklerini
barındıran ORACLE veri tabanı üzerinde çalıştığımızı varsayarak, fonksiyonları
ona göre anlatacağız.
Bu derste, aksi söylenmedikçe "fonksiyon" sözcüğü ile tek satır fonksiyonlarından söz
edildiği anlaşılacaktır. Tek satır fonksiyonlarını aşağıda belirtildiği biçimde tanımlıyoruz;
49
fonksiyon Herhangi bir SQL fonksiyonunu
simgeler. Örneğin LOWER bir
fonksiyon ismidir. Bu ismi
sütun
değiştiremeyiz.
ifade Herhangi bir tabloya ilişkin sütun adı
argümanlar Herhangi bir karakter dizisi ya da
hesaplama ifadesi
Fonksiyonla birlikte kullanılabilecek
argümanlar
50
Bir sütunun ya da katarın
içerdiği karakter sayısını
döndürür.
a. LOWER() Fonksiyonu
LOWER() fonksiyonu, bir karakter katarının tüm harflerini küçük harflere dönüştürür.
Örnek
51
b. UPPER () Fonksiyonu
UPPER() fonksiyonu, bir karakter katarındaki tüm harfleri büyük harflere çevirir.
52
Örnek
53
Bu fonksiyonların en çok kullanılanlarını şu şekilde sıralayabiliriz:
54
Eğer n sıfır ise veya fonksiyon içinde belirtilmemiş ise, yuvarlatma sonunda elde edilecek
tamsayının ondalık hanesi olmayacaktır. ROUND() fonksiyonu şu şekilde tanımlanır;
Örnek
55
2.3.3 Tarih Fonksiyonları
Tarih işlemlerinde kullanılan bazı tarih fonksiyonlarından söz edilebilir. Bu fonksiyonların
en çok kullanılanlarından biri SYSDATE fonksiyonudur. Bu fonksiyonun herhangi bir
argümanı bulunmamaktadır. O andaki tarih ve zaman bilgisini elde etmek amacıyla
kullanılır. Diğer tarih fonksiyonlarını aşağıdaki tablo üzerinde görebilirsiniz;
Fonksiyon İşlevi
İki tarih arasında kaç aylık bir
süre olduğunu saptar.
Belirli bir tarih bilgisine n ay
ilave edildiğinde hangi tarihe
ulaşılacağını belirler.
Haftanın belirli bir gününün,
bir sonra hangi tarihe karşılık
geldiğini bulmak için kullanılır.
Belirlenen tarihe ilişkin ayın
son gününü bulmak için
kullanılır.
Örnek 1
Personelin işe giriş tarihinden bu zamana kadar olan süreyi ay olarak hesaplatmak
istiyoruz. Amacımıza uygun SELECT deyimi şu şekilde olabilir;
56
SELECT ADI, GİRİŞ_TAR,
MONTHS_BETWEEN (SYSDATE,GİRİŞ_TAR) AS AY
FROM PERSONEL;
Örnek 2
İşe giriş süresi 200 aydan daha az olan personeli listelemek için şu şekilde bir sorgu
yapılabilir;
SELECT ADI,GİRİŞ_TAR,
MONTHS_BETWEEN(SYSDATE,GİRİŞ_TAR) AS AY
FROM PERSONEL
WHERE MONTHS_BETWEEN(SYSDATE,GİRİŞ_TAR)<200;
Örnek 3
Personelin işe giriş tarihinden 6 ay sonrasının hangi tarihe karşılık geldiğini hesaplayan
bir sorgu şu şekilde oluşturulabilir;
Örnek 4
Personelin işe giriş tarihlerini göz önüne alarak her bir tarihin ait olduğu ayın en son
gününü belirleyen sorgu ifadesi şu şekilde olabilir;
Fonksiyon İşlevi
Tarih veya sayısal bilginin
istenildiği gibi biçimlendirilerek
karakter dizisine dönüştürülmesini
sağlar.
Bir karakter katarının içerdiği
sayısal değerleri istenildiği gibi
biçimlendirilerek sayısal veri türüne
dönüştürmek için kullanılır.
Bir karakter katarının içerdiği tarih
verilerini istenildiği gibi
biçimlendirilerek tarih veri türüne
dönüştürmek için kullanılır.
57
Bu fonksiyon, tarih veya sayısal bilginin istenildiği gibi biçimlendirilerek karakter dizisine
dönüştürülmesini sağlar. İki farklı uygulama alanı bulunmaktadır. Eğer tarih bilgisini
karakter dizisine, yani bir katara dönüştürmek söz konusu ise;
tanımı uygulanır.
Eleman Anlamı
YYYY Dört haneli yıl bilgisi. Örneğin; 2002
YEAR Yılın rakamlarla değil, okunduğu gibi yazılması
MM İki haneli ay bilgisi
MONTH Ayın tam adı
DD İki haneli gün bilgisi
DY Haftanın günü. Üç karakterden oluşur.
DAY Günün tam adı
58
Zamanla ilgili biçimlendirme ifadeleri ise aşağıdaki elemanlardan oluşabilir;
Eleman Anlamı
AM,PM Meridyen göstergesi
HH Günün saati
MI Dakika bilgisi
SS Saniye bilgisi
Eleman Anlamı
9 Sayısal değeri ifade eder.
0 Sıfır değerini ifade eder.
$ Dolar işaretini yerleştirir.
L Yerel para işaretini yerleştirir.
. Ondalık hanesini gösterir.
, Binler hanesini gösterir.
Örnek 1
Personelin işe giriş tarihlerini MM/YY biçiminde elde etmek için şu şekilde bir sorgu
düzenlenebilir;
SELECT ADI,TO_CHAR(GİRİŞ_TAR,'MM/YY')
FROM PERSONEL;
Örnek 2
Personel ücretlerini, binler hanesinden ayırarak elde etmek istiyoruz. Ayrıca ücret
rakamının sol tarafına ($) işaretini yerleştireceğiz. Amacımıza uygun sorgu şu şekilde
düzenlenebilir;
SELECT ADI,TO_CHAR(ÜCRET,'$99,999')
FROM PERSONEL;
59
Biçimlendirme ifadesi, TO_CHAR() fonksiyonunda olduğu gibi, aşağıda yer alan işaretler
kullanılarak düzenlenir;
Eleman Anlamı
9 Sayısal değeri ifade eder.
0 Sıfır değerini ifade eder.
$ Dolar işaretini yerleştirir.
L Yerel para işaretini yerleştirir.
. Ondalık hanesini gösterir.
, Binler hanesini gösterir
60
Örnek
İşe giriş tarihlerine göre PERSONEL tablosunu sorgulayacağız. Arama ifadesi "Ocak 1,
1980" biçiminde olabilir. Bu ifadeyi SELECT deyiminin yorumlayabileceği bir biçime
dönüştürmek gerekiyor. Amacımıza uygun SELECT deyimi şu şekilde olabilir;
61
! NVL() fonksiyonunun EVET ve HAYIR durumlarında çalışma şeklini görmek için; EVET ve
HAYIR düğmelerine tıklayınız.
Örnek 1
Yıllık toplam ücretleri hesaplamak istiyoruz. Bunun için; aylık ücret bilgisi, 12 ile
çarpılacak ve bulunan sonuca komisyon miktarı eklenecektir. Ancak pek çok personelin
komisyon bilgisi NULL değerler içermektedir. NULL değerler içeren sütunlar üzerinde
aritmetik işlemler yapamayız. NULL değerler yerine 0 değerini yerleştirerek hesaplamalar
yapılabilir. O halde, NVL() fonksiyonunu kullanmamız söz konusudur. Amacımıza uygun
SELECT deyimi şu şekilde olmalıdır;
SELECT ADI,ÜCRET,KOMİSYON,ÜCRET*12+NVL(KOMİSYON,0)
FROM PERSONEL;
Örnek 2
İşe giriş tarihleri NULL olan personel için '01-01-2002' tarihini işe başladığı tarih olarak
görüntüleyen SELECT deyimi şu şekilde olabilir;
SELECT ADI,GİRİŞ_TAR,NVL(GİRİŞ_TAR,'01-01-2002')
FROM PERSONEL;
62
Örnek 3
Görevi henüz belli olmayan personel için, görev olarak "GÖREVİ BELİRLENMEDİ" mesajını
görüntüleyen SELECT deyimi şu şekilde olabilir;
63
Örnek
Personel arasında görevi; MEMUR olanlara %10, ŞEF olanlara %15, MÜDÜR olanlara
ise, %20 zam yapılacaktır. Diğerlerinde ise herhangi bir değişiklik olmayacaktır. Bu
işlemleri yerine getirmek üzere aşağıdaki SELECT deyimini düzenliyoruz;
SELECT ADI,GÖREVİ,ÜCRET,
DECODE(GÖREVİ,'MEMUR', ÜCRET*1.10,
'ŞEF',ÜCRET*1.15,
'MÜDÜR'ÜCRET*1.20,
ÜCRET) AS "YENİ ÜCRETLER"
FROM PERSONEL;
DECODE(TRUNC(ücret,0), …)
64
2.5 Grup Fonksiyonları
Tek satır fonksiyonları, tablonun bir satırına uygulanabiliyor ve buna karşılık gelen bir
sonuç satırı elde edilebiliyordu. Bir grup satıra bir fonksiyonun uygulanması söz konusu
ise; "çoklu satır" ya da bir başka deyişle "grup fonksiyonlarından" söz edilir. Grup
fonksiyonları tablonun tüm satırlarına uygulanabildiği gibi, GROUP BY sözcüğü
yardımıyla da alt gruplara uygulanabilir.
Bir tablonun tüm satırları için grup fonksiyonu uygulanacak ise, SELECT deyimi aşağıda
belirtildiği biçimde kullanılır;
65
2.5.1 AVG() Fonksiyonu
Herhangi bir sütunun içerdiği sayısal değerlerin aritmetik ortalamasını hesaplamak
amacıyla; AVG() fonksiyonu kullanılır. Bu fonksiyonun uygulandığı sütunun veri türü
sayısal olmalıdır.
Örnek 1
Personel ücretlerini göz önüne alalım. Ücretlerin ortalamasını bulmak için şöyle bir yol
izlenir;
66
SELECT AVG (ÜCRET) AS ORTALAMA
FROM PERSONEL;
Örnek 1
Personel ücretlerini göz önüne alalım. Ücretlerin ortalamasını bulmak için şöyle bir yol
izlenir;
Örnek 2
Personel arasında görevi MEMUR olanların ortalama ücreti aşağıda gösterildiği biçimde
hesaplanabilir;
67
2.5.2 SUM() Fonksiyonu
Sütunların içerdiği sayısal değerleri toplamak amacıyla SUM() fonksiyonundan
yararlanılır.
Örnek
68
2.6 Gruplama İşlemleri
Bir tablonun satırları gruplara ayrılarak, grup fonksiyonlarının bunlara uygulanması
sağlanabilir. Böyle bir amaçla SELECT deyimi içinde GROUP BY sözcüğünden
yararlanılır.
Örnek
PERSONEL tablosunu göz önüne alarak, her bölüm için personel sayısını, ücret toplamını
ve ortalama ücretleri hesaplayan SELECT deyimi şu şekilde oluşturulabilir;
69
2.6.1 GROUP BY Kullanırken Dikkat Edilecek Noktalar
SELECT deyimi içinde grup fonksiyonları, sütun isimleri ile birlikte kullanılabilirler.
Ancak grup fonksiyonları; GROUP BY sözcüğü olmadan aşağıda gösterildiği biçimde,
sütun isimleri ve grup fonksiyonu ile birlikte kullanılamaz. Örneğin;
biçiminde bir tanım yapılamaz. Böyle bir amaca ancak aşağıda gösterildiği biçimde
varılabilir;
70
değildir. Örneğin; bölüm numarasına göre oluşturulan grupta, yani her bölümün ücret
ortalamalarının görüntülenmesi için şöyle bir tanım yapılabilir;
SELECT AVG(ÜCRET)
FROM PERSONEL
GROUP BY BÖLÜM_NO;
Örnek
Her bölümü ve bölüm içindeki görevlere göre personeli gruplayarak bu bazda ücret
toplamları elde etmek amacıyla SELECT deyimi şu şekilde düzenlenebilir;
71
2.6.3 Grup Koşullarının Kullanımı
Grup işlemleri yerine getirilirken, doğal olarak grup bazında bazı sınırlamalar söz konusu
olabilir. Örneğin, bölüm bazında yapılan bir işlemin, bölüm ücret ortalamasının 2000'den
büyük ise gerçekleştirilmesi istenebilir. Bunun için aşağıda gösterildiği biçimde bir tanım
yapılabilir;
Örnek 1
PERSONEL tablosunu göz önüne alalım. Ortalama ücreti 3500'den daha fazla olan
bölümlerin bölüm numarası ve o bölümdeki en yüksek ücret miktarı görüntülenecektir.
Amacımıza uygun SELECT deyimi şu şekilde olabilir;
72
Yukarıdaki sorgulamanın sonucunu görmek için linke tıklayınız
Örnek 2
73
74
75
76
77
78
79
ÇOKLU TABLOLAR VE KARMAŞIK SORGULAR
Bu bölümde;
anlatılmaktadır.
Bölüm Hedefi
Bu bölümde aşağıda sıralanan konular ele alınarak
incelenecektir:
80
Bu iki tablo arasında ortak olan BÖLÜM_NO sütunları aracılığıyla bir ilişki kurulur ve her
iki tablo verilerinden oluşan bir sonuç elde edilir.
81
Tanımdan görüldüğü gibi, iki tabloyu birleştirmek için bir birleştirme koşulunun
düzenlenmesi gerekiyor. Bu koşul, her iki tablonun hangi sütunları kullanılarak
birleştirileceğini belirler. Sütun isimlerinin ön tarafına, tablo isimlerinin yazılması yararlı
olacaktır. Özellikle her iki tablodaki sütun isimleri aynı ise, söz konusu sütunların hangi
tablodan geldiğini belirtmek mümkün olamayacak ve bu durumda SELECT deyimi
çalışmayacaktır.
Sadece iki tablo değil n sayıda tablo da birleştirilebilir. Ancak bu durumda en az (n-1)
birleştirme koşulu tanımlanmalıdır. Yani, dört adet tabloyu birleştirmekiçin en az üç
birleştirme koşulu olmalıdır. Bu koşul, birleştirilmiş birincil anahtara sahip tablolar için
geçerli olmayacaktır.
Örnek
PERSONEL ve BÖLÜM tablolarını göz önüne alalım. Bu iki tabloyu aşağıda görüldüğü
biçimde birleştirmek istiyoruz.
82
3.4 Birleştirme Türleri
Tabloları farklı şekillerde birleştirme olanağı bulunmaktadır. Solda, tabloları birleştirme
türleri verilmiştir. Bu birleştirme türlerinin herbirini ayrıntılı biçimde ele alarak
inceleyeceğiz.
83
Bu tür birleştirmelere "basit birleştirme", "eşiti olan birleştirme" ya da "iç birleştirme"
isimleri verilmektedir. Bu birleştirme aşağıda belirtildiği biçimde gerçekleştirilir;
Bir personelin çalıştığı bölümün adını elde etmek için; PERSONEL tablosu, BÖLÜM
tablosunun BÖLÜM_NO isimli sütununun içeriği ile karşılaştırılır. Yani her iki tablo
arasındaki BÖLÜM_NO sütununun içerdiği değerlerin eşit olması durumunda birleştirme
gerçekleştirilmiş olur.
84
3.4.1.2 Sütun İsimlerindeki Belirsizlik
Birleştirme işleminde, SELECT listesindeki her bir sütunun, ilgili tablo ile gösterilebildiğini
gördük. Bu, her iki tablodaki alan isimlerinin aynı olması durumunda sorun yaratacaktır.
Örneğin; PERSONEL.BÖLÜM_NO ve BÖLÜM.BÖLÜM_NO yerine sadece BÖLÜM_NO
yazılsaydı, SQL bunu yorumlayamayacaktı çünkü, bu sütunun hangi tablodan alınacağı
belirtilmemiştir. Bu durumda SELECT deyimi hata mesajı verecektir.
Sadece bir tabloda yer alan sütun isimlerinin, yukarıda belirtildiği gibi, tablo isimleri ile
birlikte belirtilmesi zorunluluğu yoktur.
Bu tür bir tanıma FROM sözcüğü içinde yer verilir. Tablonun gerçek isminin hemen
ardından bir boşluk bırakılarak takma isim tanımlanır. SELECT deyiminin herhangi bir
yerinde, gerçek tablo ismi yerine bu takma isim kullanılabilir.
Örnek
SELECT PERSONEL.PERSONEL_NO,PERSONEL.ADI,
PERSONEL.BÖLÜM_NO,BÖLÜM.BÖLÜM_ADI,BÖLÜM.KONUM
FROM PERSONEL,BÖLÜM
WHERE PERSONEL.BÖLÜM_NO=BÖLÜM.BÖLÜM_NO;
Sorgu içinde PERSONEL tablosuna P; BÖLÜM tablosuna ise, B takma ismini vererek aynı
sorguyu aşağıda gösterildiği biçimde düzenleyebiliriz;
SELECT P.PERSONEL_NO,P.ADI,
P.BÖLÜM_NO,B.BÖLÜM_ADI,B.KONUM
FROM PERSONEL P,BÖLÜM B
WHERE P.BÖLÜM_NO=B.BÖLÜM_NO;
85
SELECT P.PERSONEL_NO,P.ADI,B.BÖLÜM_ADI,B.KONUM
FROM PERSONEL P, BÖLÜM B
WHERE P.BÖLÜM_NO=B.BÖLÜM_NO
AND P.ADI='BEGÜM';
86
Bu iki tablo incelendiğinde, BÖLÜM tablosunda yer alan REKLAM bölümünde herhangi
bir personelin çalışmadığı görülecektir. İki tablo; eşiti olan birleştirme yöntemine göre
birleştirilirse, sonuç içinde bu bölüm adı görüntülenmeyecektir. Böyle durumlarda
eşleşmeyen kayıtları da birleştirme işlemine katmak için; dış birleştirme yöntemi
uygulanır.
SELECT tablo1.sütun1,
tablo2.sütun2
FROM tablo1, tablo2
WHERE
tablo1.sütun1(+)=tablo2.sütun2
veya
SELECT tablo1.sütun1,
tablo2.sütun2
FROM tablo1, tablo2
WHERE
tablo1.sütun1=tablo2.sütun2(+)
Tanımda (+) işaretlerinin yer alması, dış birleşme olayının olduğunu göstermektedir. Bu
işaret eksik bilginin olduğu tarafa yerleştirilir.
Örnek
87
PERSONEL ve BÖLÜM tablolarını göz önüne alalım. BÖLÜM tablosunda yer alan, ancak
PERSONEL tablosunda yer almayan ve REKLAM bilgisini içeren bir satır bulunmaktadır.
Bu iki tabloyu, karşılaşmayan kayıtları da görüntüleyecek biçimde birleştirmek ve sonucu
listelemek istiyoruz. Bunun için aşağıdaki yol izlenir:
SELECT P.ADI,P.BÖLÜM_NO,B.BÖLÜM_ADI
FROM PERSONEL P,BÖLÜM B
WHERE P.BÖLÜM_NO(+)=B.BÖLÜM_NO;
Bilgi eksikliği PERSONEL tablosundadır çünkü, BÖLÜM tablosunda yer alan REKLAM
satırı, PERSONEL tablosunda yoktur. O halde (+) işareti, PERSONEL tablosunun ilgili
sütunu yanında tanımlanmıştır. Bu işlemin aynısını MS Jet SQL'de gerçekleştirmek için
biraz daha farklı tanım yapmak gerekiyor. Bu tür bir dış birleşme için LEFT JOIN…ON
sözcükleri kullanılır.
88
3.4.4 Kendine Birleştirme
Bazı uygulamalarda birleştirme işlemi, iki ayrı tablo yerine tek bir tablodaki veriler
kullanılarak yapılır. Örneğin, PERSONEL tablosunu aşağıda görüldüğü gibi, iki farklı tablo
biçiminde düşünebiliriz. Böylece bu iki tabloyu birleştirerek çeşitli sonuçlar elde etmek
imkânımız vardır.
Örnek
89
3.5 Küme İşleçlerini Kullanarak Birleştirme
SQL deyimleri içinde küme işlemlerini temel alarak, çeşitli sorgulamalar yapılabilir. Bu tür
sorgularda küme işleçlerinden yararlanılır. Küme işleçleri sayesinde birden fazla tablo
birleştirilerek sonuçlar alınabilir.
! SQL'de kullanılan küme işleçlerini tekrar görmek için 'TEKRAR' düğmesine tıklayınız.
90
3.5.1 UNION ve UNION ALL İşleçleri
UNION işleci; verilen koşul ifadesine uygun olarak çift kayıtları göz ardı eder ve her iki
kümedeki tüm kayıtları seçer. Buna karşılık, verilen koşul ifadesine uygun olarak çift
kayıtlar da dahil olmak üzere, tüm kayıtların seçilmesi söz konusu ise; UNION ALL işleci
kullanılır.
Örnek
PERSONEL tablosunda, adı "A" ile başlayanları veya görevi "M" ile başlayanları topluca
listelemek istiyoruz.
Burada iki ayrı koşuldan söz edilebilir. Bunlardan birincisi, adının ilk harfi "A" ile başlayan
personelin oluşturduğu kümedir. İkincisi ise; görevi "M" harfi ile başlayanların
oluşturduğu kümedir.
Bu deyim çalıştırıldığında, birbirinin aynı olan yani, çift kayıtlar görüntülenmez. Eğer çift
kayıtların da görüntülenmesi isteniliyorsa; UNION ALL işleci kullanılır.
91
3.5.2 INTERSECT İşleci
Her iki koşula da uygun kayıtları elde etmek için; INTERSECT işleci kullanılır. Bu işleç, iki
kümenin ara kesiti olarak düşünülür ve iki bölgedeki kayıtların seçilmesini sağlar.
Örnek
PERSONEL tablosunda, adı "A" ile başlayanları ve görevi "M" ile başlayan kayıtları
bulacağız. Amacımıza uygun SELECT deyimi şu şekilde olabilir:
92
MINUS İşlecinin Etkisi
Örnek
Adı "A" ile başlayan ancak işi, "M" ile başlamayan kayıtları listelemek gerektiğinde;
MINUS işlecine başvurulur. Bunun anlamı, birinci sorguda ismi "A" ile başlayanlar; ikinci
sorguda da işi, "M" ile başlayanlar aranılacaktır. MINUS işleci, bu iki küme arasındaki
farkı ortaya çıkaracaktır.
Uygulamada, bir sorgudan elde edilen sonuç, bir diğer sorguyu ilgilendirebilir. Bu gibi
durumlarda alt sorgular ya da bir başka deyişle iç sorgular kullanılır.
Şu soruyu göz önüne alalım: "Hangi personelin ücreti, "HALİT" isimli personelin
ücretinden daha fazladır?" Bu problemi iki farklı sorguya ayırmak mümkündür:
93
Yukarıdaki iki sorguyu aşağıdaki şekilde analiz ederek bir sorgu biçimine döndürebiliriz.
Alt sorgular bu amaçla tanımlanır.
SELECT liste
FROM tablo
WHERE ifade
işleç
(SELECT liste
FROM tablo);
Tanımda görüldüğü gibi, iki SELECT deyimi ile bir farklı sorgu tanımlanmıştır. Bu iki
sorgu birbirine WHERE koşul sözcüğü içinde bağlanmıştır. Bir alt sorgu, aşağıdaki
sözcükler içinde kullanılabilir:
• WHERE
• HAVING
• FROM
Örnek
Personel numarası "110" olan personelin ücretinden daha fazla ücret alan personel
isimlerini listelemek istiyoruz. Amacımıza uygun SELECT deyimi şu şekilde olabilir:
SELECT ADI,ÜCRET
FROM PERSONEL
WHERE ÜCRET >
( SELECT ÜCRET
FROM PERSONEL
WHERE PERSONEL_NO=110 );
94
Bu sorgu çalıştırıldığında, şöyle bir yol izlenecektir:
a. Alt sorgu Personel numarası "110" olan personelin ücretini bulacaktır. Bu ücret;
"5000" dir.
b. Elde edilen ücret bilgisi ana sorgudaki WHERE sözcüğü içinde yerine konulacaktır.
Yani ana sorgunun WHERE koşulu şu şekli almış olacaktır:
WHERE ÜCRET > 5000
c. Ana sorgu bu şekilde çalışır. Yani ücreti "5000" den fazla olan personelin listesi
görüntülenir.
95
3.6.3 Tek Satır Alt Sorguları
Sadece bir değer döndüren alt sorgulardır. İç taraftaki SELECT deyiminden sadece tek bir
değer elde edilir. Bu sorgularda soldaki animasyonda yer alan işleçler kullanılır.
96
Örnek 1
Personel numarası "140" olan personelle aynı göreve sahip olan personelin isimlerini
listelemek istiyoruz. Amacımıza aşağıdaki sorgu yardımıyla ulaşabiliriz:
SELECT ADI,GÖREVİ
FROM PERSONEL
WHERE GÖREVİ =
(SELECT GÖREVİ
FROM PERSONEL
WHERE PERSONEL_NO=140);
Bu sorgu çalıştırıldığında, alt sorgu sonucunda "140" numaralı personelin görevi, yani
"ŞEF" değeri elde edilir. Ana sorgu ise görevi "ŞEF" olanları sorgular.
Örnek 2
Personel numarası "155" olan personelle aynı göreve sahip olan ve "350" numaralı
personelin ücretinden daha fazla ücret alan personeli listelemek istiyoruz.
SELECT ADI,GÖREVİ,ÜCRET
FROM PERSONEL
WHERE GÖREVİ =
(SELECT GÖREVİ
FROM PERSONEL
WHERE PERSONEL_NO=155)
97
AND ÜCRET>
(SELECT ÜCRET
FROM PERSONEL
WHERE PERSONEL_NO=350);
98
Örnek
Personel arasında en az ücret alanları listelemek istiyoruz. Bu sorgu doğal olarak alt
sorgularla yapılabilir. Önce alt sorgu içinde en az ücret alan personel belirlenecek,
bulunan değer ana sorgu içinde bu ücrete göre seçilecektir. Amacımıza uygun SELECT
deyimi şu şekilde olabilir:
SELECT ADI,ÜCRET
FROM PERSONEL
WHERE ÜCRET =
(SELECT MIN(ÜCRET)
FROM PERSONEL);
99
3.6.5 HAVING ile Grup Koşullarının Tanımlanması
Ana sorgu grup fonksiyonu içeriyorsa, doğal olarak grup koşullarının tanımlanması
gerekebilecektir. Yani HAVING sözcüğü de kullanılacaktır. Bu durumda SELECT deyimi şu
şekli alacaktır:
SELECT liste
FROM tablo
GROUP BY sütun
HAVING fonksiyon işleç
(SELECT fonksiyon
FROM tablo);
100
Örnek
En düşük ücreti "20" numaralı bölümün en düşük ücretinden daha büyük olan bölümleri
listelemek istiyoruz. Amacımıza ulaşmak için şu şekilde bir akıl yürüteceğiz: :
101
3.6.5 Alt Sorgularda Hatalı Çalışma Durumu
Tek satır alt sorgularının yapısını ve özelliklerini biliyoruz. Bu tür alt fonksiyonlar, sadece
bir değer üreterek, onu ana sorguya aktarır. Eğer alt sorgu tek satırlı alt sorgu olarak
düşünülüyorsa, bunu bozabilecek tanımlardan kaçınmak gerekiyor. Aksi takdirde söz
konusu sorgu çalışmaz. Eğer alt sorgunun birden fazla değer üretmesi söz konusu ise,
çoklu satır alt sorgularını tanımlamak gerekiyor.
102
Örnek
SELECT PERSONEL_NO,ADI
FROM PERSONEL
WHERE ÜCRET >
(SELECT MIN(ÜCRET)
FROM PERSONEL
GROUP BY BÖLÜM_NO);
SELECT PERSONEL_NO,ADI
FROM PERSONEL
WHERE ÜCRET >
(SELECT MIN(ÜCRET)
FROM PERSONEL);
103
Yukarıda sayılan işleçlerden hiçbiri NOT işleci ile birlikte kullanılamaz!
3.7.1 IN İşleci
Bir liste içindeki değerlerden birini seçmek için IN işlecini kullanıyorduk. Örneğin,
biçimindeki bir sorgu, ÜCRET sütunu içeriğinin, IN işleci ile belirlenen listedeki değerlerle
karşılaştırılmalarını sağlıyordu. Bu tür bir işlem, alt sorgularda da gerçekleştirilebilir.
Örnek
Bir liste içindeki değerlerden birini seçmek için IN işlecini kullanıyorduk. Örneğin,
104
SELECT ADI,ÜCRET,GÖREVİ
FROM PERSONEL
WHERE ÜCRET IN(
SELECT MIN(ÜCRET)
FROM PERSONEL
GROUP BY BÖLÜM_NO);
biçimindeki bir sorgu, ÜCRET sütunu içeriğinin, IN işleci ile belirlenen listedeki değerlerle
karşılaştırılmalarını sağlıyordu. Bu tür bir işlem, alt sorgularda da gerçekleştirilebilir.
105
Örnek 1
En fazla kazanan MEMUR dan daha az maaşı olan personeli listelemek istiyoruz.
Amacımıza uygun sorgu şu şekilde olabilir.
SELECT ADI,ÜCRET,GÖREVİ
FROM PERSONEL
WHERE ÜCRET <ANY(
SELECT ÜCRET
FROM PERSONEL
WHERE GÖREVİ='MEMUR');
106
Örnek 2
En düşük ücretli MEMUR dan daha fazla maaşı olan personeli listelemek için aşağıda
belirtilen yol izlenebilir:
SELECT ADI,ÜCRET,GÖREVİ
FROM PERSONEL
WHERE ÜCRET >ANY(
SELECT ÜCRET
FROM PERSONEL
WHERE GÖREVİ='MEMUR');
107
Örnek
Ücreti tüm bölümlerin ortalama ücretinden daha büyük olan personellerii listelemek
istiyoruz. Amacımıza uygun sorgu şu şekilde olabilir:
SELECT ADI,ÜCRET
FROM PERSONEL
WHERE ÜCRET >ALL(
SELECT AVG(ÜCRET)
FROM PERSONEL
GROUP BY BÖLÜM_NO);
108
3.8 Çok Sütunlu Alt Sorgular
Önceki bölümde, alt sorgunun ürettiği bir sütun, ana sorgu için bir girdi olarak
kullanılıyordu. Bazı uygulamalarda alt sorgunun birden fazla sütun üretmesi ve koşul
içinde bu değerlerin kulanılması söz konusu olabilir. Böyle durumlarda aşağıda belirtildiği
biçimde sorgu tanımlanır. Bu tür bir tanım MS Access'de, yani MS Jet SQL'de geçerli
değildir.
SELECT liste
FROM tablo
WHERE sütun1, sütun2,... IN
( SELECT sütun1, sütun2,...
FROM tablo
WHERE koşul );
109
Örnek
"SEZİN" isimli personelin görevi ve ücretiyle aynı olan personeli listelemek istiyoruz.
Sorgu şu şekilde düzenlenebilir:
Örnek
Bir bölümün ortalama ücretinden daha fazla ücret alan tüm personelin ortalama
ücretlerini listelemek istiyoruz. Amacımıza uygun sorgulama şu şekilde olabilir:
110
FROM PERSONEL
GROUP BY BÖLÜM_NO) S
WHERE P.BÖLÜM_NO=S.BÖLÜM_NO
AND P.ÜCRET>S.MAAŞ;
Burada, PERSONEL tablosu yanısıra bir alt sorgu tanımlanmaktadır. Bu sorgu tıpkı bir
tablo gibi düşünülerek ona S adı verilmiştir. Bu sorgu bölümlerin ücret ortalamalarını
üretmektedir.
111
112
113
114
115
116
117
118
119
VERİTABANI TABLOLARININ YARATILMASI
Bu bölümde;
• Tablolar
• DML İşlemleri
• Hareket İşleme
anlatılmaktadır.
Bölüm Hedefi
Bu bölümde aşağıda sıralanan konular ele alınarak
incelenecektir:
• DML
• Tablolara yeni satır ekleme
• Tablodaki verilerin güncelleştirilmesi
• Tablodan satır silme işlemi
• Hareket işleme
4.1 Tablolar
Tablolar veri tabanının temel yapılarıdır. Tablo yapılarının en önemli özellikleri şunlardır:
a) Tablolar herhangi bir anda, hatta veri tabanının bir kullanıcı tarafından kullanılması
esnasında bile yaratılabilir.
b) Tablolar için bir boyut belirlemeye gerek yoktur. Ancak yine de tablonun ne kadarlık
bir hacime ulaşabileceğini tahmin etmekte yarar vardır.
120
Veri tabanlarında iki türlü tablo yer almaktadır:
121
Tablo isimleri büyük-küçük harf ayrımına karşı duyarlı değildir. Küçük harflerle ya da
büyük harflerle veya karışık yazılması fark etmez. Tablo isimleri verilirken aşağıda
sıralanan hususlara dikkat edilmesi tavsiye edilir:
Aynı sütunlar birden fazla tablo içinde yer alıyorsa, aynı isimleri vermek yararlı
b) olacaktır. Örneğin PERSONEL ve BÖLÜM tablosu içindeki bölüm numarasını içeren
sütunlar BÖLÜM_NO biçiminde belirlenmiştir.
122
123
124
125
126
127
4.1.3 Tabloların Yaratılması
Tabloların yaratılabilmesi için CREATE TABLE deyimi kullanılır. Bu deyim şu şekilde
tanımlanır:
Şema nesneleri, veri tabanı içindeki verilere doğrudan karşılık gelen mantıksal yapılardır.
Şema nesneleri tablolar, görünümler, dizinler ve diğer nesnelerdir. Bir tablo belirli bir
kullanıcıya ait ise, tablo adı kullanıcı adı ile birlikte ifade edilir.
Bir sütunun değeri, daha tablo yaratılırken varsayılan değer (default value) olarak
atanabilir. Burada doğrudan bir değer, bir ifade veya bir fonksiyon belirlenebilir. Ancak
belirtlenen değer, ilgili sütunun veri türüne uygun olmalıdır. Örneğin, PERSONEL
tablosunun GİRİŞ_TAR isimli alanı, personelin işe giriş tarihini içerecektir. Eğer herhangi
bir değer kaydedilmez ise, bu personelin tabloya kaydedildiği günün tarihini işe giriş tarihi
olarak kabul etmek istiyoruz. Bu amaçla DEFAULT sözcüğü,
128
… GİRİŞ_TAR DATE DEFAULT SYSDATE biçiminde kullanılabilir.
Örnek
[(sütunlar)]
AS
altsorgu ;
CREATE TABLE deyiminde sütun tanımları yapılmamış ise, alt sorgudan elde edilen
sütunlar yeni yaratılacak olan tablonun sütunlarını oluşturacaktır. Eğer CREATE TABLE
deyimi içinde sütun tanımları verilmiş ise, bunların sayısı alt sorgudan elde edilen sütun
sayısı ile aynı olmalıdır. Bu durumda yeni tablo sütunları ile alt sorgu sütunları sıraya göre
eşleşir.
129
Örnek
PER20 isimli bir tablo yaratacağız. Bu tablo PERSONEL tablosunda yer alan ve "20"
numaralı bölüme ilişkin personel kayıtlarını içerecektir. PERSONEL tablosundaki aylık
ücret bilgileri yıllığa çevrilerek PER20 tablosuna yazdırılacaktır.
130
ALTER TABLE tablo
ADD ((sütun1 veri türü
[DEFAULT ifade]
[,sütun2 veri türü]…);
Örnek
Daha önce yaratılan PER20 isimli tabloya GÖREVİ isimli yeni bir sütun eklemek
istiyoruz. Bu sütun VARCHAR2 veri türüne sahip olacak ve en fazla 9 karakter
içerebilecektir. Bunun için şöyle bir yol izlenir:
131
ALTER TABLE tablo
MODIFY (sütun1 veri türü
[DEFAULT ifade] [,sütun2
veri türü]…);
132
Örnek
PER20 isimli tablonun ADI isimli sütunun genişliğini 15 karakter olarak değiştirmek
istiyoruz. Bunun için aşağıda belirtilen yol izlenir:
133
Örnek
Veri tabanındaki BÖLÜM isimli tablounun adını YENİ_BÖLÜM olarak değiştirmek için
şöyle bir yol izlenebilir:
Bu deyim tehlikeli sonuçlara neden olabilecek bir deyimdir. O halde kullanırken bazı
noktalara dikkat etmek gerekiyor:
134
Örnek
PER20 isimli tabloyu yok etmek için aşağıda belirtilen yol izlenir:
Eğer bir tabloya yeni kayıt ilave edilmesi, var olan bir satır üzerinde değişiklikler
yapılması veya bir satırın yok edilmesi söz konusu ise, sorgulama deyimleri bir işe
yaramaz. Onun yerine başka yöntemlere başvurmak gerekir.
135
DML-(Data Manipulation Lanquage) adı verilen dil yardımıyla; veri tabanı tabloları
üzerinde kayıt ekleme, veri değiştirme ve kayıt silme gibi işlemler yapılabilir. Bu bölümde
söz konusu dilin temel özelliklerini inceleyeceğiz.
Bu deyim her çalıştığında tabloya yeni bir satır eklenir. INSERT INTO deyimi içinde sütun
isimlerini belirlemek zorunlu değildir. Ancak, bu durumda sütunların tablo tanımındaki
varsayılan sırası kabul edilir.
136
Örnek
BÖLÜM tablosunun aşağıda görüldüğü biçimde 6 adet kayıta sahip olduğunu varsayalım:
Yukarıda olduğu gibi, herhangi bir tablonun satırlarını nasıl görüntüleyeceğimizi geçen
derslerden biliyoruz. Bu işlem aşağıda belirtildiği biçimde SELECT sorgulama deyimi ile
yapılır:
SELECT *
FROM BÖLÜM;
137
Bu tabloya yeni bir bölüm eklemek istiyoruz. Eklenecek yeni bölüm ile ilgili veriler şu
şekildedir:
Bölümün
: 70
numarası
Bölümün adı : EĞİTİM
Bölümün
: KADIKÖY
konumu
Örnek
BÖLÜM tablosuna yeni bir kayıt ekleyeceğiz. Eklenecek satırda KONUM sütununa NULL
değerini atamak için INSERT INTO deyimi aşağıda belirtilen biçimlerde kullanılabilir.
138
Yukarıdaki sorgulamanın sonucunu görmek için linke tıklayınız
Örnek
PERSONEL tablosuna yeni bir kayıt ekleme esnasında, GİRİŞ_TAR isimli alana o günün
tarih ve zaman bilgisini kaydetmek için şöyle bir yol izlenebilir:
139
INSERT INTO deyimi ile, tabloya belirlenen değerleri içeren bir satır eklenebildiği gibi,
bir başka tablodan okunan satırlar da eklenebilir. Diğer tablodan satırları okumak için
SELECT sorgulama deyimi kullanılır. Bu durumda VALUES sözcüğü kullanılmaz.
Bir tablodan satır okuyarak, bir diğer tabloya eklemek için aşağıda belirtilen tanım
kullanılır:
Alt sorgudan elde edilecek sütunlar ile INSERT INTO içinde tanımlanan sütunlar karşılıklı
eşleşecektir. O nedenle, aynı veri türüne sahip olmalarına dikkat etmek gerekiyor.
Örnek
YÖNETİCİLER isimli bir tabloya, PERSONEL tablosunda yer alan ve görevi "MÜDÜR"
veya "ŞEF" olanları seçerek eklemek istiyoruz. Amacımıza uygun deyimler şu şekilde
olacaktır:
140
4.2.5 Tablodaki Verileri Güncelleme
Bir tablonun içerdiği değerler gerektiğinde değiştirilecektir. Bu amaçla UPDATE
deyiminden yararlanılır. Bu deyim şu şekilde tanımlanır:
UPDATE tablo
SET sütun1=değer1,
sütun2=değer2,…
[WHERE koşul];
141
Verilerin güncelleştirilmesi için WHERE deyimi ile bir koşul tanımlanabilir. Bu tanımın
yapılmadığı durumlarda, söz konusu tablonun tüm satırları güncelleştirilmiş olacaktır.
Örnek
Personel numarası "300" olan personelin ücretini "2500" olarak değiştirmek istiyoruz.
Bunu sağlamak için şöyle bir yol izlenir:
UPDATE PERSONEL
SET ÜCRET=2500
WHERE PERSONEL_NO=300;
142
! UPDATE okuna tıklayınız.
Örnek
Numarası "350" olan personel ile aynı göreve sahip tüm personelin bölüm numarasını,
"90" olarak değiştirmek istiyoruz. Amacımıza şu şekilde ulaşabiliriiz:
UPDATE PERSONEL
SET BÖLÜM_NO=90
WHERE GÖREVİ=(SELECT GÖREVİ
FROM PERSONEL
WHERE PERSONEL_NO=350);
143
Örnek 1
BÖLÜM isimli tablonun tüm kayıtlarını silmek için şöyle bir yol izlenebilir:
Ancak bu tür bir silme işleminin gerçekleştirilebilmesi için, bu tablo üzerinde bütünlük
sınırlamalarının bulunmaması gerektiği unutulmamalıdır. Bu tablonun PERSONEL tablosu
arasında bütünlük ilişkilerinin tanımlandığını varsayacak olursak, bu silme işleminin
gerçekleşmeyeceğini söyleyebiliriz.
Örnek 2
BÖLÜM isimli tabloda yer alan ve bölüm kodu "60" olan bölümü silmek istiyoruz. Bunun
için DELETE deyimi şu şekilde düzenlenebilir:
144
4.3 Hareket İşleme
Veri tabanlarını doğal olarak aynı anda çok sayıda kişi kullanacaktır. Kullanıcı; veri
ekleyebilir, veriyi değiştirebilir hatta silebilir. Bu değişikliklerin diğer kullanıcıları hemen
etkilemesi istenmez. Çünkü yapılan bazı işlemlerin iptal edilerek, veri tabanının önceki
hale dönüşmesi gerekebilir. Yani veri üzerinde bir değişiklik yaptığımızda, bunun
sonucunu sadece kendimiz görürüz. Gerek görülürse; bu değişikliklerin kalıcı hale
getirilerek diğer kullanıcılar tarafından da görülmesi sağlanabilir. Bu tür bir amaca
ulaşmak için hareket işleme (transaction processing) kavramını bilmek gerekir.
Verinin değiştirilmesi üzerinde etkili olan DML deyimleri çalıştırıldığında, "veri tabanı
hareketleri " (database transactions) oluşur. Başlayan bir hareket COMMIT ya da
ROLLBACK deyimleri çalıştırılıncaya dek sona ermez ve sonuçları kalıcı değildir. Bu
deyimlerden biri çalıştırıldığında veya bir başka DDL deyimi (örneğin CREATE)
çalıştırıldığında da hareket son bulur. Ayrıca bilgisayarın çalışması sona erince ya da
sistem bozulmalarında (crashes) veri tabanı hareketleri sona erecektir.
145
Veri tabanı hareketlerinin başlaması için INSERT,UPDATE veya DELETE deyimlerinden
birinin çalıştırılması yeterlidir. Ancak bir kullanıcının bu şekilde yaptığı bir işlemin sonucu
diğer kullanıcıyı etkilemez. Bu şekilde başlayan bir işlemi sona erdirmek için COMMIT
kullanılır.
Örnek
UPDATE PERSONEL
SET BÖLÜM_NO=10
WHERE PERSONEL_NO=300;
COMMIT; deyimini çalıştıracak olursa, yaptığı tüm değişiklikler kalıcı hale gelir ve diğer
veri tabanı kullanıcıları da bu değişikliği algılamış olurlar.
ROLLBACK;
deyimi kullanılır.
Örnek
146
DELETE FROM PERSONEL;
147
148
149
150
151
152
153
PL/SQL’E GİRİŞ
Bu bölümde;
anlatılmaktadır.
Bölüm Hedefi
Bu bölümde aşağıda sıralanan konular ele alınarak
incelenecektir:
• Açıklama satırları
154
• Oracle veri tabanı sunucusu
• Oracle yazılım geliştirme araçları
Bu iki ortam birbirinden bağımsız olarak değerlendirilebilir. PL/SQL programları yada bir
başka deyişle PL/SQL blokları doğrudan veri tabanı üzerinde tanımlanarak çalıştırılabilir.
Bunun dışında, söz konusu PL/SQL programları bir uygulama geliştirme ortamında,
örneğin “Oracle Developer” isimli yazılım geliştirme araçları üzerinde tanımlanarak
kullanılabilir.
PL/SQL blokları PL/SQL motoru üzerinde çalıştırılır. PL/SQL motoru PL/SQL programlarını
çalıştıran bir ortamdır. PL/SQL programları SQL deyimlerini ve bunlara ek olarak bazı özel
deyimleri içeren bir programlama dilidir. PL/SQL motoru şekil üzerinde görüldüğü biçimde
bu programları yorumlayarak, istekleri SQL komutları biçiminde Oracle veri tabanına
gönderir.
• Anonim bloklar
• Yordamlar (procedures)
• Fonksiyonlar (functions)
155
5.3 PL/SQL Programlarının Yapısı
PL/SQL programları bloklardan oluşur. Bu bloklar ayrı ayrı olabileceği gibi, içiçe blokların
oluşturulması da mümkündür. Bir blok yada alt blok mantıksal bildirimler (declaration)
ve onu takip eden PL/SQL deyimlerinden oluşmaktadır. Bir PL/SQL bloğu aşağıda
belirtildiği biçimde tanımlanmaktadır:
156
157
5.4 PL/SQL Programlarının Görünümü
Bir SQL bloğu DECLARE, BEGIN ve EXCEPTION bölümlerinden oluşmaktadır. Yandaki örnek
bir PL/SQL programının görünümü hakkında bir fikir vermektedir. Bu blok içinde yer alan
deyimleri sonraki bölümlerimizde ele alarak inceleyeceğiz.
158
5.5.1 SQL*Plus Arayüzüne Giriş
SQL*Plus arayüzüne ulaşabilmek için, öncelikle kullanıcının veri tabanına kendisini
tanıtması gerekmektedir. Bu kullanıcı daha önce veri tabanında yaratılmış olması
zorunludur. Örneğin, kulanıcı adının test şifresinin de test olduğunu varsayalım. Şu anda
Oracle’ın tek kişilik sürümünde varsayıyoruz. Yani veri tabanı şu anda aynı bilgisayar
üzerindedir. O nedenle üçüncü satırdaki ana bilgisayar ile ilgili tanım yapılmaz.
SQL>
ifadesinin hemen ardından kaydedilir. Bu arayüzü kapatmak için, menü üzerindeki Dosya
seçeneğinin Çıkış alt seçeneği kullanılabilir. Ancak,
159
SQL> EXIT;
160
Bir SQL deyimi veya bir PL/SQL bloğu SQL*Plus ortamında bu şekilde yazıldıktan sonra
çalıştırılırsa, bu deyim bir ara belleğe otomatik olarak kaydedilir. O halde bu deyimi bir
sonraki adımda çalıştırmak gerektiğinde yeniden yazmaya gerek yoktur. Onun yerine,
SQL> RUN;
veya kısaca,
SQL> /
İkinci yol olarak, SQL*Plus’un SAVE komutu kullanılır. Bu şekilde yapılan saklama
işlemleri sonucunda, sonu .sql ile biten bir dosya yaratılmış olur. Örneğin test isimli bir
SQL dosyası şu şekilde oluşturulabilir:
161
Bir dosya yaratıldıktan sonra, doğal olarak gerektiğinde çağrılarak çalıştırılacaktır. Var
olan bir SQL dosyasını çağırmak için SQL*Plus’un START komutu kullanılır. Örneğin, daha
önce yaratılmış bir SQL dosyası şu şekilde çağrılarak çalıştırılabilir:
! PL/SQL programları büyük harf-küçük harf ayrımına karşı duyarlı değildir. Yani bir
deyim ya da değişken istenirse küçük, istenirse büyük harflerle yazılabilir. Programın
işleyişi bundan etkilenmez.
DECLARE
adı VARCHAR2(20);
musteri_no NUMBER(5);
Bir değişken bu şekilde tanımlandıktan sonra, program içinde bu değişkene belirli bir
değer atanabilir, yani bir değer yerleştirilebilir. Bir değişkene bir değeri atamak için “:=”
işareti kullanılır. Örneğin, musteri_no değişkenine 196 değerini atamak için şöyle bir
tanım yapılır:
musteri_no := 196;
Bir değişkene program içinde bu şekilde bir atama yapılabileceği gibi, gerektiğinde
bildirimler bölümünde bir başlangıç değer atanabilir. Örneğin, musteri_no değişkenine
aşağıda görüldüğü gibi, bildirimler bölümünde bir değer atanabilir.
162
DECLARE
adı VARCHAR2(20);
musteri_no NUMBER(5) :=196;
DECLARE
PI CONSTANT REAL :=3.14159;
163
PL/SQL blokları DDL deyimlerini desteklemez. Bu deyimler, bildiğiniz gibi, veri tabanı
içindeki tabloları yaratma ve yok etme ya da özelliklerini değiştirme ile ilgilidir. O nedenle
CREATE TABLE, ALTER TABLE, DROP TABLE ve bunun gibi DDL deyimlerini PL/SQL blokları
içinde kullanamayız.
PL/SQL blokları içinde SELECT deyimi kullanılabilir. Bunun için, SQL deyimlerinin aşağıda
belirtilen yapıya sahip olması gerekmektedir.
! Burada INTO anahtar kelimesine dikkat etmek gerekmektedir. Bu kelime, seçilen sütun
değerlerinin hangi değişkene ya da kayıta aktarılacağını belirlemektedir. Sözü edilen
değişkenler PL/SQL bloğununun DECLARE bölümünde tanımlanmış olmalıdır.
! SELECT deyiminin kullanımında dikkat edilecek önemli bir nokta daha bulunmaktadır.
PL/SQL blokları içinde yer alacak SELECT sorgularında sadece bir satırın döndürülmesi
gerektiği unutulmamalıdır. Her bir SELECT deyimi “;” işareti ile son bulmalıdır.
Örnek
Veri tabanında yer alan personel isimli tablodan personel numarası 101 olan personeli
seçerek adını v_adi isimli bir değişken içine yerleştirmek istiyoruz.
DECLARE
v_adi VARCHAR2(10) ;
BEGIN
SELECT adi
INTO v_adi
FROM personel
WHERE personel_no=101;
164
…
END;
Örnek 1
Veri tabanında yer alan personel isimli tabloya bir kayıt eklemek istiyoruz.
Amacımıza uygun olarak düzenlenen PL/SQL bloğunu görmek için linke tıklayınız
BEGIN
INSERT INTO personel(personel_no,adi,giris_tar,ucret)
VALUES(101,'BURAK','15/03/1970',7000)
END;
Örnek 2
Veri tabanında yer alan personel isimli tabloda, personel numarası 101 olan personelin
ücretine %25 zam yapmak istiyoruz.
İlgili personelin ücret bilgisinin nasıl güncelleştirildiğini görmek için linke tıklayınız
DECLARE
v_ucret NUMBER :=1.25;
165
BEGIN
UPDATE personel
SET ucret=ucret*v_ucret
WHERE personel_no=101;
END;
Örnek 3
DECLARE
v_personel_no personel.personel_no%TYPE :=101;
BEGIN
DELETE FROM personel
WHERE personel_no=v_personel_no;
END;
Örnek
DECLARE
v_ucret NUMBER :=1.25;
BEGIN
UPDATE personel
SET ucret=ucret*v_ucret
WHERE personel_no=101;
COMMIT;
END;
/
166
Bazı değişkenlerin bildirimi bazı durumlarda PL/SQL blokları içinde tanımlanmaz. Bu
değişkenler PL/SQL bloğu dışında bir ortamda tanımlanır. Örneğin, SQL*Plus ortamında
daha önce tanımlanmış bir değişken PL/SQL içinde doğrudan kullanılabilir. Bunun için
değişkenin başına (:) işareti yerleştirilir. Bir bağlı değişken (bind variable) şu şekilde
tanımlanır:
O halde bir bağlı değişkeni, yani PL/SQL bloğu dışında bir değişkeni tanımlamak için,
VARIABLE deyimi içinde önce ilgili değişkenin adı, ardından o değişkenin veri türü
belirlenir. Bir bağlı değişkenin içerdiği değeri görüntülemek için PRINT komutu kullanılır.
Bu deyim şu şekilde tanımlanır:
Örnek 1
Aşağıdaki PL/SQL deyimlerini göz önüne alalım. PL/SQL bloğu başında SQL*Plus’un
VARIABLE komutu yardımıyla g_adi değişkenini tanımlıyoruz.
ifadeleri bir g_adi isimli değişkeni tanımlamaktadır. Bu değişken PL/SQL bloğu tarafından
kullanılmaktadır. PL/SQL bloğunun kullandığı değişken DECLARE bölümü içinde
tanımlanmaktadır:
DECLARE
v_adi VARCHAR2(10) ;
Bloğun işlem kısmı BEGIN ile başlamaktadır. Bu bölümde bir SELECT deyimi
çalıştırılmaktadır. Söz konusu deyim, personel tablosunda personel numarası 101 olan
personelin adını seçmektedir.
BEGIN
167
SELECT adi
INTO v_adi
FROM personel
WHERE personel_no=101;
Blok içindeki SELECT deyimi çalıştığında, seçilen personel adı v_adi isimli değişken içine
yerleşecektir. Bu sonucu kullanabilmek için bir dış değişkene aktarıyoruz. Sözü edilen dış
değişkeni VARIABLE deyimi ile en başta tanımlamıştık. v_adi değişkeninin içerdiği değer
g_adi değişkeni içine şu şekilde aktarılmaktadır:
:g_adi := v_adi ;
Artık g_adi isimli değişkenin içeriğini görüntüleyebiliriz. Bunun için SQL*Plus ortamında
PRINT komutu şu şekilde kullanılır.
G_ADI
--------------------------------
BURAK
Örnek 2
Bir x bağlı değişkenini tanımladıktan sonra bu değişkene PL/SQL bloğu yardımıyla 100
değerini atamak istiyoruz. Bu işlemin ardından x değişkeni içeriği görüntülenecektir.
! Son satırda “/” işareti yer aldığı için bu yordam çalışmaya başlar. Bu PL/SQL bloğu
aşağıda görülen sonuç elde edilir:
SQL> PRINT X;
X
----------
100
168
amaca ulaşmak için, DBMS_OUTPUT.PUT_LINE()paketi kullanılır. Bu paket şu şekilde
tanımlanır:
komutunun çalıştırılmış olması gerekmektedir. Aksi takdirde söz konusu paket etkili
olmayacaktır.
Örnek
Veri tabanındaki personel isimli tablodan 101 numaralı personelin adını bulacağız. Bunun
için, öncelikle PL/SQL bloğunun SQL*Plus ortamında istenen sonucu verebilmesi için
aşağıda görüldüğü biçimde bir tanım yapılmalıdır:
DECLARE
v_adi VARCHAR2(10) ;
BEGIN
SELECT personel_no, adi
INTO v_no, v_adi
FROM personel
WHERE personel_no=101;
-- Sonuç görüntüleniyor …
DBMS_OUTPUT.PUT_LINE (v_adi);
END;
BURAK
DECLARE
v_no VARCHAR2(10) ;
v_adi VARCHAR2(10) ;
BEGIN
SELECT personel_no, adi
INTO v_no, v_adi
FROM personel
WHERE personel_no=101;
169
-- Sonuç görüntüleniyor …
DBMS_OUTPUT.PUT_LINE (v_no ||' ' ||v_adi);
END;
101 BURAK
Örnek
DECLARE
170
fis_no NUMBER(5) :=0;
durum BOOLEAN := FALSE;
Bu tanımdan şu anlaşılmaktadır: fis_no isimli NUMBER veri türüne sahip bir değişkene 0
başlangıç değeri; durum isimli BOOLEAN veri türüne sahip bir değişkene FALSE değeri
atanmaktadır. Bunun yerine, aynı anlamı taşımak üzere şu şekilde bir tanım yapılabilir:
DECLARE
fis_no NUMBER DEFAULT 0;
durum BOOLIAN DEFAULT FALSE;
Normal olarak bir değişken NULL değerler içerebilir. Bir değişkenin NULL değerler
içermesini önlemek gerekebilir. Bu tür bir sınırlama koyabilmek için, değişken
bildirimlerine NOT NULL anahtar kelimeleri eklenebilir.
Örnek
DECLARE
fis_no NUMBER(5) NOT NULL :=0;
durum BOOLEAN := FALSE;
Bu tanımdan şu anlaşılmaktadır: fis_no isimli NUMBER veri türüne sahip bir değişkene 0
başlangıç değeri atanmaktadır. Söz konusu değişkene daha sonra bir başka değer
atanabilir. Ancak hiçbir zaman NULL değer atanamaz, yani boş bırakılamaz.
Bir değişkenin sahip olduğu veri türünü bir başka değişken için de geçerli kılınabilir. Böyle
bir amaca ulaşabilmek için %TYPE anahtar kelimesinden yararlanılır. Bu anahtar kelime şu
şekilde kullanılır:
171
değişken%TYPE
Örnek 1
DECLARE
tutar REAL(9,2);
DECLARE
tutar REAL(9,2);
bolum_tutar REAL(9,2);
DECLARE
tutar REAL(9,2);
bolum_tutar TUTAR%TYPE;
Örnek 2
Aşağıdaki PL/SQL bloğunu göz önüne alalım. DECLARE bölümünde tanımlanan değişken,
personel tablosunun ucret isimli sütunu ile ilişkilidir. O nedenle, değişken türünü
belirlerken %TYPE ifadesinden yararlandık.
DECLARE
v_ucret personel.ucret%TYPE :=1.25;
BEGIN
172
UPDATE personel
SET ucret=ucret*v_ucret
WHERE personel_no=101;
END;
PL/SQL bildirimler bölümünde, bir tablo içindeki satırın kayıt türünü simgelemek üzere
%ROWTYPE anahtar kelimesi kullanılır. Burada sözü edilen kayıt, bir tablodan veya bir
imleç (cursor) yardımıyla elde edilebilir. İmleçleri ve kullanım biçimlerini daha sonraki
derslerimizde ayrıntılı olarak ele alarak inceleyeceğiz.
İmleç, kısaca söz etmek gerekirse, SQL deyimlerini çalıştırmak için gereksinim duyulan
bellek alanlarıdır. Önceki konularımızda ayrıntılı biçimde öğrendiğimiz SQL’in SELECT
deyimi ile bir tablodan okunan sonuçlar, bir imleç üzerine yerleştirilir ve imleç üzerinde
bir kayıt kümesi oluşturulur. PL/SQL deyimleri yardımıyla bu kayıtlar işleme tabi tutulur.
Örnek
DECLARE
pers_kayit personel%ROWTYPE
CURSOR c1 IS SELECT adi_soyadi, numara, bölüm_no
FROM personel;
bolum_kayit c1%ROWTYPE;
pers_kayit personel%ROWTYPE
173
tanımıdır. Bu tanım, personel isimli bir tablodan okunan her bir kayıdı pers_kayit
olarak belirlemektedir. Yani tablonun her bir satırı pers_kayit adıyla saklanmaktadır.
İkinci %ROWTYPE tanımı ise,
bolum_kayit c1%ROWTYPE;
satırı ise, bir imleci belirlemektedir. Buna göre, personel tablosundan SELECT
deyimi ile seçilen sonuçlar için c1 imleci atanmaktadır. SELECT deyiminin nasıl
kullanıldığını ve yazılan ifadelerin ne anlama geldiğini önceki derslerden
biliyorsunuz.
174
Veri türü Anlamı
175
Örnek
DECLARE
adi VARCHAR2(20);
personel_no BUNBER(8);
ucret NUMBER(7,2);
adres VARCHAR2(200);
dogum_tar DATE;
5.13 İfadeler
Değişkenlere doğrudan bir değerin atanması yerine, bir ifadenin atanması da söz konusu
olabilir. Örneğin bir aritmetik ifade tanımlanarak sonucunun atanması mümkündür.
Üstelik mantıksal ifadeler de tanımlanarak sonucun doğru ya da yanlış olma durumuna
göre TRUE ya da FALSE değerleri atanabilecektir.
Örnek
sayac := sayac+1;
ssk_primi := brut_ucret*oran;
zamli_ucret := aylik_ucret*1.45;
durum := calisilan_saat>225;
176
5.14 İşleçler
Aritmetik işlemler başta olmak üzere, büyüklüklerin karşılaştırılması ve mantıksal
karşılaştırmaların yapılmasını sağlamak için işleç (operatör) adı verilen simgelere
başvurulur. PL/SQL programlarında en çok aşağıda belirtilen işleçler kullanılmaktadır.
Bölme işlemlerinde paydanın sıfır değere sahip olmamasına dikkat etmek gerekiyor.
Örnek
Aşağıdaki satırları inceleyiniz. Burada üç ifade yer almaktadır. Bu ifadeler içinde aritmetik
işleçlerin kullanıldığını görüyoruz:
177
Bu işleçler iki sayısal değeri ya da iki karakteri karşılaştırmak amacıyla kullanılır. Söz
konusu bu işleçler çoğunlukla program içindeki karşılaştırma deyimleri ile birlikte
kullanılır. Karşılaştırma işleçlerini yandaki tablo üzerinde sunuyoruz.
İki veya daha fazla koşul, doğruluk değerleri göz önüne alınarak birlikte değerlendirilir.
Koşullardan birincisine x , ikincisine ise y adını verelim. Bu iki koşulun değil, ve ile veya
işleçlerine göre doğruluk tablosu aşağıda verildiği gibidir.
178
Program içinde birden fazla koşul birlikte kullanılıyorsa, yukarıdaki tabloda yer alan
doğruluk değerleri kullanılır.
Açıklama satırını PL/SQL programı içine yerleştirmek için, satırın baş tarafına “--“
işaretleri kaydedilir. Örneğin şu şekilde bir açıklama satırı oluşturulabilir:
Eğer açıklama satırı birden fazla ise, her satırın başına bu işaretleri kaydetmek yerine,
açıklama satırının başlangıcına “/*” işareti, sonuna ise “*/” işareti kaydedilir. Örnek
olarak aşağıdaki tanım yapılabilir.
179
180
181
182
183
184
PROGRAM DENETİMİ
Bu bölümde;
anlatılmaktadır.
Bölüm Hedefi
Bu bölümde aşağıda sıralanan konular ele alınarak
incelenecektir:
Bir PL/SQL programında karşılaştırma işlemi sonucunda bir eylemin yapılması söz konusu
ise, yani belirli deyimlerin çalıştırılması gerekiyorsa IF..THEN deyimine başvurulur. Bu
deyim şu şekilde tanımlanır:
IF koşul THEN
Deyimler;
END IF
Bu tanıma göre, ifade içinde belirtilen koşulun “doğru” olması halinde, IF..THEN ile END
IF arasında belirtilen deyimler çalışır. Eğer koşulun doğruluk değeri “yanlış” ise bu
aralıkta içinde tanımlanan deyim işlem görmez.
185
Örnek 1
PL/SQL bloğu içinde bir sayi isimli bir değişken tanımladıktan sonra bu değişkenin içine
90 değerini yerleştireceğiz. Daha sonra bu değişken değerini IF deyimi ile denetleyerek
100 den küçük olup olmadığını denetleyeceğiz. Bu koşul gerçekleşiyorsa bir mesaj değeri
elde edilecektir. Mesajı görüntülemek için mesaj isimli bir bağlı değişken, yani aşağıdaki
şekilde bir dış değişken tanımlanır.
DECLARE
sayi number(5) :=90;
BEGIN
IF sayi < 100
THEN
:mesaj :='kosul dogru ';
END IF;
END;
/
Program çalıştıktan sonra mesaj hemen görüntülenmez. mesaj isimli değişkenin içeriğini
görüntülemek için PRINT deyimini kullanıyoruz.
186
MESAJ
--------------------------------
KOŞUL DOĞRU
Örnek 2
personel tablosunu okuyarak, 5000' den fazla ücret alan olup olmadığını denetlemek
istiyoruz. Bunun için mesaj' ı yerleştirmek üzere bir dış değişken tanımlıyoruz.
DECLARE
buyuk_ucret NUMBER(9);
BEGIN
SELECT MAX(ucret) INTO buyuk_ucret FROM personel; IF buyuk_ucret >
5000
THEN
:mesaj :='5000 den fazla ücret alan var..';
END IF;
END;
/
Bu PL/SQL bloğu çalıştırıldıktan sonra PRINT komutu ile mesaj değişkeninin içeriğini
öğreniyoruz:
MESAJ
-------------------------------
5000 DEN FAZLA ÜCRET ALAN VAR..
IF koşul THEN
deyim 1;
ELSE
deyim 2;
187
END IF
Bu tanıma göre, ifade içinde belirtilen koşulun “doğru” olması halinde, IF içinde belirtilen
deyim 1 çalışır. Aksi durumda, yani koşulun doğruluk değeri “yanlış” ise deyim 2 deyimi
işlem görür.
Örnek
Bir SAYI değişkenine 200 değerini yerleştiriyoruz. Bu sayının 200 den küçük olup
olmadığını denetlemek istiyoruz. Koşulun gerçekleşmediği durumda farklı bir mesajı
görüntülemek için ELSE deyimi kullanılıyor. Mesajı görüntülemek için MESAJ isimli bir bağlı
değişken, yani bir dış değişken tanımlıyoruz.
DECLARE
sayi number(5) :=200;
BEGIN
IF sayi < 100
THEN
:mesaj :='KOŞUL DOĞRU ';
ELSE
:mesaj :='KOŞUL YANLIŞ ';
END IF;
END;
/
Bu program çalıştırıldıktan sonra PRINT deyimi ile aşağıdaki sonuç elde edilir.
188
Blok çalıştırıldığında oluşan çıktıyı görmek için linke tıklayınız
MESAJ
--------------------------------
KOŞUL YANLIŞ
IF koşul THEN
deyimler
ELSE
IF koşul THEN
deyimler
ELSE
deyimler
END IF;
END IF;
Bu tanım yerine, ELSE ve IF kelimeleri ELSIF biçiminde birleştirilerek yandaki ifade biçimi
de kullanılabilir. Bu durumda END IF deyimleri de ortak hale gelmiş olur.
IF koşul THEN
deyimler
ELSEIF koşul THEN
deyimler
ELSE
deyimler
END IF;
Örnek
Verilen üç adet sayısal değerin en küçüğünü bulan bir PL/SQL bloğu yazmak istiyoruz.
189
Program içinden elde edilen sonucu aktarmak için bir SONUC isimli değişkeni SQL*Plus
ortamında şu şekilde tanımlıyoruz:
190
-- Bu PL/SQL bloğu üç sayısal değer
-- arasından en küçük olanını seçer..
DECLARE
a NUMBER(5) :=7;
b NUMBER(5) :=5;
c NUMBER(5) :=11;
kucuk NUMBER;
BEGIN
IF a < b
THEN
IF b<c
THEN
kucuk :=a;
END IF;
ELSIF b>c
THEN
KUCUK :=c;
ELSE
KUCUK:=b;
END IF;
:sonuc :=kucuk;
END;
/
SONUC
----------
5
191
PL/SQL bloklarında kullanılabilecek döngüler içinde en basit yapılı olanlarıdır. Bu tür
döngülere basit döngüler'in yanı sıra sonsuz döngüler adı da verilmektedir. Söz
konusu döngü şu şekilde tanımlanmaktadır:
LOOP
deyimler;
END LOOP;
Görüldüğü gibi bu döngünün sonunu belirleyen herhangi bir deyim yoktur. Döngüden
çıkma olasılığı yoktur. O nedenle bu tür döngüye sonsuz döngü deniliyor.
LOOP
…
IF koşul
THEN
EXIT;
END IF;
…
END LOOP;
192
Örnek
Bir PERSON isimli tabloya altı adet kayıt eklemek istiyoruz. Tablo iki sütundan
oluşmaktadır. Biz sadece birinci sütununa birden başlayan ve her defasında 1 artan bir
sayısal değer yerleştireceğiz. İkinci sütun ise boş kalacaktır. Amacımıza uygun PL/SQL
bloğunu LOOP döngüsü ile yaratıyoruz. Yeni eklenen personel numaraları ise 500 ile 506
arasında olacaktır.
DECLARE
sayi NUMBER := 500;
BEGIN
LOOP
-- Tabloya kayıt ekleme işlemi..
INSERT INTO person(per_no,per_adi)
VALUES (sayi, NULL);
sayi:= sayi + 1;
--Eğer 506 numaraya ulaşılmış ise
--Döngü terkedilecektir..
IF sayi >506
THEN
EXIT;
END IF;
END LOOP;
END;
/
Bu blok çalıştırıldığında, PERSON isimli tablo içine 7 adet yeni kayıt eklendiği ve personel
numarası olarak 500 ile 506 sayıları arasındaki değerlere yer verildiği görülecektir.
Tablonun içeriğini görüntülediğimizde, söylediklerimizin gerçekleştiği anlaşılır:
193
Blok çalıştırıldığında oluşan çıktıyı görmek için linke tıklayınız
PER_NO PER_ADI
---------- ---------
500
501
502
503
504
505
506
LOOP
…
EXIT WHEN koşul;
…
END LOOP;
Bu tanıma göre, LOOP döngüsü içinde EXIT WHEN ile belirlenen bir koşul gerçekleştiğinde
bu döngü terk edilecektir.
Örnek
194
Önceki örneği yeniden ele alalım. Bu örnek şu şekilde idi: Bir PERSON isimli tabloya altı
adet kayıt eklemek istiyoruz. Tablo iki sütundan oluşmaktadır. Biz sadece birinci
sütununa birden başlayan ve her defasında 1 artan bir sayısal değer yerleştireceğiz. İkinci
sütun ise boş kalacaktır. Amacımıza uygun PL/SQL bloğunu LOOP döngüsü ile yaratıyoruz.
Yeni eklenen personel numaraları ise 500 ile 506 arasında olacaktır. Bu kez WHEN EXIT
deyimlerini kullanarak sonsuz döngüden çıkacağız.
DECLARE
sayi NUMBER := 500;
BEGIN
LOOP
-- Tabloya kayıt ekleme işlemi..
INSERT INTO person(per_no,per_adi)
VALUES (sayi, NULL);
sayi:= sayi + 1;
--Eğer 506 numaraya ulaşılmış ise
--Döngü terkedilecektir..
EXIT WHEN sayi >506;
END LOOP;
END;
/
Bu PL/SQL bloğu çalıştırıldıktan sonra PERSON tablosuna belirlenen miktarda kayıt eklenir.
PER_NO PER_ADI
---------- ---------
500
501
502
503
504
505
506
Bir koşulun gerçekleşmesi durumunda belirli işlemlerin tekrarlanması söz konusu ise
WHILE döngülerinden yararlanılır. Bu döngü aşağıdaki şekil üzerinde görüldüğü biçimde
çalışmaktadır. Koşul sağlanmadığı sürece döngü içindeki hiçbir deyim çalışmayacaktır. Bu
denetim döngü bloğunun başında yapılır. Söz konusu WHILE döngüsü şu şekilde
tanımlanmaktadır:
WHILE koşul
195
LOOP
deyimler;
END LOOP;
Örnek 1
5 sayısal değerinden daha küçük olan tüm tamsayıları listelemek istiyoruz. Bu amaçla
aşağıda görüldüğü biçimde, WHILE deyimini kullanarak bir PL/SQL bloğu hazırlayabiliriz.
Listeyi elde etmek için DBMS_OUTPUT.PUT_LINE()paketini kullanıyoruz.
196
Blok çalıştırıldığında oluşan çıktıyı görmek için linke tıklayınız
Örnek 2
Daha önce ele alarak inceledğimiz bir örneği yeniden göz önüne alıyoruz: Bir PERSON
isimli tabloya altı adet kayıt eklemek istiyoruz. Tablo iki sütundan oluşmaktadır. Biz
sadece birinci sütununa birden başlayan ve her defasında 1 artan bir sayısal değer
yerleştireceğiz. İkinci sütun ise boş kalacaktır. Amacımıza uygun PL/SQL bloğunu bu kez
WHILE döngüsü ile yaratıyoruz. Yeni eklenen personel numaraları 500 ile 506 arasında
olacaktır.
DECLARE
sayi NUMBER := 500;
n NUMBER :=506;
BEGIN
WHILE sayi <= n
LOOP
-- Tabloya kayıt ekleme işlemi..
INSERT INTO person(per_no,per_adi)
VALUES (sayi, NULL);
sayi:= sayi + 1;
END LOOP;
END;
/
PER_NO PER_ADI
---------- ---------------
500
197
501
502
503
504
505
506
PL/SQL bloğu içinde bir ya da daha fazla sayıda deyimin belirli bir koşulun
gerçekleşmesine dek tekrarlanması söz konusu ise FOR deyimi kullanılır. Bu deyim şu
şekilde tanımlanmaktadır:
LOOP
deyimler;
END LOOP;
Bu deyimden şu anlaşılmaktadır: Döngü bir sayaca göre yapılacaktır. Yani her bir döngü
işlemi sayılacaktır. Döngü işlemi sayaç tamamlanıncaya dek devam edecektir. Sayaç
tamamlandığında döngü terk edilerek bir sonraki deyim işlem görmeye başlar.
Örnek 1
0 ile 5 arasındaki sayısal değerleri listelemek için bir PL/SQL bloğu hazırlayabiliriz.
198
DECLARE
BEGIN
-- Döngü tanımlanıyor..
FOR i IN 0..5
LOOP
-- sonuclar listeleniyor...
DBMS_OUTPUT.PUT_LINE (i);
END LOOP;
END;
/
Örnek 2
Klavye yardımıyla girilen iki tamsayı arasında kalan tüm tüm sayıların toplamını bulmak
istiyoruz. Başlangıc ve son sayılar bu toplama dahil edilmeyecektir.
199
6.2.4 Döngü Etiketleri
Bazı uygulamalarda içi içe döngüler yer alabilir. Örneğin bir LOOP döngüsü içinde bir
başka LOOP döngüsü yer alabilir. Bu tür döngülerde, döngülerden çıkış anında bir sorun
ile karşılaşılır.
Döngüden çıkış deyimi olarak kullanılan EXIT deyimi sadece en içteki döngüden çıkışı
sağlar. Ancak bazı durumlarda iç içe döngüden tümüyle çıkmak söz konusu olabilir. Böyle
durumlarda döngü etiketleri kullanılabilir. Bir döngüyü etiketlendirmek için şu şekilde bir
tanım yapılır:
<<etiket>>
<<durum1>>
LOOP
deyimler;
Örnek
Aşağıdaki PL/SQL bloğu içinde, iç içe iki LOOP döngüsü bulunmaktadır. İkinci LOOP içinde
yer alan EXIT deyimi çalıştığında, her iki döngü de terk edilir.
<<son1>>
LOOP
200
…
LOOP
…
EXIT son1 WHEN ….
END LOOP;
…
END LOOP son1;
GOTO etiket;
Doğal olarak böyle bir işlemin gerçekleşebilmesi için belirtilen etiketin blok içinde
tanımlanmış olması gerekmektedir. Bu deyim dikkatli biçimde kullanılmalıdır. Örneğin, bir
IF deyiminde THEN bloğunda GOTO deyimi ile ELSE bloğun atlamak yanlış bir davranış
olacaktır.
Örnek
Blok içinde satir_gir isimli etikete sapılmasını sağlayan tanım aşağıda gösterildiği
biçimde yapılabilir:
BEGIN
…
GOTO satir_gir;
…
<<satir_gir>>
201
INSERT INTO personel VALUES …
END;
202
203
204
205
206
PL/SQL TABLOLARI VE KAYITLARI
Bu bölümde,
• PL/SQL Tabloları
• Kullanıcı Tanımlı PL/SQL Kayıtları
anlatılmaktadır.
Bölüm Hedefi
Bu bölümde aşağıda sıralanan konular ele alınarak
incelenecektir:
• Kayıtların Kullanılması
PL/SQL tabloları, PL/SQL bloklarında dizi (array) kullanma gereksinimini karşılar. Aslında
PL/SQL tabloları bir diziye benzer. Dizilerde olduğu gibi, aynı türdeki verileri içerir. Bu
tablonun her bir elemanı bir benzersiz (unique) indekse sahiptir.
207
7.1.1 PL/SQL Tablolarının Yaratılması
PL/SQL tablolarının kullanılabilmesi için, PL/SQL blokları içinde DECLARE bölümünde
tanımlanması gerekmektedir. Bir PL/SQL tablosu yanda belirtildiği biçimde yaratılır.
INDEX BY BINARY_INTEGER;
Tablonun indeksi BINARY_INTEGER veri türüne sahip olmalıdır. Bu veri türü -2147483647
ile +2147483647 arasındaki tamsayıları simgeler.
208
tablo adı tablo veri türü;
Örnek 1
Bir PL/SQL tablosu yaratmak istiyoruz. Bu tablo tarih veri türüne sahip veriler içerecektir.
! Amacımıza uygun tablo tanımını görmek için tablo tanımı düğmesine tıklayınız.
DECLARE
TYPE tarih IS TABLE OF DATE
INDEX BY BINARY_INTEGER;
tarih_dizi tarih;
Burada TYPE deyimi ile bir PL/SQL tablosu için veri türü tanımı yapılmaktadır. Tanımın
hemen ardından, bu tanım bir değişkene atanarak, bloklar içinde kullanılabilmesi için
hazır hale getirilmektedir.
DECLARE
TYPE ucret_turu IS TABLE OF personel.ucret%TYPE
INDEX BY BINARY_INTEGER;
ucret_tablo ucret_turu;
tablo_adı (indeks)
Örneğin test_tablo isimli bir PL/SQL tablosunun üçüncü elemanına ulaşmak için,
test_tablo(3)…
Örnek 1
Bir PL/SQL tablosu içine üç değeri yerleştirdikten sonra bu değerleri tek tek görüntülemek
istiyoruz.
209
Amacımıza uygun PL/SQL bloğunu görmek için linke tıklayınız.
101
119
125
Örnek 2
Veri tabanında yer alan personel tablosunda en yüksek ücretin ne olduğunu belirleyerek,
bu değeri bir tablo içine yerleştirmek istiyoruz.
DECLARE
-- tablo tanımlanıyor..
TYPE ucret_turu IS TABLE OF personel.ucret%TYPE
INDEX BY BINARY_INTEGER;
ucret_tab ucret_turu;
BEGIN
-- personel tablosundan okunan değer
-- PL/SQL tablosuna yerleştiriliyor..
210
SELECT MAX(ucret)
INTO ucret_tab(1)
FROM PERSONEL;
DBMS_OUTPUT.PUT_LINE (ucret_tab(1));
END;
Bu blok çalıştırıldığında, personel ücetleri arasında en fazla olanı SELECT deyimi ile
bulunur ve bu değer ucret_tab tablosunun birinci elemanı olarak atanır.
8750
Örnek 3
Bu kez aynı tablodan en fazla ve en az ücretleri elde ederek PL/SQL tablosu içine
yerleştirmek ve sonuçları listelemek istiyoruz.
DECLARE
-- tablo tanımlanıyor..
TYPE ucret_turu IS TABLE OF personel.ucret%TYPE
INDEX BY BINARY_INTEGER;
ucret_tab ucret_turu;
BEGIN
-- personel tablosundan okunan değerler
-- PL/SQL tablosuna yerleştiriliyor..
SELECT MAX(ucret), MIN(ucret)
INTO ucret_tab(1) , ucret_tab(2)
FROM PERSONEL;
DBMS_OUTPUT.PUT_LINE (ucret_tab(1));
DBMS_OUTPUT.PUT_LINE (ucret_tab(2));
END;
8750
2000
211
PL/SQL tabloları yaratıldıktan sonra üzerinde birçok işlem yapılabilir. Bunun için tabloya
ilişkin belirli öznitelikler (attribute) kullanılabilmektedir. Aşağıda bu öznitelikleri
özetliyoruz. PL/SQL tablo öznitelikleri şu şekilde tanımlanır:
212
213
7.1.3.1 Tablonun Eleman Sayısı
Bazı uygulamalarda PL/SQL tablosunun kaç elemandan oluştuğunu bulmak gerekebilir.
Böyle durumlarda PL/SQL tablolarının COUNT özniteliği kullanılır. Bu öznitelik şu şekilde
tanımlanıyor:
tablo adı.COUNT
Örnek
personel tablosunda en az ve en fazla ücretleri elde ettikten sonra bir PL/SQL tablosuna
yerleştiriyoruz ve daha sonra bu tablonun elemanlarını ekran üzerinde listeliyoruz.
Listelemeyi FOR döngüsü ile yapıyoruz. Döngü sınırı PL/SQL tablosunun eleman sayısı
kadar olmalıdır. Bunu sağlamak için COUNT kullanılıyor.
DECLARE
-- tablo tanımlanıyor..
TYPE ucret_turu IS TABLE OF personel.ucret%TYPE
INDEX BY BINARY_INTEGER;
ucret_tab ucret_turu;
BEGIN
-- personel tablosundan okunan değerler
-- PL/SQL tablosuna yerleştiriliyor..
SELECT MAX(ucret), MIN(ucret)
INTO ucret_tab(1) , ucret_tab(2)
FROM PERSONEL;
FOR i IN 1..ucret_tab.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE (ucret_tab(i));
END LOOP;
END;
214
Blok çalıştırıldığında oluşan çıktıyı görmek için linke tıklayınız
8750
2000
tablo adı.FIRST
tablo adı.LAST
Örnek
Bir dizi içine beş adet sayısal değer yerleştirdikten sonra, tablonun birinci ve sonuncu
elemanının indekslerini elde etmek istiyoruz.
DECLARE
-- tablo tanımlanıyor..
TYPE test_turu IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;
test_tab test_turu;
BEGIN
215
-- tabloya değerler yerleştiriliyor..
test_tab(1) :=101;
test_tab(2) :=119;
test_tab(3) :=125;
test_tab(4) :=35;
test_tab(5) :=196;
DBMS_OUTPUT.PUT_LINE ('İlk=' ||test_tab.FIRST);
DBMS_OUTPUT.PUT_LINE ('Son=' ||test_tab.LAST);
END;
İlk=1
Son=5
DELETE
DELETE(n)
DELETE(m,n)
Birinci tanım tablonun tüm elemanlarının silinmesini sağlar. İkinci tanım belirli bir n
satırının silinmesini sağlar. Burada sözü edilen n ilgili tablonun indeks numarasıdır. Son
tanım ise n ve m gibi belirli iki satır arasındaki tüm satırların silinmesini sağlar.
216
Örnek 1
DECLARE
-- tablo tanımlanıyor..
TYPE test_turu IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;
test_tab test_turu;
BEGIN
-- tabloya değerler yerleştiriliyor..
test_tab(1) :=101;
test_tab(2) :=119;
test_tab(3) :=125;
test_tab(4) :=35;
test_tab(5) :=196;
-- tablonun 4. ve 5. elemanları siliniyor..
test_tab.DELETE(4,5);
-- tablonun son hali görüntüleniyor..
FOR i IN test_tab.FIRST .. test_tab.LAST
LOOP
DBMS_OUTPUT.PUT_LINE (test_tab(i));
END LOOP;
END;
101
119
125
Örnek 2
Önceki örneği yeniden ele alalım. Bu kez sadece 4. elemanını silmek istediğimizi
varsayalım.
217
DECLARE
-- tablo tanımlanıyor..
TYPE test_turu IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;
test_tab test_turu;
BEGIN
-- tabloya değerler yerleştiriliyor..
test_tab(1) :=101;
test_tab(2) :=119;
test_tab(3) :=125;
test_tab(4) :=35;
test_tab(5) :=196;
-- tablonun 4. elemanı siliniyor..
test_tab.DELETE(4);
-- tablonun son hali görüntüleniyor..
FOR i IN test_tab.FIRST .. test_tab.LAST
LOOP
DBMS_OUTPUT.PUT_LINE (test_tab(i));
END LOOP;
END;
218
Örnek
Aşağıda bir PL/SQL kayıt türü tanımlanmaktadır. Bu kayıt, p_no, p_adi ve p_ucret gibi
üç alandan oluşmaktadır. Bu kayıt türünün adı per_kayit_turu olarak belirlenmiştir.
DECLARE
TYPE per_kayit_turu IS RECORD (
p_no NUMBER(3),
p_adi VARCHAR2(15),
p_ucret NUMBER);
Bu tanım içindeki alan türleri, bir diğer değişkenden ya da bir veri tabanı tablosunun
alanlarından alınabilir. Böyle bir amaç için %TYPE anahtar kelimesini kullanıyoruz.
Aşağıdaki örnek, kaydın alanlarına ait veri türlerinin personel tablosundan kopyalandığını
göstermektedir:
DECLARE
TYPE per_kayit_turu IS RECORD (
p_no personel.personel_no%TYPE,
p_adi personel.adi%TYPE,
p_ucret personel.ucret_no%TYPE,);
kayıt_adı kayıt_türü_adı;
Örnek
Aşağıdaki blok içinde önce bir kayıt türü tanımlıyoruz ve ardından bu türe dayanarak
per_kayit isimli bir kayıt yaratıyoruz.
219
DECLARE
TYPE per_kayit_turu IS RECORD (
p_no NUMBER(3),
p_adi VARCHAR2(15),
p_ucret NUMBER);
per_kayit per_kayit_turu;
kayıt_adı.alan_adı
Örnek 1
DECLARE
-- Kayıt türü tanımlanıyor..
TYPE per_kayit_turu IS RECORD
(per_no NUMBER(3),
p_adi VARCHAR2(15),
p_ucret NUMBER);
-- Kayıt tanımlanıyor..
per_kayit per_kayit_turu;
BEGIN
-- alanlara bilgi yerleştiriliyor..
per_kayit.per_no := 305
per_kayit.p_adi := 'BEGUM';
220
per_kayit.p_ucret :=6650;
END;
305
BEGUM
6650
Örnek 2
personel tablosundan bazı verileri SELECT deyimi ile okuyarak kayıt alanlarına
yerleştirmek istiyoruz.
Bu amaca yönelik olarak düzenlenen PL/SQL bloğunu görmek için linke tıklayınız.
DECLARE
-- Kayıt türü tanımlanıyor..
TYPE per_kayit_turu IS RECORD (
per_no NUMBER(3),
p_adi VARCHAR2(15),
p_ucret NUMBER);
-- Kayıt tanımlanıyor..
per_kayit per_kayit_turu;
BEGIN
-- tablodan okunan veriler kayıt
-- alanlarına yerleştiriliyor..
SELECT personel_no, adi, ucret
INTO per_kayit.per_no, per_kayit.p_adi, per_kayit.p_ucret
FROM personel
WHERE personel_no=101;
-- alanlardaki bilgiler görüntüleniyor..
DBMS_OUTPUT.PUT_LINE (per_kayit.per_no);
DBMS_OUTPUT.PUT_LINE (per_kayit.p_adi);
DBMS_OUTPUT.PUT_LINE (per_kayit.p_ucret);
END;
221
101
BURAK
7000
Veri tabanındaki bir tablodan SELECT ya da FETCH deyimleri ile bilgi alınırken, kayıt
alanlarını tek tek tanımlamaya gerek olmayacaktır. FETCH deyimi imleçlerden bilgi
okumayla ilgili bir deyimdir. Bu deyimi daha sonraki konularımızda ele alarak
inceleyeceğiz. Böyle bir amaç şu şekilde bir tanım yapılmalıdır:
Bu tanımda görüldüğü gibi, bir veri tabanı tablosu kullanılacak ise, kaydın her bir alanı
için TYPE ile veri türü tanımını yapmaya gerek yoktur. Sadece yukarıda görüldüğü
biçimde kayıt adı tanımlanır.
Örnek
Veri tabanındaki personel isimli tablodan 110 numaralı personele ait bilgileri alarak bir
PL/SQL kayıtı üzerine yerleştireceğiz ve daha sonra bu bilgiler arasında iki alanın içeriğini
görüntüleyeceğiz.
DECLARE
-- Kayıt türü tanımlanıyor..
per_kayit personel%ROWTYPE;
BEGIN
-- tablodan okunan veriler kayıt alanlarına yerleştiriliyor..
SELECT *
INTO per_kayit
FROM personel
WHERE personel_no=110;
-- alanlardaki bilgiler görüntüleniyor..
DBMS_OUTPUT.PUT_LINE (per_kayit.personel_no);
DBMS_OUTPUT.PUT_LINE (per_kayit.adi);
END;
222
Blok çalıştırıldığında oluşan çıktıyı görmek için linke tıklayınız
110
DILAY
223
224
225
226
227
228
İMLEÇLER
Bu bölümde;
• İmleç
• Belirtilmiş İmleçler
• İmleçlerin Çalışma Biçimi
• İmleçlerin Tanıtılması
• İmleçlerin Açılması ve Kapatılması
• İmleçten Bilgi Alma
• İmleç Öznitelikleri
• İmleçlere Dayalı Kayıtlar
• FOR Döngüsü ile İmleçlerin Tanımlanması
• Parametrelerin Kullanımı
anlatılmaktadır.
Bölüm Hedefi
Bu bölümde aşağıda sıralanan konular ele alınarak
incelenecektir:
• İmleç Nedir?
• Belirtilmiş İmleçler
• İmleçlerin Çalışma Biçimi
• İmleçlerin Tanıtılması
• İmleçlerin Açılması ve Kapatılması
• İmleçten Bilgi Alma
• İmleç Öznitelikleri
• İmleçlere Dayalı Kayıtlar
• FOR Döngüsü ile İmleçlerin Tanıtılması
• Parametrelerin Kullanımı
229
Örtülü imleçler, önceki bölümde ele alarak incelediğimiz biçimde yaratılır. Bu tür imleçleri
yaratmak için özel bir işlem yapılmaz. SELECT veya DML deyimlerinin kullanıldığı bir
PL/SQL bloğunda örtülü imleçler otomatik olarak açılır. Bu tür imleçleri sorgulama
işlemlerinde kullanırken, sadece bir kayıt döndüren SELECT deyimleri için geçerli
olabileceği unutulmamalıdır.
230
8.2 Belirtilmiş İmleçler
Bir imleçi oluşturmak için herşeyden önce bir sorgulama işlemine ihtiyaç duyulur. SELECT
deyimi ile yapılan sorgu sonucunda elde edilen veriler imleç üzerine yerleşir.
231
8.4 İmleçlerin Tanıtılması
Bir imleci PL/SQL bloğu içinde kullanabilmek için öncelikle DECLARE bloğu içinde
tanımlanmış olması gerekmektedir. Bunun için CURSOR deyimine başvurulur. Söz konusu
deyim şu şekilde tanımlanır:
CURSOR imleç_adı
SELECT deyimi;
232
Örnek
DECLARE
CURSOR per_imlec IS
SELECT personel_no, adi
FROM personel;
deyimi kullanılır. Bir imleç kapatıldıktan sonra gerekiyorsa, OPEN deyimi ile yeniden
açılabilir.
233
Örnek
per_imlec isimli bir imleci tanımladıktan sonra açmak istiyoruz. Bunun için aşağıda
belirtildiği biçimde bir yol izlenir:
DECLARE
-- imlecin tanıtılması....
CURSOR per_imlec IS
SELECT personel_no, adi
FROM personel;
BEGIN
-- imlecin açılması...
OPEN per_imlec;
…
-- imlecin kapatılması...
CLOSE per_imlec;
END;
234
Örnek
personel tablosundan personelin numarasını ve adını okuyarak bir imleç içine yerleştiren
ve sonunda imleç içindeki bu değerleri listeleyen bir PL/SQL bloğu yazalım.
DECLARE
v_no personel.personel_no%TYPE;
v_adi personel.adi%TYPE;
-- imlecin tanıtılması....
CURSOR per_imlec IS
SELECT personel_no, adi
FROM personel;
BEGIN
-- imlecin açılması...
OPEN per_imlec;
-- imleç değerlerinin okunarak
-- değişkenlere atanması..
FOR i IN 1..5
LOOP
FETCH per_imlec INTO v_no, v_adi;
-- sonuçların görüntülenmesi…
DBMS_OUTPUT.PUT_LINE (v_no|| ' '||v_adi);
END LOOP;
-- imlecin kapatılması..
CLOSE per_imlec;
END;
101 BURAK
235
105 BEGUM
120 SELIN
110 DILAY
130 SEZIN
imleç adı%öznitelik
%NOTFOUND BOOLEAN En son FETCH işlemi bir satır döndürmemiş ise TRUE döndürür.
%FOUND BOOLEAN En son FETCH işlemi bir satır döndürmüş ise TRUE döndürür.
Örnek 1
PL/SQL bloğunda bir imlecin açık olup olmadığı denetleyen, eğer açık değil ise açılması
işlemi yerine getiren PL/SQL bloğu yazalım.
DECLARE
v_no personel.personel_no%TYPE;
v_adi personel.adi%TYPE;
-- imlecin tanıtılması....
CURSOR per_imlec IS
SELECT personel_no, adi
FROM personel;
BEGIN
-- imlecin açılması...
IF NOT per_imlec%ISOPEN
THEN
OPEN per_imlec;
END IF;
-- imleç değerlerinin okunarak
-- değişkenlere atanması..
236
FOR i IN 1..5
LOOP
FETCH per_imlec INTO v_no, v_adi;
-- sonuçların görüntülenmesi…
DBMS_OUTPUT.PUT_LINE (v_no|| ' '||v_adi);
END LOOP;
-- imlecin kapatılması..
CLOSE per_imlec;
END;
101 BURAK
105 BEGUM
120 SELIN
110 DILAY
130 SEZIN
Örnek 2
Önceki örnekte imleçten veri getirme işlemini FOR döngüsü içinde yapmıştık. Aynı bloğu
bu kez sonsuz LOOP döngüsü içinde düzenleyelim.
DECLARE
v_no personel.personel_no%TYPE;
v_adi personel.adi%TYPE;
-- imlecin tanıtılması....
CURSOR per_imlec IS
SELECT personel_no, adi
FROM personel;
BEGIN
-- imlecin açılması...
IF NOT per_imlec%ISOPEN
THEN
OPEN per_imlec;
END IF;
-- imleç değerlerinin okunarak
-- değişkenlere atanması..
LOOP
237
FETCH per_imlec INTO v_no, v_adi;
EXIT WHEN per_imlec%ROWCOUNT > 7 OR
per_imlec%NOTFOUND;
-- sonuçların görüntülenmesi…
DBMS_OUTPUT.PUT_LINE (v_no|| ' '||v_adi);
END LOOP;
-- imlecin kapatılması..
CLOSE per_imlec;
END;
101 BURAK
105 BEGUM
120 SELIN
110 DILAY
130 SEZIN
160 AHMET
200 ALI
Örnek
Veri tabanında yer alan personel isimli tablodan personel numarası ve isimlerini
okuyarak gecici isimli bir başka tabloya bu satırları eklemek istiyoruz.
DECLARE
-- imlecin tanıtılması....
CURSOR per_imlec IS
SELECT personel_no, adi
238
FROM personel;
-- imlece dayalı kayıtın tanımlanması..
per_kayit per_imlec%ROWTYPE;
BEGIN
OPEN per_imlec;
-- imleç değerlerinin okunarak kayıt içine
-- yerleştirilmesi ve diğer tabloya satır ekleme..
LOOP
FETCH per_imlec INTO per_kayit;
EXIT WHEN per_imlec%NOTFOUND;
INSERT INTO gecici (p_no, p_adi)
VALUES(per_kayit.personel_no,per_kayit.adi);
END LOOP;
per_kayit per_imlec%ROWTYPE;
ifadesi ile, per_kayit isimli bir kayıt tanımlandığı ve bu kayıt alanlarının imleç alanları ile
aynı isimde ve veri türünde olduğu anlaşılmaktadır. INSERT INTO işleminde ise bu
kayıtın alanları kullanılmaktadır. Bu blok çalıştırıldıktan sonra belirlenen kayıtlar gecici
isimli tablo içine eklenir. Bu tablonun içeriği görüntülenirse, amacımıza ulaştığımız
anlaşılır.
P_NO P_ADI
---------- ----------
101 BURAK
105 BEGUM
120 SELIN
110 DILAY
130 SEZIN
160 AHMET
200 ALI
150 AYBIKE
155 AYSE
250 ERSIN
300 HALIT
140 DILARA
350 ORCUN
239
İmleçleri tanımlamak ve kullanmak için nasıl bir yol izleneceğini görmüş bulunuyoruz.
Ancak imleçleri tanımlamak için çok kısa bir yol daha bulunmaktadır. Bu tanımlama FOR
döngüsü yardımıyla yerine getirilir. FOR deyimi bu amaçla şu şekilde tanımlanır:
FOR deyimi bu şekilde tanımlandığında, OPEN ile imleci açma, FETCH ile veri okuma ve
CLOSE ile imleci kapama işlemlerini tanımlamaya gerek yoktur. Bu işlemler ve kayıt
tanımlama işlemleri örtülü olarak (imlicit), yani FOR tarafından otomatik olarak
gerçekleştirilir.
LOOP
deyimler…
END LOOP;
Bu durumda DECLARE bloğunda imleci ve sorgu ifadesini tanımlamaya gerek yoktur. Hatta
imleçlerle ilgili şu ana kadar gördüğümüz deyimlerin hiçbirini kullanmaya gerek yoktur.
PL/SQL imleç işlemlerini örtülü olarak gerçekleştirir.
Örnek 1
personel isimli veri tabanı tablosundan personel numarası ile adını okuyarak, bu verileri
per_imlec imlecine yerleştirmek istiyoruz. Daha sonra bu imleç içindeki tüm satırları tek
tek görüntüleyeceğiz.
DECLARE
CURSOR per_imlec IS
SELECT personel_no, adi
FROM personel;
240
BEGIN
FOR per_kayit IN per_imlec LOOP
DBMS_OUTPUT.PUT_LINE (per_kayit.personel_no
|| ' ' ||per_kayit.adi);
END LOOP;
END;
PL/SQL bloğunda,
101 BURAK
105 BEGUM
120 SELIN
110 DILAY
130 SEZIN
160 AHMET
200 ALI
150 AYBIKE
155 AYSE
250 ERSIN
300 HALIT
140 DILARA
350 ORCUN
Örnek 2
Önceki örneği, FOR deyimi içinde sorgu işlemini yerleştirerek yeniden düzenleyelim.
241
BEGIN
FOR per_kayit IN (SELECT personel_no, adi
FROM personel)
LOOP
DBMS_OUTPUT.PUT_LINE (per_kayit.personel_no
|| ' ' ||per_kayit.adi);
END LOOP;
END;
Yukarıdaki PL/SQL bloğu çalıştırıldığında, aynen önceki örnekte olduğu gibi bir sonuç elde
edilir:
101 BURAK
105 BEGUM
120 SELIN
110 DILAY
130 SEZIN
160 AHMET
200 ALI
150 AYBIKE
155 AYSE
250 ERSIN
300 HALIT
140 DILARA
350 ORCUN
242
İmlece geçirilecek parametre bu şekilde tanımlandıktan sonra OPEN deyimi içinde sorguya
geçirilecek değer tanımlanır.
OPEN imleç_adı(değer);
Örnek
personel isimli veri tabanı tablosunda bölüm numarası 10 olan personeli seçerek
listelemek istiyoruz.
DECLARE
v_no personel.personel_no%TYPE;
v_adi personel.adi%TYPE;
-- imlecin tanıtılması....
CURSOR per_imlec (v_bolum NUMBER)
IS
SELECT personel_no, adi
FROM personel
WHERE bolum_no=v_bolum;
BEGIN
-- imlecin açılması ve parametre değerinin
-- imlece geçirilmesi...
OPEN per_imlec(10);
-- imleç değerlerinin okunarak değişkenlere
-- atanması..
LOOP
FETCH per_imlec INTO v_no, v_adi;
EXIT WHEN per_imlec%NOTFOUND;
-- sonuçların görüntülenmesi…
DBMS_OUTPUT.PUT_LINE (v_no|| ' '||v_adi);
END LOOP;
-- imlecin kapatılması..
CLOSE per_imlec;
END;
243
Blok çalıştırıldığında oluşan çıktıyı görmek için linke tıklayınız
101 BURAK
105 BEGUM
120 SELIN
244
245
246
247
KURAL DIŞI DURUMLARIN DENETLENMESİ
Bu bölümde;
anlatılmaktadır.
Bölüm Hedefi
Bu bölümde aşağıda sıralanan konular ele alınarak
incelenecektir:
PL/SQL bloklarında kural dışı durumlar BEGIN içinde tanımlanır. Bir kural dışı durum
ortaya çıktığında bunu çözümlemek ve ne yapılacağını tanımlamak üzere EXCEPTION
bloğu içinde bir tanım yapmak gerekecektir.
248
PL/SQL bloklarında kural dışı durumların denetlenmesi önemli bir konudur. Bu sayede
programların daha iyi denetlenmesi sağlanır. Blok çalıştırıldığında bir kural dışı durum ile
karşılaşıldığında, programın akışı bu noktadan itibaren EXCEPTION içindeki deyimlere
aktarılır ve böylece, bloğun çalışması EXCEPTION içindeki deyimlerin çalışması ardından
sona erer. Böylece BEGIN içinde kural dışı durumun ortaya çıktığı noktadan sonraki BEGIN
deyimleri işlem görmez.
WHEN anahtar kelimesi kural dışı durum ortaya çıktığında ne yapılacağını tanımlar. Birden
fazla WHEN kullanılabilir. WHEN OTHERS ise WHEN ile tanımlanan durumun dışında kalan
kural dışı durumlarda neler yapılacağını belirler.
Örnek
249
Bir tabloda aranılan kayıt bulunamadığında, NO_DATA_FOUND isimli kural dışı durum ortaya
çıkar. Bu durumu denetleyerek bir mesaj üretmek üzere aşağıdaki PL/SQL bloğunu
yazıyoruz:
DECLARE
v_adi personel.adi%TYPE;
BEGIN
-- tablodan okunan veriler değişken
-- içine yerleştiriliyor..
SELECT adi
INTO v_adi
FROM personel
WHERE personel_no=999;
-- personel adı görüntüleniyor..
DBMS_OUTPUT.PUT_LINE (v_adi);
EXCEPTION
-- kural dışı durum tanımlanıyor...
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE ('Kayıt bulunamadı.');
END;
Kayıt bulunamadı..
250
251
!Kural dışı durumlara ait iki örnek aşağıda verilmiştir. Örnekleri görmek için düğmelere
tıklayınız.
DECLARE
v_adi personel.adi%TYPE;
BEGIN
-- tablodan okunan veriler değişken içine
-- yerleştiriliyor..
SELECT adi
INTO v_adi
FROM personel;
-- personel adı görüntüleniyor..
DBMS_OUTPUT.PUT_LINE (v_adi);
EXCEPTION
-- kural dışı durum tanımlanıyor...
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Kayıt bulunamadı..');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('Birden fazla kayıt..');
END;
252
Birden fazla kayıt..
mesajının görüntülenmesine neden olacaktır. Çünkü, SELECT deyimi içinde herhangi bir
kısıt olmadığı için birden fazla kayıt seçilecektir. Bu tür bir uygulamada, SELECT deyiminin
sadece bir kayıt seçmesi beklenir. Buna karşılık, çok sayıda kayıt seçildiği için
TOO_MANY_ROWS durumu ortaya çıkmıştır.
Örnek 2
Programda belirtilen hazır kural dışı durumları kullanabildiğimiz gibi, söz konusu kural dışı
durumun türünü belirtmeden de denetleme yapabiliriz. Aşağıdaki örnek bu amaçla
hazırlanmıştır. Bu örnekte SELECT deyimi birden fazla satır seçtiği için bir kural dışı durum
ortaya çıkmıştır. Bunun için, önceki örnekte olduğu gibi TOO_MANY_ROWS hazır kural dışı
durum ifadesini kullanabiliriz. Bunun yerine, WHEN OTHERS ifadesini kullanarak sadece bir
hata ortaya çıktığını algılamak istiyoruz. Böyle bir amaca ulaşamak için aşağıdaki PL/SQL
bloğunu hazırlıyoruz.
DECLARE
v_adi personel.adi%TYPE;
BEGIN
-- tablodan veriler okunuyor..
SELECT adi
INTO v_adi
FROM personel;
-- personel adı görüntüleniyor..
DBMS_OUTPUT.PUT_LINE (v_adi);
EXCEPTION
-- kural dışı durum tanımlanıyor...
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Kayıt bulunamadı..');
253
Bu özel ifadeler veri tabanı sunucusunun iç hata kodlarına karşılık gelmektedir. Ancak bu
kodlar yerine özel isimleri kullandık. Bu özel kural dışı durumlar dışında daha pekçok
kural dışı durum mevcuttur. Söz konusu kural dışı durumları da denetlemek mümkündür.
Örnek
DECLARE
-- kural dışı durum tanımlanıyor…
h_bolum_no EXCEPTION;
PRAGMA EXCEPTION_INIT (h_bolum_no, -2292);
BEGIN
-- veritabanından bazı kayıtlar siliniyor..
DELETE FROM bolum
WHERE bolum_no=10;
COMMIT;
EXCEPTION
-- kural dışı durum yakalanıyor…
WHEN h_bolum_no THEN
DBMS_OUTPUT.PUT_LINE ('Kayıt silemezsiniz..');
END;
254
Bu blok çalıştığında, 10 numaralı bölüm silinemez. Çünkü bu tabloyla ilişkili olan
personel tablosunda 10 numaralı bölümde çalışan personel bilgileri yer almaktadır. O
halde bu bölümü bolum tablosundan silemeyiz. Böyle bir durumda, veri tabanı sunucusu
-2292 numaralı hata kodunu üretir. Bu hata kodunu, DECLARE bölümünde tanımlamıştık.
EXCEPTION bölümünde ise WHEN deyimi ile bu hata kodu algılanır ve aşağıda görüldüğü
biçimde bir mesaj yayınlanır:
Kayıt silemezsiniz..
SQLCODE
fonksiyonları kullanılabilir. Bu koda ilişkin hata mesajını elde etmek gerektiğinde ise,
SQLERRM
Örnek 1
Bu örnekte SELECT deyimi birden fazla satır seçtiği için bir kural dışı durum ortaya
çıkmıştır. Bunun için, önceki örnekte olduğu gibi TOO_MANY_ROWS hazır kural dışı durum
ifadesini kullanabiliriz. Bunun yerine, WHEN OTHERS ifadesini kullanarak ORACLE veri
tabanı sunucusunun kendi hata mesaj kodunu ve bu mesaj ifadesini elde etmek istiyoruz.
255
Bu amaç ile yazılan PL/SQL bloğunu görmek için linke tıklayınız.
DECLARE
v_adi personel.adi%TYPE;
BEGIN
-- tablodan veriler okunuyor..
SELECT adi
INTO v_adi
FROM personel;
-- personel adı görüntüleniyor..
DBMS_OUTPUT.PUT_LINE (v_adi);
EXCEPTION
-- kural dışı durum ortaya çıktığında
-- hata kodu ve hata mesajı görüntülenecektir..
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE (SQLCODE);
DBMS_OUTPUT.PUT_LINE (SQLERRM);
END;
Bu program çalıştırıldığında, ortaya çıkan hatalı duruma uyan ORACLE veri tabanı sunucu
hata kodu ve hata ifadesi görüntülenir.
-1422
ORA-01422: <hata mesajı...
Örnek 2
personel tablosundan 999 numaralı personelin adını okumak istiyoruz. Ancak söz konusu
tabloda böyle bir numaraya sahip personel bulunmamaktadır. Bu kural dışı durum ile ilgili
olarak ORACLE sunucusunun ürettiği hata kodunu ve mesajını öğrenmek istiyoruz.
DECLARE
v_adi personel.adi%TYPE;
BEGIN
-- tablodan veriler okunuyor..
SELECT adi
INTO v_adi
FROM personel
WHERE personel_no=999;
-- personel adı görüntüleniyor..
DBMS_OUTPUT.PUT_LINE (v_adi);
EXCEPTION
-- kural dışı durum ortaya çıktığında
-- hata kodu ve hata mesajı görüntülenecektir..
WHEN OTHERS THEN
256
DBMS_OUTPUT.PUT_LINE (SQLCODE);
DBMS_OUTPUT.PUT_LINE (SQLERRM);
END;
Bu program çalıştırıldığında, ortaya çıkan hatalı duruma uyan ORACLE veri tabanı sunucu
hata kodu ve hata ifadesi görüntülenir.
100
ORA-01403: hiç bir veri bulunmadı
Örnek 1
personel tablosunda 999 numaralı personelin ücret bilgisini 8900 olarak değiştirmek
istiyoruz. Bu işlemin yapılabilmesi için doğal olarak ilgili personelin personel tablosunda
kayıtlı olması beklenir. Eğer ilgili personel bulunamaz ise bir uyarı mesajı
görüntülenecektir. Bu tür kural dışı durumu denetlemek için NO_DATA_FOUND hazır
tanımları kullanılabilir. Ancak biz bu yola başvurmadan kendi kodlarımıza bu durumu
ortaya koymak istiyoruz.
DECLARE
-- Kural dışı durum adı tanımlanıyor..
h_gecersiz EXCEPTION;
BEGIN
-- veri tabanı tablosu güncelleştiriliyor..
UPDATE personel
257
SET ucret= 8900
WHERE personel_no=999;
-- SQL in kayıt bulunamadı mesajı üretilmiş ise
-- kural dışı durumu ortaya çıkarılıyor..
IF SQL%NOTFOUND THEN
RAISE h_gecersiz;
END IF;
COMMIT;
EXCEPTION
WHEN h_gecersiz THEN
DBMS_OUTPUT.PUT_LINE ('Geçersiz personel no..');
END;
Örnek 2
PL/SQL bloğu içinde iki sayısal değeri topladıktan sonra, sonuç negatif ise bunu bir kural
dışı durum olarak kabul edip, sonucu bir mesaj ile duyuralım istiyoruz.
DECLARE
sayi_1 NUMBER :=5;
sayi_2 NUMBER :=-7;
sonuc NUMBER;
-- Kural dışı durum adı tanımlanıyor..
hata EXCEPTION;
BEGIN
sonuc := sayi_1 + sayi_2;
-- kural dışı durumu ortaya çıkarılıyor..
IF sonuc < 0 THEN
RAISE hata;
END IF;
EXCEPTION
WHEN hata THEN
DBMS_OUTPUT.PUT_LINE ('Sonuç negatif..');
END;
Sonuç negatif..
258
259
260
261
ALTPROGRAMLAR
Bu bölümde;
• Altprogram
• PL/SQL Modüllerinin Ortak Yapıları
• Yordamlar
• Fonksiyonlar
• Paketler
anlatılmaktadır.
Bölüm Hedefi
Bu bölümde aşağıda sıralanan konular ele alınarak
incelenecektir:
• Paketlerin Yaratılması
PL/SQL programları da modüler kodlamaya uygundur. PL/SQL blokları aslında birer modül
olarak değerlendirilir. Daha önceki konularda ele alarak incelediğimiz anonim bloklar birer
modül olarak söz önüne alınır. Modüllere “altprogram” adı da verilebilir. PL/SQL
altprogramlarını şu şekilde sıralamız mümkündür:
• Anonim bloklar
• Yordamlar (procedures)
• Fonksiyonlar
• Paketler (packages)
262
Önceki bölümlerde anonim blokları ele alarak incelemiştik. Bu tür blokların aşağıda
sıralanan özelliklere sahip olduğunu biliyoruz:
a. Başlık: Sadece bir isime sahip olan modüllerde bu kısım kullanılır. Başlık kısmında
aşağıda sıralanan öğreler yer alır:
o Modül adı
o Parametre listesi
o RETURN deyimi. Bu deyim sadece fonsiyonlarda vardır.
b. DECLARE bölümü aşağıda sıralanan öğrelere sahip olabilir:
263
o Değişken tanımları
o İmleç tanımları
o Alt bloklar
c. BEGIN bölümünde aşağıda yer alan işlemlere başvurulabilir:
o Atama işlemleri
o IF-THEN-ELSE karar işlemleri
o Döngü işlemleri
o Diğer PL/SQL bloklarını çağırma işlemleri
d. EXCEPTION bölümünde ise aşağıda sıralanan işlemler yerine getirilir:
o Kural dışı durumları yakalama işlemleri
10.3 Yordamlar
PL/SQL programlarında yer alabilecek bir değer modül türü yordam (procedure) olarak
bilinmektedir. Yordam, bir veya daha fazla eylemi yerine getirmek üzere oluşturulan
yapılardır. Çağrıldığında herhangi bir değer döndürmez, sadece verilen görevi yerine
getirir. Bu yönü göz önüne alındığında fonksiyonlardan farklı olduğunu söyleyebiliriz.
Yordam, aslında bir PL/SQL bloğudur. Belirli bir yapısı vardır. PL/SQL yordamları
oluşturulma ve kullanma açısından iki farklı türü bulunmaktadır. Bunlar yanda
verilmektedir.
264
10.3.1 Anonim Blok İçinde Kullanılan Yordamlar
Anonim bloklar içinde bir veya daha fazla yordam yer alabilir. Bu yordamlar belirli bir
yapıya sahiptir. Bir yordam şu şekilde kullanılabilir:
Görüldüğü gibi, yordamın bir ismi olmalıdır. Bu isime dayanılarak, söz konusu yordam
PL/SQL bloklarının BEGIN bölümünde çağrılarak kullanılabilir. Yordamlar PL/SQL
bloklarının DECLARE bölümünde tanımlanır.
Örnek
Amacımıza uygun bir SELECT deyimini test isimli bir yordam içinde şu şekilde
tanımlıyoruz:
265
END test;
Parametre : p_no
Yukarıdaki yordamı çalıştırabilmek için, örneğin 101 numaralı personel ilişkin olarak
sorgulama yapabilmek için,
test(101);
biçiminde kullanmak gerekiyor. Diğer personeli de sorgulamak için benzer tanım yapılır.
Buraya kadar söylediklerimizi bir PL/SQL bloğu içinde aşağıda gösterildiği biçimde
birleştirerek sunuyoruz:
DECLARE
-- yordam tanımlanıyor...
PROCEDURE test (p_no NUMBER) IS
v_adi personel.adi%TYPE;
BEGIN
-- tablodan veriler okunuyor...
SELECT adi
INTO v_adi
FROM personel
WHERE personel_no=p_no;
-- personel adı görüntüleniyor..
DBMS_OUTPUT.PUT_LINE (v_adi);
END test;
BEGIN
-- yordam ardarda üç kez çalıştırılıyor..
test(101);
test(105);
test(120);
END;
BURAK
BEGUM
SELIN
266
Önceki kısımda ele aldığımız yordamların en önemli özelliği, bir anonim PL/SQL bloğunun
içinde yer almasıdır. Bu tür yordamları sadece o anonim blok tarafından kullanılabilir
çünkü anonim blok ve yordam aynı programın birer parçasıdır.
Herhangi bir PL/SQL bloğundan ya da bir diğer dış uygulamadan, örneğin bir ASP
programından ya da Visual Basic programından çağrılarak kullanılabilirler. O nedenle saklı
yordamlar uygulama geliştiriciler açısından önemli kavramlardır.
Örnek
Veri tabanında yer alan BOLUM isimli tabloya satır ekleme işlemlerini yerine getirmek
üzere bir yordam yaratmak istiyoruz. Bu yordamın adı bolum_ekle olacaktır.
267
Yukarıdaki yordam bu şekliyle çalıştırılırsa, veri tabanında bolum_ekle isimli bir yordam
yaratılır. Bu yordam artık diğer tüm uygulamalar tarafından bolum_ekle ismi kullanılarak
çalıştırılmaya hazırdır
Örnek
Şu anda BOLUM tablosunun aşağıda görüldüğü gibi 5 adet satıra sahip olduğunu
varsayalım.
Bu BOLUM tablosuna bir kayıt eklemek için aşağıdaki yordamın veri tabanında yaratıldığını
varsayalım.
BEGIN
-- yordam iki kez ardarda çalıştırılıyor..
bolum_ekle (60,'REKLAM','KADIKÖY');
bolum_ekle (70,'SATIŞ','İZMİR');
END;
268
Yukarıdaki PL/SQL bloğunu çalıştırdığımız takdirde, BOLUM tablosuna iki adet satır ilave
edilecektir. Tablonun içeriğini yeniden görüntüleyecek olursak, sözünü ettiğimiz iki
kayıdın eklendiği görülür.
Bir yordamın normal olarak bir değer döndürmediğini söylemiştik. Ancak, parametre
girişlerini yanı sıra parametre çıkışlarını da tanımlayarak bir değer döndürmesi
sağlanabilir. Bunun için yordam parametreleri ile birlikte IN ve OUT anahtar kelimeleri
kullanılabilir. Eğer bir parametre giriş parametresi olacak ise, yani çağrılan yordama bir
değer aktarılacak ise IN, çağrılan yordamdan bir değer okunacak ise parametrelerle
birlikte OUT kelimeleri kullanılır. Eğer bir parametre hem giriş, hem de çıkış amacıyla
kullanılacak ise, o parametre için IN OUT biçiminde bir tanım yapılır.
Örnek
İki sayısal değeri okuyan ve değerlendiren bir yordam yaratacağız. Bu yordamın adı test
olacaktır. Bu yordam bu iki değeri toplayacak, sonuç negatif ise “NEGATİF..” mesajını,
aksi takdirde “POZİTİF..” mesajını kendini çağıran bir anonim PL/SQL bloğuna
aktaracaktır. Sözü edilen blok, yordamdan aldığı mesajı görüntüleyecektir. Yordam şu
şekilde yaratılabilir:
269
v_sonuc := sayi_1 + sayi_2;
IF v_sonuc < 0 THEN
mesaj:= 'Negatif..';
ELSE
mesaj := 'Pozitif..';
END IF;
END test;
Bu yordam veri tabanında test ismiyle yer alacaktır. Söz konusu yordamı çağıran anonim
PL/SQL bloğunu ise şu şekilde oluşturuyoruz:
DECLARE
v_mesaj varchar2(30);
BEGIN
-- yordam çalıştırılıyor..
test(5,-7,v_mesaj);
DBMS_OUTPUT.PUT_LINE (v_mesaj);
END;
Negatif..
10.4 Fonksiyonlar
Bir diğer PL/SQL modül türü fonksiyon olarak bilinir. Fonksiyonlar aynen yordamlara
benzer. Farkı, fonksiyonların bir değer döndürmek zorunda oluşudur. Fonksiyonları iki
faklı biçimde kullanma olanağımız vardır.
270
[EXCEPTION
deyimler;
END fonksiyon adı;
Fonksiyonların yordamlardan en önemli farkı, bir değer döndürmesidir. Tanım içinde yer
alan RETURN deyimi değer döndürmek amacıyla kullanılır.
Örnek
9000, 1000 ve 5000 ücret miktarlarının, personel tablosunda yer alan en yüksek ücretten
daha büyük olup olmadığını belirlemek istiyoruz. Eğer bu değer ücretten büyük ise,
personel tablosundaki en yüksek ücret seviyesi görüntülenecektir. Aksi takdirde verilen
değer görüntülenecektir. Personel arasında en yüksek ücret miktarının 7000 olduğunu
varsayıyoruz.
DECLARE
-- fonksiyon tanımlanıyor...
FUNCTION f_test (v_ucret IN NUMBER)
RETURN NUMBER IS
v_max_ucret NUMBER;
BEGIN
SELECT MAX(ucret)
INTO v_max_ucret
FROM personel;
IF v_ucret>v_max_ucret THEN
RETURN(v_max_ucret);
ELSE
RETURN(v_ucret);
END IF;
END f_test;
BEGIN
271
-- fonksiyon ardarda üç kez çalıştırılıyor..
DBMS_OUTPUT.PUT_LINE (f_test(9000));
DBMS_OUTPUT.PUT_LINE (f_test(1000));
DBMS_OUTPUT.PUT_LINE (f_test(5000));
END;
7000
1000
5000
Herhangi bir PL/SQL bloğundan yada bir diğer dış uygulamadan, örneğin bir ASP
programından yada yada VisualBasic programından çağrılarak kullanılabilirler.
272
RETURN veri türü
IS
BEGIN
deyimler;
END fonksiyon adı;
Örnek
Önceki örneği yeniden göz önüne alalım. Bu örnekte şu amaca ulaşılıyordu: 9000, 1000
ve 5000 ücret miktarlarının, personel tablosunda yer alan en yüksek ücretten daha
büyük olup olmadığını belirlemek istiyoruz. Eğer bu değer ücretten büyük ise, personel
tablosundaki en yüksek ücret seviyesi görüntülenecektir. Aynı amaca bu kez saklı
fonksiyonları kullanarak ulaşmak istiyoruz. Bunun için aşağıda belirtilen blok hazırlanır ve
çalıştırılır.
Yukarıdaki yordam bu şekliyle çalıştırılırsa, veri tabanında f_test isimli bir fonksiyon
yaratılır. Bu fonksiyon artık diğer tüm uygulamalar tarafından f_test ismi kullanılarak
çalıştırılmaya hazırdır.
Örnek
273
Bu amaç ile yazılan PL/SQL bloğunu görmek için linke tıklayınız.
BEGIN
-- fonksiyon ardarda üç kez çalıştırılıyor..
DBMS_OUTPUT.PUT_LINE (f_test(9000));
DBMS_OUTPUT.PUT_LINE (f_test(1000));
DBMS_OUTPUT.PUT_LINE (f_test(5000));
END;
7000
1000
5000
10.5 Paketler
Bir diğer PL/SQL modülü paket (package) olarak bilinir. Paketler veri tabanı nesneleri
olarak kabul edilir. Diğer veri tabanı nesnelerini mantıksal olarak bir grup halinde içereren
bir nesnedir. O halde bir paket, amacına uygun olarak birden fazla yordam ve fonksiyonu
içeren bir nesnedir. Bir paket belirli bir isim ile veri tabanı içinde saklanabilir. Bu sayede
aynı paketi çok sayıda uygulama aynen kullanabilecektir.
Paketler, iki parça halinde düşünülür. Bunlardan birincisi, paketin içerdiği modüllerin adını
ve parametrelerini içeren başlık kısmıdır. İkincisi ise, paketin içerdiği yordam ve
fonksiyonların ayrıntılı kodlarını, yani BEGIN ile başlayan ana kodlarını içeren kısmıdır. Bu
yöntem, güvenlik açısısından uygulamalara bazı avantajlar sağlar. Uygulama programları
sadece paketin başlık kısmıyla ilgilenir. Diğer kısımlarına uygulama programları ulaşamaz.
Sadece çalışarak görevlerini yerine getirmeleri sağlanabilir.
274
10.5.1 Paketlerin Yaratılması
Bir paketin yaratılması için belirli işlemlerin yapılması gerekmektedir. Bir paketi yaratmak
için iki deyim kullanılır:
Birinci ifade paketlerin başlık kısmını yaratmak amacıyla kullanılır. İkinci deyim ise
paketin ana kısmını yaratmak üzere kullanılır. Aşağıdaki deyim, paketin başlık kısmını
yaratır:
Örnek
Bir paket oluşturacağız. Bu paket bir yordam ve bir fonksiyondan oluşacaktır. Yordam,
bolum tablosuna yeni bölümler eklemeyi sağlar. Fonksiyon ise bolum tablosunda kaç
bölümün kaydedildiğini görüntüler.
! Amacımıza uygun p_test isimli paketin başlık ve paketin ana kısımlarını oluşturmak için
paket düğmesine tıklayınız.
275
Amacımıza uygun p_test isimli paketin başlık kısımları şu şekilde yaratılabilir:
Paket bu şekilde oluşturulduktan sonra çalıştırılırsa, bir veri tabanı nesnesi olarak veri
tabanı içine kaydedildiği görülür. Bu işlemin ardından paketin ana kısımları oluşturulur:
Paket bu şekilde oluşturulduktan sonra çalıştırılırsa, paketin ana kısmı da veri tabanı
üzerinde yaratılmış olur.
276
paket adı.modül adı(parametreler);
Örnek
Bir anonim blok içinde yer alan p_test yordamı f_test fonksiyonu aşağıda gösterildiği
biçimde çalıştırılabilir:
BEGIN
/* p_test isimli yordam içindeki p_ekle yordamı
ve f_test fonksiyonu çalıştırılıyor..
f_test fonksiyonu, 10 numaralı bölümdeki
personel sayısını verecektir.. */
p_test.bolum_ekle (60,'REKLAM','KADIKÖY');
DBMS_OUTPUT.PUT_LINE (p_test.f_test(10));
END;
277
278
279
280
DERS SONU
İleri Veri Tabanı Sistemleri dersinin sonuna gelmiş bulunmaktayız. Bu
çalışmamızın tüm öğrencilerimize faydalı olması dileğiyle...
281