PL/SQL COMPOSITE DATA TYPES

Scalar Tiplerin aksine birden fazla veri tutabilirler. İki türü vardır

  • PL/SQL Records
  • PL/SQL Collections
    • Associative array (INDEX BY table)
    • Nested table
    • VARRAY

PL/Sql Record : Bu veri tipi birbirleri arasında ilişki bulunan ancak tipleri benzemeyen verileri için kullanılır. Örneğin ‘bir personelin‘ adını soyadını ve kimlik numarasını tutan bir record yazabiliriz. Record ile tüm bilgileri tek bir değişkende tutabiliriz.

PL/Sql Collection : Koleksiyonlar ise aynı tip ancak birden çok verileri turmak için idealdir. ‘Tüm personellerin‘ isimlerini tutmak istiyorsak kullanabiliriz. (Programlama dillerindeki dizilere benzer.)

Şu şekilde açıklayabiliriz; Record lar bir satırdaki tüm bilgileri tutabilirken, Collection lar bir sütundaki tüm bilgileri tutabilir diyebiliriz.

PL /Sql RECORD

  • Herbir record birden çok farklı veri tipi için tanımlanabilir.
  • Reocrd lar başlangıç değerlerini tutabilir ve not null olarak tanımlanabilir.
  • Memory de tutulabilir, diske yazılmaya ihitiyaç duymazlar.
  • Record lar nested tanımlanabilir. Yani bir record diğer bir record un bileşeni olabilir
  • Record kullanabilmek için declare bölümünde bir record type tanımlanması gereklidir.
DECLARE TYPE calisan_inf IS RECORD
    (
        EMP_ID  NUMBER,
        FIRST_NAME   EMPLOYEES.FIRST_NAME%TYPE,
        LAST_NAME     EMPLOYEES.LAST_NAME%TYPE,
        EMAIL  EMPLOYEES.EMAIL%type,
        DEPT_ID DEPARTMENTS.DEPARTMENT_ID%type,
        HIRE_DATE   EMPLOYEES.HIRE_DATE%type
    );
    calisan_rec calisan_inf;
BEGIN
    SELECT 
        d.DEPARTMENT_ID,
        e.EMPLOYEE_ID,
        e.FIRST_NAME,
        e.LAST_NAME,
        e.EMAIL,
        e.HIRE_DATE
    INTO
        calisan_rec.DEPT_ID,
        calisan_rec.EMP_ID,
        calisan_rec.FIRST_NAME,
        calisan_rec.LAST_NAME,
        calisan_rec.EMAIL,
        calisan_rec.HIRE_DATE
    from employees e join departments d
        on(e.DEPARTMENT_ID = d.DEPARTMENT_ID)
        where employee_id=100;
        
    dbms_output.put_line('calışanın department id si : '||calisan_rec.DEPT_ID
                            ||' adı: '|| calisan_rec.FIRST_NAME
                            ||' soyadı : '||calisan_rec.LAST_NAME
                            ||' epostası : '||calisan_rec.EMAIL
                            ||' işe giriş tarihi '||calisan_rec.HIRE_DATE);
END;

Çıktı;
 
calışanın department id si : 90 adı: Steven soyadı : King epostası : SKING işe giriş tarihi 17-JUN-03

Eğer record birden çok tabloda değilde tek bir tablo üzerinde oluşturulacaksa %ROWTYPE kullanmak bizi record içeriğini tanımlamaktan ve ayrıca record içine veri atarken tek tek record fieldlerine yazmaktan kurtarır.

declare 
    calisan_inf     employees%rowtype;
begin
    select * 
    INTO    calisan_inf
    from employees
    where employee_id=100;
    
    dbms_output.put_line(   ' adı: '|| calisan_inf.FIRST_NAME
                            ||' soyadı : '||calisan_inf.LAST_NAME
                            ||' epostası : '||calisan_inf.EMAIL
                            ||' işe giriş tarihi '||calisan_inf.HIRE_DATE);
end;

ÇIKTI

adı: Steven soyadı : King epostası : SKING işe giriş tarihi 17-JUN-03

PL/SQL Collection

Associative Arrays (INDEX BY Tables)

Index by table koleksiyon tipini iki kolonu olan ve bu kolonlardan biri id değeri tutan ve primary key constraint içeren diğer kolon ise normal değer tutan kolona sahip bir tablo gibi düşünebiliriz. Birinci kolon index içeriğine sahiptir, ikinci kolon ise sclar yada record data tipine sahip olarak veriler tutabilir.

ORNEK:  Bir tablonun tek bir kolonundaki veriyi stoklayan index by table kullnımı.

declare 
    TYPE per_isimleri   IS 
    TABLE OF EMPLOYEES.FIRST_NAME%type INDEX BY PLS_INTEGER;
    
    per_name per_isimleri;
BEGIN
    for i in (select * from employees)
    LOOP
        dbms_output.put_line(i.employee_id);
        select first_name 
        INTO per_name(i.employee_id)
        from employees where employee_id=i.employee_id;
    end LOOP;
    
    FOR i in per_name.first .. per_name.last
    LOOP
        dbms_output.put_line(per_name(i));
    END LOOP;
END;

ORNEK 2 Tablonun tüm kolonlarının index by table kullanılarak alınması.

declare
    TYPE per_bilgileri is 
    TABLE OF employees%ROWTYPE
    INDEX by pls_integer;
    
    per_inf     per_bilgileri;
BEGIN
    for i in (select * from employees)
    LOOP
        select * INTO per_inf(i.employee_id)
        from employees where employee_id=i.employee_id;
    END LOOP;
    FOR i in per_inf.first .. per_inf.last
    loop
        dbms_output.put_line('adı : '|| per_inf(i).first_name||
                             ' soyadı : '||per_inf(i).last_name||
                             ' TEL Numarası : '||per_inf(i).phone_number);
    end loop;
END;

Index By Methotları

Method Açıklama
COUNT Dizinin eleman sayısını döndürür.
FIRST Dizinin en küçük index numarasını döndürür. Dizi Boş ise
null döndürür.
LAST Dizinin en büyük index numarasını döndürür. Dizi Boş ise
null döndürür
PRIOR(n) n index numarasından önceki index numarasını döndürür.
NEXT(n) n index numarasından sonraki index numarasnı döndürür.
DELETE DELETE tüm dizi elementlerini siler.
DELETE(n) n indexli elemanı siler.
DELETE(m,n) m .. n index aralığındaki elemnları siler.
EXISTS(n) Dizide n elemanı varsa TRUE döndürür

Nested Tables

Nested Table Index by Table a benzerdir. Nested table da data tipleri belli olmalıdır. Nested Table da key tipi pls_integer değildir ve negatif olamaz. Row lar düzenli bir sırada değildir, başlangıç noktası ilk değeridir. Nested table lar index by table aksine database de depolayabilirler.

Syntax

TYPE type_name IS TABLE OF
      {column_type | variable%TYPE
                   | table.column%TYPE} [NOT NULL]
                   | table.%ROWTYPE

ÖRNEK

declare 
    TYPE per_isimleri IS TABLE OF employees.first_name%type;
    per_names   per_isimleri;
BEGIN
    per_names:=per_isimleri('faruk','ahmet','mahmut','levent');
    for i in 1 .. per_names.COUNT
    LOOP
        dbms_output.put_line(per_names(i));
    end LOOP;
END;

ÇIKTI

faruk
ahmet
mahmut
levent

VARRAY

Varray tipi koleksiyonlar da nested table gibidir ancak varray için boyut tanımlamak gerekir. Ayrıca varray lerde nested table lar gibi en fazla 2 gb data tutabilir. Varray database de depolanabilirler.

ÖRNEK:

declare 
    TYPE per_isimleri IS VARRAY(4) OF employees.first_name%type;
    per_names   per_isimleri;
BEGIN
    per_names:=per_isimleri('faruk','ahmet','mahmut','levent');
    for i in 1 .. per_names.COUNT
    LOOP
        dbms_output.put_line(per_names(i));
    end LOOP;
END;

ÇIKTI

faruk
ahmet
mahmut
levent