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.

  1. Implicit(Örtülü) Cursor
  2. 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.

PL/SQL CURSOR - PL/SQL Implicit Cursor - PL/SQL Örtülü Cursor

Ş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.

PL SQL CURSOR - PL SQL Implicit Cursor - PL SQL Örtülü Cursor

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;
/

PL-SQL CURSOR - PL-SQL Implicit Cursor - PL-SQL Örtülü Cursor

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ı

PL/SQL CURSOR - PL/SQL Explicit Cursor - PL/SQL Açık Cursor

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

Loading