Minggu, 09 Januari 2011

CURSOR

Blok PL/SQL tidak memungkinkan untuk menangani query dengan keluaran lebih dari satu baris(record) karena variabel penampungnya harus mempunyai sebuah nilai. Karena itu, diperlukan sebuah cursor untuk menampung semua kondisi dari keluaran sebuah query. Cursor merupakan suatu variabel yang digunakan untuk menampung  hasil query yang terdiri atas lebih dari satu row atau record. Cursor dapat diilustrasikan sebagai penampung sekaligus pointer atas hasil eksekusi query. Pada dasarnya perintah “SELECT ..” pada PL/SQL merupakan sebuah cursor. Terdapat dua macam cursor, yaitu: cursor implisit dan cursor eksplisit

Cursor Implisit

Merupakan perintah SELECT statement dengan klausa INTO yang terdapat di dalam blok PL/SQL dan harus menghasilkan satu baris record. Jika hasil cursor implisit ini lebih dari satu baris atau tidak menghasilkan satu baris pun, maka Oracle akan mengeluarkan pesan kesalahan. Klausa into pada cursor implisit dipakai untuk menugaskan nilai hasil proses select ke dalam variabel-variabel yang dipilih.

Atribut
Keterangan
SQL%FOUND
TRUE jika cursor menghasilkan sebuah baris dari queri yang dideklarasikan. Sebaliknya FALSE.
SQL%NOTFOUND
Kebalikan dari %FOUND
SQL%ROWCOUNT
Jumlah baris yang telah diambil/ditangkap (FETCH)
SQL%ISOPEN
Mengembalikan nilai TRUE jika cursor masih dalam keadaan terbuka (OPEN)










Contoh:
declare
      mhs_rec mahasiswa%rowtype;
      nim_nya mahasiswa.nim%type;
begin
      nim_nya := '30108001';
      select nim, nama, alamat into mhs_rec
      from nahasiswa
      where nim = nim_nya;
      ...
end;


                                                                                                                                                                   
Jika nilai nim sama dengan 30108001 dipenuhi maka hasil proses select menghasilkan satu baris, sedangkan jika nilai nim_nya diganti dengan nilai lain dimana nilai tersebut tidak akan menghasilkan satu baris pun, maka Oracle akan mengeluarkan pesan kesalahan. Demikian pula jika klausa where pada cursor di atas dihilangkan sementara di dalam tabel proyek terdapat lebih dari satu baris, maka cursor tersebut tidak dapat menampung semua baris yang diterima. Hal ini akan menimbulkan error “exact fetch returns more than requested number of rows”.

--IMPLICIT CURSOR CONTOH 1.

declare
  vnim  mahasiswa.nim%type:='&nim_mhs';
  vnama mahasiswa.nama%type;

begin
  select nim,nama into vnim,vnama
  from mahasiswa
  where nim =vnim;
  dbms_output.put_line('Nim            : '||vnim);
  dbms_output.put_line('Nama mahasiswa : '||vnama);

exception
  when no_data_found then
dbms_output.put_line('Tidak ada mahasiswa
dengan nim : '||vnim);
  when too_many_rows then
dbms_output.put_line('Data yang dihasilkan
lebih dari 1 baris');
end;
/

-- IMPLICIT CURSOR CONTOH 2.

declare
  vnim  mahasiswa.nim%type:='&nim_mhs';
  vnama mahasiswa.nama%type;
  n number;

begin
  select nim,nama into vnim,vnama
  from mahasiswa
  where nim =vnim;
  n := sql%rowcount;
  dbms_output.put_line('Data Mahasiswa');
  if sql%found then
     dbms_output.put_line('Nim   : '||vnim);
     dbms_output.put_line('Nama  : '||vnama);
     dbms_output.put_line('Jumlah data   : '||n);
  end if;

exception
  when no_data_found then
   dbms_output.put_line('Tidak ada mahasiswa dengan
nim: '||vnim);
  when too_many_rows then
   dbms_output.put_line('Data yang dihasilkan lebih
dari 1 baris');
end;
/

-- IMPLICIT CURSOR CONTOH 3.

declare
  vnama mahasiswa.nama%type :='&nama_mhs';
  -- masukkan paijo misal ada 2 mahasiswa dengan
     nama depan paijo
  n number;

begin
  update mahasiswa set alamat='SKB'
  where nama like vnama||'%';
  n := sql%rowcount;
  if sql%found then
    dbms_output.put_line('Mahasiswa dengan nama
        depan '||vnama||' telah di update');
     dbms_output.put_line('Jumlah data yang diupdate
        = '||n);
  else
     dbms_output.put_line('Tidak ada mahasiswa
        dengan nama depan : '||vnama);
     dbms_output.put_line('Jumlah data yang diupdate
        = '||n);
  end if;

exception
  when too_many_rows then
   dbms_output.put_line('Data yang dihasilkan lebih
   dari 1 baris');
end;
/

Cursor Eksplisit

Tidak seperti cursor implisit, cursor eksplisit harus dideklarasikan terlebih dahulu sebelum digunakan. Terdapat empat tahapan penggunaan cursor eksplisit ini yaitu: declare, open, fetch dan terakhir adalah close.

Statement declare:
CURSOR nama_cursor IS query


Merupakan deklarasi nama cursor dan definisi struktur query yang akan dilakukan di dalamnya.

Contoh:
DECLARE
CURSOR CUR1 IS
SELECT nim, nama, alamat
FROM mahasiswa
.. .. ..



Statement open
OPEN nama_cursor;

Sebelum suatu cursor dapat digunakan, cursor harus dibuka terlebih dahulu.

Contoh:
OPEN CUR1;


Statement fetch
FETCH nama_cursor INTO <variable1,variable2,..>;




Fetch merupakan perintah untuk mengambil isi cursor, dimana isi dari cursor tersebut adalah hasil query yang telah dideklarasikan pada statement deklarasi cursor. Dan tiap-tiap field hasil query tersebut kemudian ditampung dalam variable-variable yang tipe datanya sesuai dengan tipe-tipe kolom query pada statemen deklarasi. Fetch ini dilakukan untuk tiap-tiap baris.

Contoh:
FETCH CUR1 INTO v_nim, v_nama, v_alamat;



Statement close
CLOSE nama_cursor;


 Setelah pemrosesan query selesai, cursor harus ditutup dengan satatemen CLOSE ini. Berikut ini adalah atribut-atribut untuk mendapatkan status cursor. Setiap atribut dalam penggunaannya harus didahului dengan nama cursor.



Atribut
Keterangan
nama_cursor%FOUND
TRUE jika cursor menghasilkan sebuah baris dari queri yang dideklarasikan. Sebaliknya FALSE.
nama_cursor%NOTFOUND
Kebalikan dari %FOUND
nama_cursor%ROWCOUNT
Jumlah baris yang di-fetch atau diambil dari active set.
nama_cursor%ISOPEN
TRUE jika cursor sedang terbuka dan FALSE jika sebaliknya.


Contoh:
DECLARE
v_nama varchar2(20);
v_nim char(9);
CURSOR CUR1 IS SELECT NAMA, NIM
FROM MAHASISWA;
BEGIN
      OPEN CUR1;
      FETCH CUR1 INTO v_nama, v_nim;
      WHILE CUR1%FOUND LOOP
            DBMS_OUTPUT.PUT_LINE(v_nama);
            DBMS_OUTPUT.PUT_LINE(v_nim);
            FETCH CUR1 INTO v_nama, v_nim;
END LOOP;
CLOSE CUR1;
END;

















Cursor  FOR LOOP


Ada sebuah cara untuk mengambil isi cursor secara otomatis, yaitu dengan struktur pengulangan FOR LOOP.
Disebut otomatis karena
·   tidak perlu proses pembukaan cursor ( OPEN )
·   memanipulasi proses pengambilan cursor ( FETCH )
·   tidak perlu penutupan cursor ( CLOSE )
·   variabel indeks yang digunakan dalam struktur pengulangan  FOR_LOOP tidak perlu dideklarasikan terlebih dahulu

Sintaks:
DECLARE
CURSOR nama_cursor IS ekspresi-query

BEGIN
      FOR nama_record IN nama_cursor LOOP
      -- nama_record tidak perlu dideklarasikan
...
END LOOP
END;



Contoh:
DECLARE
CURSOR cur1 IS select nama from mahasiswa;

BEGIN
      FOR rec IN cur1 LOOP
            dbms_output.put_line(rec.nama);
END LOOP
END;



Nama record yang didefinisikan sesudah for merupakan pendeklarasian yang hanya internal di dalam loop, dan ruang lingkupnya bersifat internal sampai loop berhenti. Sebenarnya di dalam loop for, cursor tidak harus dideklarasikan terlebih dahulu.


-- EKSPLISIT CURSOR CONTOH 1.
(Menggunakan LOOP-EXIT)

declare
  vnim  mahasiswa.nim%type;
  vnama mahasiswa.nama%type;
 

  cursor cursor1 is
      select nim, nama from mahasiswa;
  n number;

begin
  dbms_output.put_line('Data Mahasiswa);
  dbms_output.put_line('No  Nim     Nama');
  open cursor1;
  loop
      fetch cursor1 into vnim, vnama;
      exit when cursor1%notfound;
      dbms_output.put_line(cursor1%rowcount||'. 
      '||vnim||'      '||vnama);
  end loop;
  n := cursor1%rowcount;
  dbms_output.put_line('Jumlah data = '||n);
  close cursor1;

exception
  when no_data_found then
      dbms_output.put_line('Tidak ada data
      mahasiswa');

end;
/

-- EKSPLISIT CURSOR CONTOH 2.
  (Menggunakan WHILE-LOOP)

declare
  vnim  mahasiswa.nim%type;
  vnama mahasiswa.nama%type;
  cursor cursor1 is
      select nim, nama from mahasiswa;
  n number;

begin
  dbms_output.put_line('Data Mahasiswa);
  dbms_output.put_line('No  Nim     Nama');
  open cursor1;
  fetch cursor1 into vnim, vnama;
  while cursor1%found loop
      dbms_output.put_line(cursor1%rowcount||'. 
      '||vnim||'         '||vnama);
      fetch cursor1 into vnim, vnama;
  end loop;
  n := cursor1%rowcount;
  dbms_output.put_line('Jumlah data = '||n);
  close cursor1;

exception
  when no_data_found then
   dbms_output.put_line('Tidak ada data mahasiswa);

end;
/

-- EKSPLISIT CURSOR CONTOH 3.
  (Menggunakan FOR-IN-LOOP)

declare
  cursor cursor1 is
    select nim, nama from mahasiswa;
  n number;

begin
  dbms_output.put_line('Data Mahasiswa);
  dbms_output.put_line('No  Nim     Nama');
  for x in cursor1 loop 
  -- x tidak perlu di deklarasikan
     dbms_output.put_line(cursor1%rowcount|| 
     '.'||x.nim||'       '||x.nama);
     n := cursor1%rowcount;
  end loop; 
  dbms_output.put_line('Jumlah data = '||n);

exception
  when no_data_found then
   dbms_output.put_line('Tidak ada data mahasiswa');
end;
/

-- EKSPLISIT CURSOR CONTOH 4.
   (Menggunakan FOR-IN-LOOP tanpa   
mendeklarasikan cursor)

declare
  n number:=0;

begin
  dbms_output.put_line('Data Mahasiswa);
  dbms_output.put_line('No  Nim     Nama');
  for x in (select nim, nama from mahasiswa)
  loop 
  -- x tidak perlu di deklarasikan
      n := n + 1;
      dbms_output.put_line(n||'. '||x.nim||
      '   '||x.nama);
  end loop
  dbms_output.put_line('Jumlah data = '||n);

exception
  when no_data_found then
   dbms_output.put_line('Tidak ada data mahasiswa');

end;
/

JURNAL
1.     Jelaskan perbedaan antara cursor dengan perintah SELECT!
2.     Buatlah cursor implisit dan eksplisit yang menampilkan data-data buku beserta suppliernya!
3.     Jelaskan maksud dan keluaran dari blok PL/SQL dibawah ini:
declare
  vid_buku  buku.id_buku%type;
  vjudul buku.judul%type;
  cursor cursor1 is
     select id_buku, judul from buku;
  n number;

begin
  dbms_output.put_line('Data Buku);
  dbms_output.put_line(id_buku  Judul);
  open cursor1;
  fetch cursor1 into vid_buku, vjudul;
  while cursor1%found loop
dbms_output.put_line(cursor1%rowcount||’.'||vid_buku||'         '||vjudul);
     fetch cursor1 into vid_buku, vjudul;
  end loop;

  n := cursor1%rowcount;
  dbms_output.put_line('Jumlah data = '||n);
  close cursor1;

exception
  when no_data_found then
   dbms_output.put_line('Tidak ada data buku);

end;
/

4.     Jalankan blok PL/SQL dibawah ini pada SQL Plus kemudian jika terjadi error perbaiki :
DECLARE
      v_idsupplier  supplier.id_supplier%TYPE;
      v_nama  supplier.nama%TYPE;
      v_no_telepon  supplier.no_telepon%TYPE;
v_alamat  supplier.alamat%TYPE;
BEGIN
select id_supplier, nama, no_telepon, alamat into vid_supplier, vnama, vno_telepon, valamat
from supplier order by id_supplier;
      if SQL%NOTFOUND then
            dbms_output.put_line('Nama Pemesan Tidak Ditemukan ');
      else
            dbms_output.put_line('Daftar Nama Pemesan yang Total Banquetnya <= 500000 :');
dbms_output.put_line(v_npm);
      end if;
END;
/

1 komentar: