Oracle, kodun derleme işlemini temel olarak yukarıdaki mimari ile gerçekleştirir. Begin .. End arasında bulunan bir bloğun derlenmesi sırasında once Plsql engine çağrılarak Plsql kodu derlenmeye başlanır; kod içerisindeki sql cümlecikleri için ise SQL Engine çağrılarak sql cümleciğinin sonucu SQL engine tarafından PLSQL Engine’ e döndürülür. İşte bu sırada SQL işlemlerini gerçekleştirmek için implicit cursor’lar kullanılır. Örnek verilecek olursa basit bir update cümlesi için Oracle tarafında bir implicit cursor açılarak, işlemler bu cursor aracılığı ile gerçekleştirilir. Daha once de belirttiğimiz gibi developer bu açma kapama aşamasının dışındadır. Fakat cursorun bazı özelliklerini çağırabilir. Bunlar ;
sql%rowcount -> %rowcount -> implicit cursor’da kaç satır olduğu bilgisi
sql%notfound -> implicit cursor’da kayıt yok ise true döndürür
sql%found -> implicit cursor’da kayıt var ise true döndürür.
Küçük bir örnek verelim :
DECLARE
v_cnt NUMBER;
BEGIN
UPDATE HR.employees e
SET e.salary = e.salary + 100
WHERE e.department_id = 50;
v_cnt := SQL%ROWCOUNT; -- update işlemi sırasında kullanılan implicit cursorun satır sayısı
DBMS_OUTPUT.put_line (v_cnt || ' rows updated.');
END;
DBMS_OUTPUT :
45 rows updated.
2)Explicit Cursor
Kullanımı developer hakimiyetinde olan cursor tipleridir. Bu tip cursor’ lar kodu yazan kişi tarafından tanımlanır ve kullanılırlar. Aşağıdaki örneği inceleyelim :
DECLARE
CURSOR c1 -- cursor tanımı..
IS
SELECT *
FROM hr.employees e
WHERE e.department_id = 100;
r1 c1%ROWTYPE; -- cursorun sakladığı datanın satır tipinde bir değişken tanımlanıyor..
BEGIN
if not c1%isopen then -- cursor kapalı konumda ise açılıyor. (closed konumdaysa içine erişilemez. "invalic cursor" hatası alınır.)
open c1;
end if;
LOOP
FETCH c1
INTO r1; -- cursor içindeki 6 adet kayıt, döngü içerisinde sırasıyka r1 değişkenine assign ediliyor.
DBMS_OUTPUT.put_line ( r1.employee_id
|| ' numarali personel : '
|| r1.first_name
);
EXIT WHEN c1%NOTFOUND; -- cursor artık kayıt kalmadığı zaman döngünden çıkılıyor.
END LOOP;
if c1%isopen then
close c1; -- cursor açık konumda ise kapatılyor.
end if;
END;
DBMS_OUTPUT :
108 numarali personel : Nancy
109 numarali personel : Daniel
110 numarali personel : John
111 numarali personel : Ismael
112 numarali personel : Jose Manuel
113 numarali personel : Luis
113 numarali personel : Luis
Burada dikkat edilmesi gereken nokta, cursor’un open close edilmesidir. Açık bir cursor kapatılmadığı zaman şöyle bir hataya sebep olabilir : Aşağıda ilgili cursor ile ilgili başka bir işlem için yeni bir loop açıldığında cursor sıfırdan okunmaz. Örnek verecek olursak, yukarıdaki kod içinde 6 kaydın tamamını değil de 3. kayıttan sonra döngüden çıkıp cursor’u kapatmadan aşağıda yeni bir loop’ a girse idik cursor’ı baştan değil 3. satırdan itibaren okumaya devam edecekti.
Cursor’ ı Parametre ile Çağırmak
Yukardaki örneğimizde department_id si 100 olanlar için cursor tanımlamıştık. Bazı durumlarda bu filtrelerin dinamik olarak verilmesi gerekebilir. Bu gibi ihtiyaçlarda cursor’ı parametrik tanımlayarak kullanabiliriz. Yukardaki örneğin aynısını parametrik şekilde inceleyelim:
/* Formatted on 2011/08/08 00:26 (Formatter Plus v4.8.8) */
DECLARE
CURSOR c1(p_id in number) -- id filtresi dışarıdan gelecek ..
IS
SELECT *
FROM hr.employees e
WHERE e.department_id = p_id;
r1 c1%ROWTYPE; -- cursorun sakladığı datanın satır tipinde bir değişken tanımlanıyor..
BEGIN
if not c1%isopen then --
open c1(100); -- cursor 100 parametresi ile çağrılıyor.
end if;
LOOP
FETCH c1
INTO r1;
DBMS_OUTPUT.put_line ( r1.employee_id
|| ' numarali personel : '
|| r1.first_name
);
EXIT WHEN c1%NOTFOUND;
END LOOP;
if c1%isopen then
close c1;
end if;
END;
DBMS_OUTPUT :
108 numarali personel : Nancy
109 numarali personel : Daniel
110 numarali personel : John
111 numarali personel : Ismael
112 numarali personel : Jose Manuel
113 numarali personel : Luis
113 numarali personel : Luis
REF_CURSOR Kullanımı
Adı üzerinde referans cursor’lardır. İçeriği static olarak kodun başında değil ; dinamik olarak kodun içinde belirlenir. Aşağıdaki örnek olayı biraz daha netleştirecektir :
Önce cursor un farkını daha iyi anlayabilmemizi sağlaması açıs