PL/SQL Collections

Herkese Selam,

Bugün, Oracle üzerinde geliştirme yaparken sıkça başvurduğumuz collectionlardan bahsedeceğim.

COLLECTIONS 

Collection’lar her programlama dilinde olduğu gibi PL/SQL’de de var olan temel yapılardan biridir. Collection’lar içerlerinde aynı tip bir yada birden çok data bulundururlar. Genel olarak kullandığımız programlama dillerinden bildiğimiz “array” kavramı, kısmi olarak collection kavramını karşılamakadır. PL/SQL ‘de üç tip collectiondan söz edebiliriz. Bunları başlık olarak aşağıda belirtirsek .

1- Associative Array

2- Nested Table

3- Varray

Şimdi bu 3 ayrı collection yapısını ayrı ayrı inceleyelim.

1)Associative Array:  Associative Array’ler PL/SQL ‘de dinamik array yapılarıdır. Programlama dillerinden hatırladığımız üzere arraylerin başlangıçta initiliaze edilme ve eleman sayısının belirlenme durumu söz konusudur. Associative array’lerde böyle zorunluluklar söz konusu değildir. Array’i doğrudan içine tutacağı eleman sayısını belirlemeden ve initiliaze etmeden  yaratıp istediğimiz indisine eleman ekleyebilme olanağına sahibiz. Bunun yanı sıra klasik array mantığımızda var olan indis’in yalnızca sayısal değer olabilme kısıtı Associative Array yapısında yoktur. Bu durumu açıcak olursak, array’in içerisinde hareket etmemizi sağlan indis varchar2, binary integer veya integer olabilmekte. İndis tipini “index by” söz deyimi ile tanımlayabilmekteyiz.  Aşağıdaki örnekleri inceleyerek Associative Array’lerin  farklı kullanımınlarını görebiliriz.

PL/SQL’de collection yaratabilmemiz için öncelikle “TYPE” söz deyimi ile bir tip tanımlayı daha sonra bu tip üzerinden bir değişken tanımlamamız gerekmektedir.

Yaratmak istediğimiz tipin array olacağını ise “is table of”  söz deyimi ile gerçekleştirmekteyiz.

DECLARE
TYPE myassociativearray IS TABLE OF NUMBER
INDEX BY PLS_INTEGER;

myarray myassociativearray;
BEGIN
myarray (150) := 25;
DBMS_OUTPUT.put_line (myarray(150));
END;

Yukarıdaki örnektede gördüğünüz üzere tanımladığım associative array’de herhangi bir eleman sınırlaması belirtmedim ve kullanmadan önce herhangi bir initiliaze işlemine tabi tutmadım. Şimdide varchar2 tipinde indexlenebilen associative array tipini görelim.

//Ülke Telefon Kodlarını Ülke adlarına göre saklayalım.

DECLARE
TYPE myassociativearray IS TABLE OF NUMBER
INDEX BY VARCHAR2 (30);

myarray myassociativearray;
BEGIN
myarray (‘turkiye’) := 90;
myarray (‘almanya’) := 49;
myarray (‘amerika’) := 1;
myarray (‘hollanda’) := 31;
END;

Evet yukarıda gördüğümüz gibi indis tipini varchar2 tipinde oluşturabildik. Bu tarz kullanım bize tek bir indiste birden fazla bilgi tutabilmemizi sağlayan fonksyonel bir yapı. Peki içlerini doldurduğumuz arrayleri nasıl bir döngü içerisinde okuyacağımız sorusu yada array içindeki elemanları nasıl sileceğimiz sorusu gibi sorular akıllara gelebilir. Bu soruları tüm array tiplerini inceledikten sonra yazının en sonunda collectionlara ait fonksyonları ifade ederken anlatacağım.

2) Nested Table: Bu array tipindede associative array tipinde olduğu gibi eleman sınırlaması yoktur. Array tanımlarken bir eleman sayısı vermek durumda değiliz. İhtiyacımız oldukça dizimizi extend edip içine eleman yazabilmekteyiz. Ancak bu array tipinin associative göre dez avantajı kullanabilmek için initialize edilme gereğinin olmasıdır. Şimdi nested table tipindeki collectionın nasıl kullanıldığına bakabiliriz.

DECLARE
TYPE mynestedtablearray IS TABLE OF NUMBER;

myarray mynestedtablearray;
BEGIN
myarray := mynestedtablearray (); — Initiliazing
myarray.EXTEND; — 1 elemanlik yer acildi.
myarray (1) := 5;
myarray.EXTEND; — 1 elemanlik yer acildi.
myarray (2) := 15;
myarray.EXTEND (3); — 3 elemanlik yer acildi.
myarray (3) := 25;
myarray (4) := 35;
myarray (5) := 45;
END;

 Eğer yeni eleman yazmak için yeterli yer yoksa ise ve diziyi extend etmemiş isek         yazdığımız kod “ORA-06533: Subscript beyond count ” hatası alacaktır.

3)Varray: Bu collection tipi hem intiliaze edilmek durumunda, hemde başlangıçta eleman sınırı verilmek durumundadır. Kullanım şekli klasik programlamadan bildiğimiz yöntemlere çok benzemektedir. Ancak kullanımı nested table ve associative array’e göre daha zor ve zahmetlidir. Extend edilme ihtiyacı nested tableda olduğu gibi bundada vardır.

DECLARE
TYPE myvarray IS VARRAY (3) OF NUMBER;

arrayvar myvarray;
BEGIN
arrayvar := myvarray (); — initiliazing
arrayvar.EXTEND (3); — 3 elemanlik yer acildi
arrayvar (1) := 1;
arrayvar (2) := 2;
arrayvar (3) := 3;
END;

 COLLECTIONLARA AİT METODLAR

Bu bölümde collectionlar üzerinde tanımlanmış metodları ve tanımladığımız collectionların elemanları üzerinde nasıl dolaşabileceğimizi, listeleyebileceğimi göstereceğim.

PL/SQL’de collectionları üzerine tanımlanmış metod lar collectionlar üzerinde hareket etmememizi, dizi üzerinde veri silmemizi ve çeşitli işlemler yapabilmemize olacak sağlamaktadırlar. Şimdi bu metodları inceleyelim.

1)COUNT: Tanımladığımız collectiondaki eleman sayısını döndürmektedir. Çok kullanışlı bir metoddur, bu metod sayesinde collectionımızın size’ını hızılca öğrenip buna göre döngü kurup dizimizi listeleyebiliriz veya üzerinde sırayla işlem yapabiliriz. Count geriye integer bir değer döndürmektedir ve varray tipindeki dizilerde her zaman last metodunun döndürdüğü değere eşit olmaktadır. Eleman silinmemiş bir nested tabledada bu 2 fonksyonun geriye döndürdüğü değerler eşit çıkacaktır. Anacak nested table’ın ortalarından bir eleman silindiğinde count, last’ın döndürdüğü değerden daha küçük olacaktır.

DECLARE
TYPE myassociativearray IS TABLE OF NUMBER
INDEX BY PLS_INTEGER;

myarray myassociativearray;
BEGIN
myarray (1) := 25;
myarray (2) := 35;
myarray (3) := 45;
myarray (4) := 55;
myarray (5) := 65;
DBMS_OUTPUT.put_line (myarray.COUNT);

FOR i IN 1 .. myarray.COUNT
LOOP
DBMS_OUTPUT.put_line (myarray (i));
END LOOP;
END;

Yukarıdaki örnekte Count metodunu kullanarak dizi üzerinde nasıl hareket edilebileceğinide görmüş olduk. 

2)DELETE: Delete metodu ile diziden eleman silme işlemini gerçekleştirebilmekteyiz. Birden fazla kullanım şekli mevcuttur. Bunları sırayla örnekleyecek olursak.

DECLARE
TYPE myassociativearray IS TABLE OF NUMBER
INDEX BY PLS_INTEGER;

myarray myassociativearray;
BEGIN
myarray (1) := 25;
myarray (2) := 35;
myarray (3) := 45;
myarray (4) := 55;
myarray (5) := 65;

myarray.delete; –Arrayin tamamini siler.
myarray.delete(3); — 3. elemani sile
myarray.DELETE (2, 4); — 2. 3. ve 4. elemanlar arasini siler;

END;

2)EXISTS: Exist sonucunda true yada false değeri dönmektedir. Exist içine verilen paramtere değeri ile belirlenen indis değerinin dizide olup olmadığı bilgisi dönmektedir. Eğer oindise sahip bir eleman varsa true yoksa false değeri dönmektedir.

DECLARE
TYPE myassociativearray IS TABLE OF NUMBER
INDEX BY PLS_INTEGER;

myarray myassociativearray;
BEGIN
myarray (1) := 25;
myarray (2) := 35;
myarray (3) := 45;
myarray (4) := 55;
myarray (5) := 65;

IF myarray.exists(5)
THEN
DBMS_OUTPUT.put_line (‘Bu eleman mevcut’);
END IF;
END;

3)EXTEND: Nested table ve varray collection tiplerinde de gördüğümüz gibi array yeni bir eleman yerleştirmek için yer açmaya olanak sağlayan metoddur. Bu metodla bir elemanlık yer açılabileceği gibi birden fazla elemanlık yerde açılabilmektedir. Associative arraylerde kullanılmazlar.

4)FIRST ve LAST: First ve Last metodları collection içindeki ilk ve son indis değerlerini geriye döndürmektedir. Bu dönen değerler integer değerlerdir. Ancak associative arraylerde varchar2 tipinde indis yapma mekanizması olduğundan bu tip arraylerde geriye dönen değer string’de olabilmektedir. Eğer collection boşsa first ve last null olarak geriye dönecektir. Eğer collection’da tek elemean varsa first ve last aynı değeri döndürecektir. Varray tipi collectionlarda first her zaman 1 i, Last ise her zaman count’un döndürdüğü sonucu döndürmektedir.

DECLARE
TYPE mynestedtablearray IS TABLE OF NUMBER;

myarray mynestedtablearray;
BEGIN
myarray := mynestedtablearray (); — Initiliazing
myarray.EXTEND; — 1 elemanlik yer acildi.
myarray (1) := 5;
myarray.EXTEND; — 1 elemanlik yer acildi.
myarray (2) := 15;
myarray.EXTEND (3); — 3 elemanlik yer acildi.
myarray (3) := 25;
myarray (4) := 35;
myarray (5) := 45;

FOR i IN myarray.FIRST .. myarray.LAST
LOOP
DBMS_OUTPUT.put_line (myarray (i));
END LOOP;


END;

Yukarıdaki örnekte First ve Last metodu kullanarak dizi içinde hareket etme ve listeleme işlemi yapılmıştır döngü kullanılarak. Ancak şu unutulmamalıdırki, dizinin ortalarından bir eleman silindiği takdirde o elemanı yazdırmaya sıra geldiğinde no data found hatası geriye dönmektedir.

5)LIMIT: Nested table tipi collectionlarda üst sınır olmadığından dolayı geriye null dönemektedir. Bu fonksyon eleman almada üst sınırı olan varray tipindeki collectionlar için geçerlidir. Varray tipi collectionlarda geriye döndürdüğü değer collectionın alabileceği eleman sayısıdır. Aşağıdaki örnekten bu durumu inceleyebilirsiniz.

DECLARE

TYPE myvarray IS VARRAY (13) OF NUMBER;

arrayvar myvarray;
BEGIN
arrayvar := myvarray (); — initiliazing
arrayvar.extend(13);
arrayvar (1) := 1;
arrayvar (2) := 2;
arrayvar (3) := 3;

DBMS_OUTPUT.put_line (arrayvar.limit); — dönen değer 13
END;

6)NEXT ve PRIOR: Next verilen indisten sonra gelen bir sonraki elemanın indisini döndürür. Prior ise parametre olarak verilen indisten bir önce bulunan elemanın indisini verir. Eğer eleman ilk elemanda yada öncesinde eleman yoksa geriye dönen değer null’dır. Aynı şekilde next ile verilen indisten sonra eleman yoksa sonuç yine null’dır.

DECLARE
TYPE myvarray IS VARRAY (13) OF NUMBER;

arrayvar myvarray;
BEGIN
arrayvar := myvarray (); — initiliazing
arrayvar.EXTEND (5);
arrayvar (1) := 21;
arrayvar (2) := 22;
arrayvar (3) := 23;
DBMS_OUTPUT.put_line (arrayvar.NEXT (2)); — donen deger 3
DBMS_OUTPUT.put_line (arrayvar.PRIOR (2)); — donen deger 1
END;

7)TRIM: İçine verilen değere göre collection’ın sonundan okadar eleman siler. Eğer verilen değer collectionın count değerinden büyükse geriye SUBSCRIPT_BEYOND_COUNT hatası alınır.

 

Advertisements

About ... from Emrah METE

Bilgisayar Mühendisi
This entry was posted in Oracle, Root, Uncategorized and tagged , , , , , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s