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

Loading