Pl/sql composıte (karmaşık) veri tipleri

'Marksman

Kadim Üye
8 Ocak 2013
5,400
1
2
PL / Sql ile programlama yaparken veri kaynağı olarak tabloları kullanırız. Yaptığımız işler tablolardan verileri okuyup, bu verileri yorumlayarak yine tablolara veriler eklemek yada tabloları güncellemek olarak temel anlamda tanımlanabilir. Bu işlemleri yaparken diğer programlama dillerindeki gibi kontrol blokları , döngüler, hata denetim sistemleri vs. kullanılır. Ancak bazen diziler ile işlemler yaptığımızda yada değişken olarak kullanmak istediğimiz veri bir tek veri değilde bir kolon yada bir row olursa, ya bu verileri değişkenlere parçalamamız yada karmaşık veri tiplerini kullanmamız gerekir.Bu yazımızda advanced derecede veri tipleri pl/sql de nelerdir, nasıl kullanılır açıklamalar ve örnekler yazacağız.
PL / Sql karmaşık veri tiplerini iki gurupta incelemek mümkündür.
PL/Sql Record :Bu veri tipi birbirleri arasında ilişki bulunan ancak tipleri benzemeyen verileri için kullnılır.Mesela bir ürünün adını, fiyatını, seri numarasını tutan bir record yazabiliriz.Bu ürüne ait bilgileri değişkenlerde tutmak istesek 3 adet değişken tip tanımlamamız gerekir. Ürün adı için varchar2, fiyatı için number ve seri numarası içinde number olacak şekilde. Ancak record ile tüm bilgileri tek bir değişkende tutabiliriz.
PL/Sql Koleksiyon : Koleksiyonlar ise aynı tip ancak birden çok verileri turmak için idealdir. Mesela Tüm çalışanların isimlerini tek bir koleksiyon tutabiliriz.Koleksiyon tipleri,

· Nested table
· Index By Table
· Varray ' dir.
Yani aklımızda kalması açısından, recordlar bütün bir row bilgisini, koleksiyonlar ise bütün bir kolon bilgisini tutabilir.Ne kadar veri tutabilir sorusuna gelince kısıtlama vardır. Bu veri tiplerini teker teker inceleyip örneklendirirken kapasite konusunda bilgi vereceğiz.
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.
· Recordlar nested tanımlanabilir. Yani bir record diğer bir recordun bileşeni olabilir
Record kullanabilmek için declare bölümünde bir record type tanımlanması gereklidir.

PL SQL Record



TYPE : Sizin tanımladığınız recordun tipidir.
type_name : Type adı.
field_name : record içine tanımlanacak alanların adı.
field_type : record içine tanımlanacak alanların data tipi.
identifier : record adı.
Aşağıdaki örnek bir record nasıl tanımlanır ve kullanılır görebiliriz. Ancak dikkat edilmesi gereken , bir record en fazla bir row içerir, aksi takdirde "ORA-01422: tam okuma istenilenden daha fazla sayıda satır döndürür" hatasını alırsınız.
örnek 1 : Farklı tablolardan alınacak bazı değerler için record kullnımı.
DECLARE
TYPE emp_info
IS
RECORD (
DEPARTMENT_ID NUMBER,
EMPLOYEE_ID NUMBER,
FIRST_NAME VARCHAR2 (32),
LAST_NAME VARCHAR2 (32),
EMAIL VARCHAR2 (32),
HIRE_DATE DATE
);

emp_kayit emp_info;
BEGIN
SELECT d.department_id,
e.employee_id,
e.first_name,
e.last_name,
e.email,
e.hire_date
INTO emp_kayit.department_id,
emp_kayit.employee_id,
emp_kayit.first_name,
emp_kayit.last_name,
emp_kayit.email,
emp_kayit.hire_date
FROM hr.employees e, hr.departments d
WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID AND employee_id = 100;

DBMS_OUTPUT.put_line (
'our_emolyee department_id : ' || emp_kayit.department_id
);
DBMS_OUTPUT.put_line ('our_emolyee name : ' || emp_kayit.first_name);
DBMS_OUTPUT.put_line ('our_emolyee hire_date : ' || emp_kayit.hire_date);
END;
Örnekteki pl/sql bloğu bize aşağıdaki çıktıyı verecektir.
our_emolyee department_id : 90
our_emolyee name : Steven
our_emolyee hire_date : 17/06/2003

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 kurtartabilir.Aşağıdaki örnek rowtype kullanımını gösterir niteliktedir.

örnek 2: %rowtype kullanımı.
DECLARE
emp_kayit hr.employees%rowtype;
BEGIN
SELECT *
INTO emp_kayit
FROM hr.employees
WHERE employee_id = 100;

DBMS_OUTPUT.put_line ('our_emolyee name : ' || emp_kayit.first_name);
DBMS_OUTPUT.put_line ('our_emolyee last_name : ' || emp_kayit.last_name);
DBMS_OUTPUT.put_line ('our_emolyee hire_date: ' || emp_kayit.hire_date);
END;

Bu örneğin bize vereceği output ise aşağıdaki gibi olacaktır.
our_emolyee name : Steven
our_emolyee last_name : King
our_emolyee hire_date: 17/06/2003
Recordlar kullanılarak tüm dml işlemleri yapılabilir. "insert into emp values emp_kayit;" . değişkenlerle yapılan tüm işlemler recordlar ilede yapılabilir. Recordlar C++ daki structure yapısnı anlatırlar. PL/Sql koleksiyonlarda array lere benzerler.

PL/Sql KOLEKSIYON
Index by Table;
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. Aşağıdaki resim de index by table yapsını daha net görebilirsiniz.


Index By Table Yapısı

Index by table kullanırken exist, count, prior, next, delete parametrelerini kullanabiliriz, Aşağıda bu parametrelerin ve index by table kolleksiyon tipinin kullnımına yönelik örnekler bulabilirsiniz.
örnek 3 : bir tablonun tek bir kolonundaki bir kısım veriyi stoklayan index by table kullnımı .
DECLARE
TYPE emp_name
IS
TABLE OF hr.employees.first_name%TYPE
INDEX BY PLS_INTEGER;

ename emp_name;
BEGIN
FOR i IN 100 .. 200
LOOP
SELECT first_name
INTO ename (i)
FROM employees
WHERE employee_id = i;
END LOOP;

FOR i IN ename.FIRST .. ename.LAST
LOOP
DBMS_OUTPUT.put_line (ename (i));
END LOOP;
END;
örnek 3 e ait output aşağıdaki gibi olacaktır.
Steven
Neena
Lex
Alexander
Bruce
David
......
örnek 4 : tüm tablonun kolonlarının index by table ile alınması

DECLARE
TYPE emp_name
IS
TABLE OF hr.employees%ROWTYPE
INDEX BY PLS_INTEGER;

ename emp_name;
BEGIN
FOR i IN 100 .. 200
LOOP
SELECT *
INTO ename (i)
FROM employees
WHERE employee_id = i;
END LOOP;

FOR i IN ename.FIRST .. ename.LAST
LOOP
DBMS_OUTPUT.put_line (
'ad : ' || ename (i).first_name || ' soyad: ' || ename (i).last_name
);
END LOOP;
END;
örnek 4 e ait output aşağıdaki gibi olacaktır.
ad : Steven soyad: King
ad : Neena soyad: Kochhar
ad : Lex soyad: De Haan
ad : Alexander soyad: Hunold
ad : Bruce soyad: Ernst
......

Nested Table;
Nested table da index by table fonksiyonelitesine benzerdir. Ancak mantık olarak farklılıklar vardır.Nested by table da data tipi belirli olmalıdır, index by table da belirli data tipine gerek yoktur.Nested tableda 1.kolon key tipi index by table daki gibi pls_integer değildir ve negatifde olamaz.Nested table da rowlar düzenli bir sırada değildir.Başlangıç noktası ilk değeridir.Ayrıca nested table lar index by table aksine database de depolanabilir.Nested table kavramı için aşağıdaki şekile göz atabiliriz.


Nested Table Yapısı


TYPE emp_type IS TABLE OF hr.employees.first_name%TYPE;
ename emp_type;
Burada ename tipinin değerini eğer belirlemezseniz nested table da null olarak belirlenir. Index by tableda ise boş olarak belirlenir.
ename tipine ename := emp_type('scott','steve','king'); şeklinde değer atanabilir.
örnek 5 : nested table kullanımı;
DECLARE
TYPE emp_type IS TABLE OF hr.employees.first_name%TYPE;
ename emp_type;
BEGIN
ename := emp_type ('scott', 'steve', 'king');
FOR i IN 1 .. ename.COUNT
LOOP
DBMS_OUTPUT.put_line (ename (i));
END LOOP;
END;
örnek 5 bize aşağıdaki gibi bir output verecektir.
scott
steve
king
...
VARRAY :
Varray tipi koleksiyonlar da nested table gibidir ancak varray için size tanımlamak gerekir.Ayrıca varray lerde nested table lar gibi en fazla 2 gb data tutabilir.Varray lerde database de depolanabilir.
TYPE emp_name IS VARRAY(2) OF hr.employees.first_name%TYPE;
ename emp_name;
Varray leryukarıdaki gibi tanımlanabilir.Mesela bizim tanımladığımız emp_name varray sadece 2 adet veri saklayabilir.3. veriyi girdiğinizde "ORA-06532: İndis sınırın dışında" hatasını alacaksınızdır.
örnek 6: Varray kullanımı
DECLARE
TYPE emp_type IS VARRAY(3) OF hr.employees.first_name%TYPE;
ename emp_type;
BEGIN
ename := emp_type ('scott', 'steve', 'king');

FOR i IN 1 .. ename.COUNT
LOOP
DBMS_OUTPUT.put_line (ename (i));
END LOOP;
END;
örnek 6 bize aşağıdaki gibi bir output verecektir.
scott
steve
king
...
örnek 7 :Varray içine dinamik veri aktarımı ve bir prosedure input parametresi olarak array geçirilmesi.
Önce iki adet kolonu olan bir type oluşturalım. Şöyleki tipin bir kolonu id number, diğer kolonu ise name varchar2 olsun.
CREATE TYPE person AS object
(id NUMBER(5), name VARCHAR2(30));
Daha sonra bu tipe bağlı olarak bir varray oluşturalım.
CREATE or replace TYPE array_of_persons is varray(100) of person;
Bu aşamada artık varray veritababında saklanacak şekilde oluşturmuş olduk.Şimdi array_of_persons arrayını input olarak alacak prosedurumuzu yazalım.
CREATE OR REPLACE PROCEDURE write_person (p_array IN array_of_persons)
AS
BEGIN
FOR i IN 1 .. p_array.COUNT
LOOP
DBMS_OUTPUT.put_line ('id -->'||p_array(i).id||' :name -->'||p_array(i).name);
END LOOP;
END;
Artık oluşturduğumuz varray tipini referans alarak bir değişken oluşturabilir bu değişkenin içinede istediğimiz tablounun id ve name kolonlarını atabiliriz. Yalnız dikkat edilmesi gerekn burada oluşturacağımız varray boyutu kadar değer atabilir ve sadece id iyi number ve name ide daha önce belirlediğimiz gibi varchar2 yapmalıyız.
Aşağıdaki prosedurde ayrıca daha önce oluşturduğumuz write_person prosedurunude çağırarak output değerini alabiliriz.

DECLARE
v_array array_of_persons:= array_of_persons ();
v_id number;
v_name varchar2(30);
BEGIN
for i in 1..20 loop
select employee_id,first_name into v_id,v_name from hr.employees where employee_id=i+100;
v_array.EXTEND;
v_array (i) :=person(v_id,v_name);
end loop;
write_person (v_array);
END;
örnek 7 e aiti output aşağıdaki gibi olacaktır.

id -->101 :name -->Neena
id -->102 :name -->Lex
id -->103 :name -->Alexander
id -->104 :name -->Bruce
id -->105 :name -->David
id -->106 :name -->Valli
...

Bu makalemizde PL/Sql karmaşık veri tiplerini açıklamaya ve örneklendirmeye çalıştık.Faydalı olması dileğiyle..
 
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.