Collection koleksiyon veya bir topluluk olarak çevrilebilir. Collection’lar içerlerinde aynı tip bir yada birden çok data bulundururlar. PL/SQL ‘de üç tip collectiondan söz edebiliriz.
- Index-by tables or Associative array
- Nested Table
- Variable-size array or Varray
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 string veya integer olabilmekte. İndis tipini “index by” söz deyimi ile tanımlayabilmekteyiz
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 salary IS TABLE OF NUMBER INDEX BY VARCHAR2(20); salary_list salary; name VARCHAR2(20); BEGIN -- adding elements to the table salary_list('Rajnish') := 62000; salary_list('Minakshi') := 75000; salary_list('Martin') := 100000; salary_list('James') := 78000; -- printing the table name := salary_list.FIRST; WHILE name IS NOT null LOOP dbms_output.put_line ('Salary of ' || name || ' is ' || TO_CHAR(salary_list(name))); name := salary_list.NEXT(name); END LOOP; END; /
DECLARE CURSOR c_customers is select name from customers; TYPE c_list IS TABLE of customers.name%type INDEX BY binary_integer; name_list c_list; counter integer :=0; BEGIN FOR n IN c_customers LOOP counter := counter +1; name_list(counter) := n.name; dbms_output.put_line('Customer('||counter|| '):'||name_list(counter)); END LOOP; END; /
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.
DECLARE TYPE names_table IS TABLE OF VARCHAR2(10); TYPE grades IS TABLE OF INTEGER; names names_table; marks grades; total integer; BEGIN names := names_table('Kavita', 'Pritam', 'Ayan', 'Rishav', 'Aziz'); marks:= grades(98, 97, 78, 87, 92); total := names.count; dbms_output.put_line('Total '|| total || ' Students'); FOR i IN 1 .. total LOOP dbms_output.put_line('Student:'||names(i)||', Marks:' || marks(i)); end loop; END; /
DECLARE CURSOR c_customers is SELECT name FROM customers; TYPE c_list IS TABLE of customers.name%type; name_list c_list := c_list(); counter integer :=0; BEGIN FOR n IN c_customers LOOP counter := counter +1; name_list.extend; name_list(counter) := n.name; dbms_output.put_line('Customer('||counter||'):'||name_list(counter)); END LOOP; END; /
Array
Array(dizi) konusunu linkteki yazıda bahsetmiştik.
Collectiona Ait 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.
Method İsmi | Açıklama |
EXISTS(n) | 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. |
COUNT | Tanımladığımız collectiondaki eleman sayısını döndürmektedir. 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. |
LIMIT | Nested table tipi collectionlarda üst sınır olmadığından dolayı geriye null dönemektedir. Bu fonksiyon eleman almada üst sınırı olan varray tipindeki collectionlar için geçerlidir. |
FIRST | First collection içindeki ilk indis değerlerini geriye döndürmektedir. Bu dönen değer 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 null olarak geriye dönecektir. |
LAST | Last collection içindeki son indis değerlerini geriye döndürmektedir. Bu dönen değer 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 last null olarak geriye dönecektir. Eğer collection’da tek elemean varsa first ve last aynı değeri döndürecektir. |
PRIOR(n) | Prior 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. |
NEXT(n) | Next verilen indisten(n) sonra gelen bir sonraki elemanın indisini döndürür. |
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çılacaktır. |
EXTEND(n) | 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 bellirttigimiz n sayısı kadar elemanlık yer açılacaktır. |
EXTEND(n,i) | Bu metodla i’den n sayısı kadar ekler. |
TRIM | Collection’ın sonundan 1 eleman siler. |
TRIM(n) | İçine verilen değere göre collection’ın sonundan o kadar eleman siler. Eğer verilen değer collectionın count değerinden büyükse geriye SUBSCRIPT_BEYOND_COUNT hatası alınır. |
DELETE | Delete metodu ile diziden eleman silme işlemini gerçekleştirebilmekteyiz. Bu metodla tüm ögeleri sileriz. |
DELETE(n) | n sırasındaki indisi siler. |
DELETE(m,n) | m ve n de dahil olmak üzere aradaki bütün indislere karşılık gelen elemanları siler. |
Collection Exceptions(Hataları)
Sistem tarafından tanımlı gelen hataların listesi aşağıdaki gibidir.
- COLLECTION_IS_NULL
- NO_DATA_FOUND
- SUBSCRIPT_BEYOND_COUNT
- SUBSCRIPT_OUTSIDE_LIMIT
- VALUE_ERROR
Örnek 1;
DECLARE TYPE NumList IS TABLE OF INTEGER; n NumList := NumList(1,3,5,7); BEGIN n.DELETE(2); -- Delete the second element IF n.EXISTS(1) THEN DBMS_OUTPUT.PUT_LINE('OK, element #1 exists.'); END IF; IF n.EXISTS(2) = FALSE THEN DBMS_OUTPUT.PUT_LINE('OK, element #2 has been deleted.'); END IF; IF n.EXISTS(99) = FALSE THEN DBMS_OUTPUT.PUT_LINE('OK, element #99 does not exist at all.'); END IF; END; /
Örnek 2;
DECLARE TYPE NumList IS TABLE OF NUMBER; n NumList := NumList(2,4,6,8); -- Collection starts with 4 elements. BEGIN DBMS_OUTPUT.PUT_LINE('There are ' || n.COUNT || ' elements in N.'); n.EXTEND(3); -- Add 3 new elements at the end. DBMS_OUTPUT.PUT_LINE('Now there are ' || n.COUNT || ' elements in N.'); n := NumList(86,99); -- Assign a completely new value with 2 elements. DBMS_OUTPUT.PUT_LINE('Now there are ' || n.COUNT || ' elements in N.'); n.TRIM(2); -- Remove the last 2 elements, leaving none. DBMS_OUTPUT.PUT_LINE('Now there are ' || n.COUNT || ' elements in N.'); END; /
Örnek 3;
DECLARE TYPE dnames_var IS VARRAY(7) OF VARCHAR2(30); dept_names dnames_var := dnames_var('Shipping','Sales','Finance','Payroll'); BEGIN DBMS_OUTPUT.PUT_LINE('dept_names has ' || dept_names.COUNT || ' elements now'); DBMS_OUTPUT.PUT_LINE('dept_names''s type can hold a maximum of ' || dept_names.LIMIT || ' elements'); DBMS_OUTPUT.PUT_LINE('The maximum number you can use with ' || 'dept_names.EXTEND() is ' || (dept_names.LIMIT - dept_names.COUNT)); END; /
Örnek 4;
DECLARE TYPE NumList IS TABLE OF NUMBER; n NumList := NumList(1966,1971,1984,1989,1999); BEGIN DBMS_OUTPUT.PUT_LINE('The element after #2 is #' || n.NEXT(2)); DBMS_OUTPUT.PUT_LINE('The element before #2 is #' || n.PRIOR(2)); n.DELETE(3); -- Delete an element to show how NEXT can handle gaps. DBMS_OUTPUT.PUT_LINE('Now the element after #2 is #' || n.NEXT(2)); IF n.PRIOR(n.FIRST) IS NULL THEN DBMS_OUTPUT.PUT_LINE('Can''t get PRIOR of the first element or NEXT of the last.'); END IF; END; /
Örnek 5;
DECLARE TYPE NumList IS TABLE OF NUMBER; n NumList := NumList(2,4,6,8); -- Collection starts with 4 elements. BEGIN DBMS_OUTPUT.PUT_LINE('There are ' || n.COUNT || ' elements in N.'); n.EXTEND(3); -- Add 3 new elements at the end. DBMS_OUTPUT.PUT_LINE('Now there are ' || n.COUNT || ' elements in N.'); n := NumList(86,99); -- Assign a completely new value with 2 elements. DBMS_OUTPUT.PUT_LINE('Now there are ' || n.COUNT || ' elements in N.'); n.TRIM(2); -- Remove the last 2 elements, leaving none. DBMS_OUTPUT.PUT_LINE('Now there are ' || n.COUNT || ' elements in N.'); END; /
Yararlı olması Dilegiyle …
Yazar : Mustafa Bektaş Tepe
Kaynaklar;
http://www.tutorialspoint.com/plsql/plsql_basic_syntax.htm
https://emrahmete.wordpress.com
https://developersdaily.wordpress.com
http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/
https://docs.oracle.com/cd/E11882_01/appdev.112/e40758/toc.htm
https://oracle-base.com/articles/misc/introduction-to-plsql