Cursor bir küme içinde bulunan verileri işaret eden ve cursor çeşidine göre verileri,sayısını,verinin olup olmadığını vs. bilgileri bize sunan yapılardır.Yani Cursor birden çok veriyi memory de tutup yorumlayabilmemizi sağlar. Nasıl ki değişkenler tek bir adet veriyi tutuyorsa , cursor ‘lerde bir çok veriyi hatta tabloları tutabilen pl/sql yapılarıdır. PL/SQL ‘de bulunan iki tip cursor yapısı vardır.
- Implicit(Örtülü) Cursor
- Explicit(Açık) Cursor
Implicit(Örtülü) Cursor
Implicit Cursor SQL cümlecikleri çalıştırıldığında Oracle tarafından (eğer explicit cursor yoksa) çalıştırılırlar. Programcı bu yapıya müdahale edemediği için implicit cursor(örtülü gösterge) deniliyor. Programcı bu göstergelere müdahale edemez fakat aşağıdaki tablo da açıklamaya çalıştığım fonksiyonlar ile bazı bilgiler edinebilir. Fonksiyonlardan önce aşağıdaki şekli de sizlere kısaca açıklayayım. PL/SQL bloklarının içerisinde diğer yazılarda gördüğünüz gibi SQL cümlelerini de kullanıyoruz.Oracle normalde PL/SQL Engine ile işe başlar fakat eğer arada SQL sorguları var ise SQL Engine ‘e gidip sorguyu çalıştırıp tekrar PL/SQL Engine’e döner. Aslında implicit cursor’lar işte bu geçişlerdeki verileri tutmaya yarar.
Şimdi bu geçişte tutulan veriler hakkında aşağıdaki fonksiyonlar ile ne kadar bilgi edinebileceğimizi görelim.
Fonksiyon | Açıklama |
%FOUND | Eğer INSERT, UPDATE, ya da DELETE işlemlerinden bir veya daha fazla satır etkilendiyse TRUE döner veya SELECT INTO işleminden bir veya birden fazla satır etkilendiyse TRUE döner. Bunların dışında FALSE döner. |
%NOTFOUND | Mantıksal olarak FOUND işleminin tam tersidir. |
%ISOPEN | Implicit Cursorlar için herzaman FALSE döner çünkü Oracle SQL sorgusu biter bitmez otomatik olarak cursor’ı kapatır.Yani bu fonksiyon cursor kapalı mı değil mi bunu kontrol eder. |
%ROWCOUNT | INSERT,UPDATE,DELETE işlemlerinden etkilenen satur sayısını ve INSERT INTO işleminde insert edilen kayıt sayısını döndürür. |
Aşağıdaki örnekte her çalışanın maaşına 500 eklenir ,eğer böyle bir kayıt yoksa öğrencinin seçilemediğini ve eğer seçilip update edildiyse kaç kaydın update edildiğini ekrana yazar.
DECLARE total_rows number(2); BEGIN UPDATE test_array SET salary = salary + 500; IF sql%notfound THEN dbms_output.put_line('no customers selected'); ELSIF sql%found THEN total_rows := sql%rowcount; dbms_output.put_line( total_rows || ' customers selected '); END IF; END; /
Explicit(Açık) Cursor
Diğer bir cursor tipi olan explicit cursor, programcı tarafından yazılan cursorlardır. Select sorgusu üzerinden alınan verilerin göstergesidir ve declare kısmında yazılır. Explicit cursor ile çalışmanın kuralları aşağıdaki gibidir.
- Declare kısmında cursor’ın tanımlanması ve memory ‘nin (hafıza) başlatılması
- Cursor’ın açılması
- Cursor’daki verilerin Fetch(yakalama) edilmesi
- Cursor’ı kapatıp ayrılan(allocate edilen) hafızanın serbest bırakılması
Cursor Oluşturma :
CURSOR c_employyes IS SELECT employee_id, first_name, last_name FROM hr.employees;
Cursor Açılması :
OPEN c_employyes;
Cursor’ı Fetch Etme :
FETCH c_employyes INTO c_id,c_name,c_lastname;
Cursor’u Kapatma :
CLOSE c_employyes;
Örnek 1;
DECLARE c_id hr.employees.employee_id%type; c_name hr.employees.first_name%type; c_surname hr.employees.last_name%type; CURSOR c_employees is SELECT employee_id, first_name, last_name FROM hr.employees; BEGIN OPEN c_employees; LOOP FETCH c_employees into c_id, c_name, c_surname; ** EXIT WHEN c_employees%notfound; dbms_output.put_line(c_id || ' ' || c_name || ' ' || c_surname); END LOOP; CLOSE c_employees; END; /
Ref Cursor
Ref cursor, normal cursor gibi davranan fakat normal cursor dan farklı olarak herhangi bir sql sorguya referans vererek dinamik sorgular yaratmamıza olanak sağlayan, daha kompleks, geniş alanlarda kullanımı sağlanabilen, bir oracle Plsql değişkenidir.
Bir örnek üzerinde inceleyelim; Bu değişkeni bir paket içerisinde tanımlayıp, paket içerisindeki bir procedure de kullanalım. Oluşturduğumuz bu paketi dışardan çağırarak dinamik bir yapı oluşturalım.
DECLARE TYPE empcurtyp IS REF CURSOR RETURN hr.employees%ROWTYPE; emp empcurtyp; -- after result set is built, process all the rows inside a single procedure -- rather than calling a procedure for each row PROCEDURE process_emp_cv (emp_cv IN empcurtyp) IS person hr.employees%ROWTYPE; BEGIN DBMS_OUTPUT.PUT_LINE('-----'); DBMS_OUTPUT.PUT_LINE('Here are the names from the result set:'); LOOP FETCH emp_cv INTO person; EXIT WHEN emp_cv%NOTFOUND; DBMS_OUTPUT.PUT_LINE('Name = ' || person.first_name || ' ' || person.last_name); END LOOP; END; BEGIN -- First find 10 arbitrary employees. OPEN emp FOR SELECT * FROM hr.employees WHERE ROWNUM < 11; process_emp_cv(emp); CLOSE emp; -- find employees matching a condition. OPEN emp FOR SELECT * FROM hr.employees WHERE last_name LIKE 'R%'; process_emp_cv(emp); CLOSE emp; END; /
Yararlı olması Dilegiyle …
Yazar : Mustafa Bektaş Tepe
Kaynaklar;
http://www.tutorialspoint.com/plsql/plsql_basic_syntax.htm
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