Anda di halaman 1dari 6

PL/SQL

By Chy Ichal Iiank Tegaar


Pertama-tama, buatlah table dengan SQL seperti di bawah ini:
create table mahasiswa(
nim varchar2(7) primary key,
nama varchar2(30),
ipk number(30)
);
create table matakuliah(
kode_mk varchar2(5) primary key,
nama_mk varchar2(30),
sks integer
);
create table nilai(
id_nilai integer,
nim varchar2(7),
kode_mk varchar2(5),
nilai varchar2(2),
mutu integer,
constraint fk_nim foreign key(nim) references mahasiswa(nim) on delete cascade,
constraint fk_kode_mk foreign key(kode_mk) references matakuliah(kode_mk) on
delete cascade
);
insert
insert
insert
insert
insert
insert
insert
insert

into
into
into
into
into
into
into
into

mahasiswa values('0900411','Faisal Agus Tri Putra',null);


mahasiswa values('0900412','Atiqah Hasiholan',null);
matakuliah values('IK441','Basis Data',2);
matakuliah values('IK442','Sistem Basis Data',3);
nilai values(1,'0900411','IK441','A',null);
nilai values(2,'0900412','IK441','B',null);
nilai values(3,'0900411','IK442','C',null);
nilai values(4,'0900412','IK442','A',null);

Sudah, ayo kita belajar bagaimana cara membuat PL/SQL di oracle


1. Membuat fungsi untuk mengubah huruf nilai menjadi angka
Dalam table di atas, masukan nilai masih berupa huruf. Nah, gimana caranya untuk mengubah huruf
tersebut menjadi angka? Misal: A=4, B=3, C=2, D=1, Lainnya=0.
Berikut adalah fungsi untuk mengkonversinya:
create or replace function konversiNilai(v_nilai in varchar2) return integer as
v_angka integer;
begin
if v_nilai = 'A' then
v_angka := 4;
elsif v_nilai = 'B' then
v_angka := 3;
elsif v_nilai = 'C' then
v_angka := 2;
elsif v_nilai = 'D' then
v_angka := 1;
else
v_angka := 0;
end if;
return v_angka;
end;
/
/*Execution:*/
Select konversiNilai(A) From dual;

Kayaknya udah cukup jelas yah untuk fungsi ini Kalau ada pertanyaan silahkan lewat grup.
2.

Membuat prosedur untuk menghitung semua mutu yang ada


Emmm Tadi table di atas, kolom mutu masih terisi kosong. Nah, kita akan membuat prosedur
untuk mengisi kolom mutu yang masih kosong itu.
Ini kodenya:
create or replace procedure hitungSemuaMutu as
v_kodemk varchar2(5);
v_nilai varchar2(2);
v_idnilai integer;
v_sks integer;
v_mutu integer;
cursor c_nilai is select id_nilai, kode_mk, nilai from nilai;
cursor c_sks is select sks from matakuliah where kode_mk=v_kodemk;
begin
open c_nilai;
loop
fetch c_nilai into v_idnilai, v_kodemk, v_nilai;
exit when c_nilai %notfound;
open c_sks;
loop
fetch c_sks into v_sks;
exit when c_sks %notfound;
v_mutu := v_sks*konversiNilai(v_nilai);
update nilai set mutu=v_mutu where id_nilai=v_idnilai;
end loop;
close c_sks;
end loop;
close c_nilai;
end;
/
/*execution*/
Exec hitungSemuaMutu;

3. Membuat prosedur untuk menghitung IPK yang ada


Ada dua cara sebenarnya, ada yang perlu pakai cursor dan ada yang tidak menggunakan cursor.
Kenapa? Sebab nilai SUM itu cuman ada 1 baris dan cukup mubazir (kebanyakan ngetik) kalau pake
kursor.
Oke, ini versi berkursor:
create or replace procedure hitungIPK as
v_nim mahasiswa.nim%TYPE;
v_mutu nilai.mutu%TYPE;
v_sks matakuliah.sks%TYPE;
v_ipk mahasiswa.ipk%TYPE;
cursor cnim is select nim from mahasiswa;
cursor cmutu is select sum(mutu) from nilai where nim=v_nim;
cursor csks is select sum(matakuliah.sks) from nilai,matakuliah where
matakuliah.kode_mk=nilai.kode_mk and nilai.nim=v_nim;
begin
hitungSemuaMutu;/*jaga-jaga kalau-kalau ada yang masih kosong*/
open cnim;
loop
fetch cnim into v_nim;
exit when cnim %NOTFOUND;
/* kita akan ambil mutu */
open cmutu;
fetch cmutu into v_mutu;
close cmutu;
/* kita akan ambil SKS */
open csks;
fetch csks into v_sks;
close csks;
v_ipk:=v_mutu/v_sks;

DBMS_OUTPUT.PUT_LINE('Nimnya'||v_nim||'Mutunya'||v_mutu||'SKSnya'||v_sks||'IPKn
ya'||v_ipk);
update mahasiswa set ipk=v_ipk where nim=v_nim;
end loop;
close cnim;
end;
/

Dan ini versi tidak berkursor


create or replace procedure hitungIPK as
v_nim mahasiswa.nim%TYPE;
v_mutu nilai.mutu%TYPE;
v_sks matakuliah.sks%TYPE;
v_ipk mahasiswa.ipk%TYPE;
cursor cnim is select nim from mahasiswa;
begin
hitungSemuaMutu;/*jaga-jaga kalau-kalau ada yang masih kosong*/
open cnim;
loop
fetch cnim into v_nim;
exit when cnim %NOTFOUND;
/* kita akan ambil mutu */
select sum(mutu) into v_mutu from nilai where nim=v_nim;
/* kita akan ambil SKS */
select sum(matakuliah.sks) into v_sks from nilai,matakuliah where
matakuliah.kode_mk=nilai.kode_mk and nilai.nim=v_nim;
v_ipk:=v_mutu/v_sks;
DBMS_OUTPUT.PUT_LINE('Nimnya'||v_nim||'Mutunya'||v_mutu||'SKSnya'||v_sks||'IPKn
ya'||v_ipk);
update mahasiswa set ipk=v_ipk where nim=v_nim;
end loop;
close cnim;
end;
/

Perbedaan utamanya terdapat pada penggunaaan select into dan cursor.


Pada komando:
select sum(matakuliah.sks) into v_sks from nilai,matakuliah where
matakuliah.kode_mk=nilai.kode_mk and nilai.nim=v_nim;

artinya adalah kita memberikan nilai sum(matakuliah.sks) ke variable v_sks.


REKOMENDASI: Kalau kita yakin bahwa hasil querynya hanya menghasilkan satu baris, berarti cukup
pake select into ajah.
4. Trigger untuk mengisi mutu (Before)
create or replace trigger memasukkanNilai
before
insert
on nilai
for each row
declare
v_sks integer;
v_kodemk varchar(5);
v_mutu integer;
cursor c_sks is select sks from matakuliah where kode_mk=v_kodemk;
begin
v_kodemk := :new.kode_mk;
open c_sks;
fetch c_sks into v_sks;
v_mutu := v_sks*konversiNilai(:new.nilai);
select v_mutu into :new.mutu from dual;
close c_sks;
end;

Oke, disini aku sebagai cowok ganteng akan menjelaskan mengenai hal ihwal trigger ini:
Trigger itu adalah perintah yang akan dipanggil secara otomatis ketika terjadi suatu event. Event
tersebut ada 3, yakni before/after insert, before/after update, before/after delete.
create or replace trigger memasukkanNilai
before
insert
on nilai
for each row

Komando di atas artinya kita membuat sebuah komando untuk membuat trigger dengan nama
memasukkanNilai yang akan dilakukan sebelum insert pada table nilai di setiap barisnya (on each
rows). Kalau kamu ingin dilakukan sebelum update atau delete kamu tinggal ganti saja menjadi:
Before
update

Atau
Before
Delete

Atau
Before
insert or update or delete

Kalau pake komando terakhir berarti trigger ini akan dijalankan ketika insert, update, dan delete.
Okey, next: Ciri khas dari trigger adalah kita bisa mengambil data yang sedang diinsertkan atau
sedang diupdate atau sedang di delete. Lihat contoh di bawah:
v_kodemk := :new.kode_mk;

itu artinya nilai kode_mk yang diinsertkan akan ditampung ke variable v_kodemk.
Perintah :new dan :old
Banyak diantara kita yang luarbiasa rieut dengan apa perbedaan antara :old dan :new.
Simpelnya, :new hanya bisa digunakan di insert dan update, dan :old hanya bisa digunakan di
update dan delete.
Misal ada komando:
Insert into kamu(hatimu) values(cintaku);

Itu berarti nilai :new.hatimu adalah cintaku.


Itu kalau insert, kalau update analoginya agak ribet. Kalau misalkan sebelumnya di table kamu kolom
hatimu telah terdapat value missal: cintanya
Maka komando:

Update kamu set hatimu=cintaku

Berarti :new.hatimu adalah cintaku dan :old.hatimu adalah cintanya.


Jadi old dan new pada update berbicara tentang siapa yang mengganti dan tergantikan. Kalau
misalnya kamu diputusin oleh pacar kamu, artinya kamu adalah :old. Kalau kamu telah merebut hati
pacar orang lain dan mengusir orang yang telah berada di dalamnya sebelumnya, berarti kamu
adalah :new.

WARNING: Saya tidak menganjurkan kamu untuk merebut pacar orang. :new dan
:old ini cuman sekedar ilustrasi
Oke. Tearkhir kalau delete seperti komando
Delete from kamu where hatimu=cintaku

Artinya, :old.hatimu adalah cintaku.


Lalu kenapa pada contoh di atas tidak ada query insert?
Jawabannya, itu mah otomatis. Jadi cukup dengan mengubah :new.mutu, maka mutu yang
diinsertkan akan secara otomatis berubah.
select v_mutu into :new.mutu from dual;

Kenapa pake dual? Karena select into itu harus pake table. Mirip dengan kasus untuk mengambil
hasil function.
Okeh, can you keep?
5. Trigger untuk mengisi mutu dan IPK
Haha, ini bagian paling sulit dari kasus ini. Jadi, perhitungan IPK tidak bisa dilakukan pada kondisi
AFTER. Mengapa? Sebab, kalau AFTER artinya data telah terisi dan artinya table Nilai telah
berubah (mutating). Pada kondisi AFTER, mutating adalah sebuah kondisi terlarang (tabu) sehingga
kita tidak bisa mengambil nilai jumlah mutu pada kondisi after. Hehe
Jadi solusi terakhirnya, perhitungan IPK disatukan dengan mengisi mutu. Here the code:
create or replace trigger memasukkanNilai
before
insert
on nilai
for each row
declare
v_nim mahasiswa.nim%TYPE;
v_mutu nilai.mutu%TYPE;
v_sks matakuliah.sks%TYPE;
v_mutu_tot nilai.mutu%TYPE;
v_sks_tot matakuliah.sks%TYPE;
v_ipk mahasiswa.ipk%TYPE;
v_kodemk nilai.kode_mk%TYPE;
cursor c_sks is select sks from matakuliah where kode_mk=v_kodemk;
begin

v_nim := :new.nim;
v_kodemk := :new.kode_mk;
DBMS_OUTPUT.PUT_LINE('KodeMK: '||:new.kode_mk||'nilai: '||:new.nilai||'mutu:
'||:new.mutu);
open c_sks;
fetch c_sks into v_sks;
v_mutu := v_sks*konversiNilai(:new.nilai);
select v_mutu into :new.mutu from dual;
DBMS_OUTPUT.PUT_LINE('vsks: '||v_sks);
close c_sks;
/* kita akan ambil semua mutu */
select sum(mutu) into v_mutu_tot from nilai where nim=v_nim;
/* kita akan ambil semua SKS */
select sum(matakuliah.sks) into v_sks_tot from nilai,matakuliah where
matakuliah.kode_mk=nilai.kode_mk and nilai.nim=v_nim;
v_mutu_tot := v_mutu_tot + v_mutu;
v_sks_tot := v_sks_tot + v_sks;
v_ipk := v_mutu_tot/v_sks_tot;
update mahasiswa set ipk=v_ipk where nim=:new.nim;
end;
/

Oke, ada beberapa hal menarik di atas, salah satunya ini:


v_mutu_tot := v_mutu_tot + v_mutu;
v_sks_tot := v_sks_tot + v_sks;

Kenapa coba harus ditambahkan lagi dengan v_mutu dan v_sks?


Karena ini statusnya masih BEFORE, sebelum terjadinya proses insert. Maka secara otomatis, kita
belum memasukan nilai yang akan kita insertkan kedalam v_mutu_tot dan v_sks_tot. Okey?

WARNING: Trigger After biasanya hanya digunakan untuk mengisi table log/rekapitulasi. Silahkan
belajar sendiri

Anda mungkin juga menyukai