Unduh materi bab ini dalam PDF A4. Video disertakan sebagai tautan; contoh dan tabel ikut dalam PDF.
Versi PDF materi pertemuan 10. Contoh dan tabel dapat dibaca di PDF. Kuis dapat dijalankan di halaman web: Buka materi daring.
Ketik kode pada worksheet agar memahami langkah. Pembatasan seleksi/copy merupakan pengaturan antarmuka, bukan perlindungan mutlak. Isian dan referensi tetap dapat digunakan.
Tujuan pembelajaran
Menulis IF, ELSIF, nested IF serta CASE dengan cabang lengkap.
Memilih LOOP, WHILE dan FOR serta menempatkan EXIT secara aman.
Menangani NO_DATA_FOUND, TOO_MANY_ROWS dan ZERO_DIVIDE secara spesifik.
Mendefinisikan exception sendiri dan memakai RAISE_APPLICATION_ERROR untuk validasi.
Menjelaskan alur sesudah exception tanpa menelan error atau mengambil alih transaksi pemanggil.
Pokok bahasan / praktikum
IF THEN ELSE
ELSIF
Nested IF
Simple CASE
Searched CASE
LOOP
WHILE LOOP
FOR LOOP
EXIT dan EXIT WHEN
NO_DATA_FOUND
TOO_MANY_ROWS
ZERO_DIVIDE
Custom exception dan RAISE
RAISE_APPLICATION_ERROR
Validasi nilai uang
Prasyarat: Selesaikan modul 02/03 atau jalankan setup bersama sekali pada schema latihan sendiri. Gunakan Oracle XE lokal melalui SQL Developer ATAU Oracle FreeSQL setelah login pada schema pribadi yang diizinkan; tidak harus memakai keduanya. Jangan menjalankan ulang CREATE TABLE/seed pada objek yang sudah ada. Selesaikan modul SQL sebelumnya; modul 10 juga memerlukan dasar blok modul 09.
Pilih salah satu lingkungan praktikum
Oracle XE: XE lokal dengan SQL Developer: cocok untuk instalasi, koneksi, user/schema, privilege, tablespace serta latihan SQL/PLSQL.
FreeSQL: FreeSQL dengan login: masuk menggunakan akun sendiri dan gunakan schema latihan yang diizinkan untuk SQL/PLSQL. Tidak perlu memasang XE untuk menyelesaikan latihan non-administratif.
Pengumpulan tugas menerima hasil dari salah satu lingkungan. Pastikan objek prasyarat tersedia dan tetap gunakan schema latihan, bukan schema produksi.
Amati → prediksi → jelaskan
Mulai dari pertanyaan
Apa yang terjadi ketika kondisi IF bernilai NULL?
Bagaimana memastikan loop tidak berjalan tanpa akhir?
Kapan kesalahan harus ditangani lokal dan kapan perlu dikirim kepada pemanggil?
Uji pemahaman awal
Pahami konsep · baca terstruktur · terapkan
Teori dan pembahasan
Gunakan percabangan untuk keputusan, loop untuk pekerjaan berulang, dan exception untuk alur kegagalan. Setiap mekanisme perlu kasus uji batasnya sendiri.
IF mengeksekusi cabang THEN hanya ketika kondisi bernilai TRUE.
FALSE dan NULL tidak menjalankan cabang itu, sehingga data opsional harus ditangani dengan IS NULL ketika diperlukan. ELSIF mengevaluasi alternatif berurutan; setelah cabang pertama cocok, cabang berikutnya tidak dipilih.
Poin pembahasan
Urutan ambang harus dirancang agar kondisi lebih umum tidak menutup kondisi khusus.
Nested IF berarti keputusan kedua berada di dalam keputusan pertama, misalnya stok cukup baru diikuti keputusan status transaksi.
Gunakan END IF pada tiap tingkat dan indentasi konsisten.
Latihan memakai variabel lokal supaya percabangan dapat diuji tanpa mengubah data penjualan.
Bedakan label keluaran dari bukti bahwa transaksi telah tersimpan.
02
CASE untuk pilihan yang mudah dibaca
Simple CASE membandingkan sebuah ekspresi dengan beberapa nilai WHEN, cocok untuk status BARU, LUNAS atau BATAL.
Searched CASE menuliskan kondisi pada setiap WHEN, cocok untuk rentang stok. Sebagai statement PL/SQL, setiap cabang berisi tindakan dan ditutup ENDCASE; ini berbeda dari ekspresi CASE dalam SELECT yang mengembalikan satu nilai.
Poin pembahasan
Sediakan ELSE untuk masukan yang belum dikenali.
CASE statement tanpa cabang cocok dan tanpa ELSE dapat memicu CASE_NOT_FOUND, sedangkan CASE expression tanpa ELSE menghasilkan NULL ketika tidak ada kecocokan.
Pengujian harus mencakup kondisi normal, batas ambang, dan nilai kosong agar label laporan tidak menyembunyikan data yang belum lengkap.
03
LOOP, WHILE, FOR dan EXIT
Basic LOOP selalu masuk ke badan loop dan memerlukan jalan keluar.
EXIT meninggalkan loop, sedangkan EXIT WHEN meninggalkannya hanya saat kondisi TRUE. WHILE memeriksa kondisi sebelum badan, sehingga dapat berjalan nol kali.
Poin pembahasan
Numeric FOR mengelola indeks lokal dari batas awal sampai akhir; indeks bersifat read-only dan tidak perlu dinaikkan manual.
Gunakan FOR ketika jumlah iterasi diketahui, WHILE ketika bergantung pada keadaan, dan LOOP ketika keputusan berhenti berada di badan.
Pastikan variabel pembatas benar-benar berubah agar tidak membuat infinite loop.
Contoh berikut sengaja dibatasi kecil.
Jika kebutuhan hanya agregasi seluruh detail, satu SELECTSUM umumnya lebih jelas daripada menjumlahkan dengan loop per baris.
04
Exception bawaan dan alur pemulihan
NO_DATA_FOUND terjadi ketika SELECT INTO biasa tidak memperoleh baris, TOO_MANY_ROWS ketika memperoleh lebih dari satu, dan ZERO_DIVIDE ketika membagi angka dengan nol.
Handler spesifik menerangkan penyebab dan tindakan yang cocok. Setelah exception muncul, sisa pernyataan dalam bagian eksekusi blok itu tidak berjalan; sesudah handler, kontrol melanjutkan di luar blok tersebut.
Poin pembahasan
Subblok memungkinkan percobaan yang gagal dipisahkan dari percobaan berikutnya.
Jangan mencetak berhasil setelah error tanpa menjelaskan batas tindakan yang selesai.
WHEN OTHERS bukan pengganti semua handler: jika hanya mencatat masalah tak dikenal, lakukan RAISE agar pemanggil tahu bahwa operasi gagal.
Contoh tidak memakai DML sehingga tidak memerlukan rollback.
05
Custom exception dan RAISE
Exception yang didefinisikan sendiri dideklarasikan dengan tipe EXCEPTION lalu diaktifkan secara eksplisit memakai RAISE nama_exception.
Gunakan untuk kondisi bisnis, misalnya jumlah diminta melebihi stok yang tersedia. Handler dapat menampilkan alasan dalam latihan, tetapi pada API yang dipakai program lain, kesalahan biasanya harus dikembalikan kepada pemanggil dengan kontrak yang jelas.
Poin pembahasan
Custom exception lokal tidak otomatis mempunyai pesan bisnis publik atau nomor kesalahan khusus.
Validasi harus dilakukan sebelum DML agar tidak meninggalkan perubahan sebagian.
Pemilik transaksi menentukan COMMIT atau ROLLBACK; handler tidak boleh sembarangan membatalkan pekerjaan pemanggil yang tidak terkait.
Exception saja juga tidak menggantikan constraint maupun mekanisme penguncian untuk sistem serentak.
06
RAISE_APPLICATION_ERROR dan pengujian batas
RAISE_APPLICATION_ERROR mengirim nomor kesalahan aplikasi dalam rentang -20000 sampai -20999 beserta pesan.
Contoh memvalidasi harga sebagai NUMBER tanpa skala lebih dahulu: tidak boleh NULL, harus positif, dan harus sama dengan ROUND(harga, 2). Deklarasi berskala sejak awal dapat membulatkan input sebelum diuji sehingga kelebihan desimal tidak terlihat.
Poin pembahasan
Subblok uji menangkap kesalahan yang diharapkan dengan SQLCODE dan mencetak SQLERRM; error berbeda dinaikkan lagi.
Untuk melihat kegagalan diteruskan ke client, jalankan contoh yang tidak mempunyai handler lokal secara terpisah.
Uji nilai nol, negatif, NULL, dua desimal dan desimal berlebih.
Kerjakan pada XE atau FreeSQL schema pribadi, catat keluaran aktual, dan jangan menyebut contoh tervalidasi Oracle jika belum benar-benar dijalankan.
Alur menyusun kontrol program
1Tentukan keputusan
2Pilih IF atau CASE
3Pilih pola loop bila perlu
4Definisikan handler yang tepat
5Uji normal, batas dan gagal
Gunakan alur ini sebagai panduan saat mengikuti praktikum; bukti hasil tetap berasal dari eksekusi Oracle Anda.
Amati data · ikuti langkah · pahami hasil
Contoh dan tabel pembahasan
Contoh berikut dibaca langsung, tanpa parameter atau tombol simulasi. Nilai adalah prediksi ilustratif dari data acuan, bukan hasil eksekusi pada akun Oracle Anda.
Melacak numeric FOR, bukan menebak hasil akhir
v_total dimulai dari 0. Setiap iterasi menambahkan nilai i ke accumulator.
Contoh SQL / PL/SQL
DECLARE
v_total PLS_INTEGER := 0;
BEGIN
FOR i IN 1..5 LOOP
v_total := v_total + i;
DBMS_OUTPUT.PUT_LINE(i || ' -> ' || v_total);
END LOOP;
END;
/
Iterasi i
v_total setelah penambahan
1
1
2
3
3
6
4
10
5
15
Cara membaca contoh
FOR i IN 1..5 memberikan lima nilai indeks pada contoh ini.
Perbarui accumulator setelah membaca nilai indeks.
Bedakan alur loop normal dari contoh exception; ZERO_DIVIDE harus memiliki pembagian dengan nol sebagai penyebabnya.
Yang perlu dipahami: Jejak langkah membantu menemukan kesalahan off-by-one dan penempatan assignment.
Video pembelajaran
Video utama — fokus bab ini
IF/ELSE, CASE dan loop Oracle PL/SQL; referensi kedua melengkapi exception handling.
Batas cakupan dan panduan menonton: Menggantikan video CASE saja. Custom exception dan RAISE_APPLICATION_ERROR tetap mengikuti contoh serta pengujian pada halaman.
Video merupakan pendamping, bukan pengganti keseluruhan bab. Pemeriksaan relevansi memakai transkrip yang tersedia, deskripsi pembuat dan bab waktu; bukan klaim seluruh durasi telah ditonton. Versi/editor atau bahasa dapat berbeda. Praktikum tetap mengikuti SQL/PLSQL Oracle pada halaman dan pilihan XE atau FreeSQL login. Jika pemutar dibatasi oleh YouTube, gunakan tautan Buka video.
Praktikum Oracle XE atau FreeSQL
Pilih salah satu lingkungan praktikum
Oracle XE: XE lokal dengan SQL Developer: cocok untuk instalasi, koneksi, user/schema, privilege, tablespace serta latihan SQL/PLSQL.
FreeSQL: FreeSQL dengan login: masuk menggunakan akun sendiri dan gunakan schema latihan yang diizinkan untuk SQL/PLSQL. Tidak perlu memasang XE untuk menyelesaikan latihan non-administratif.
Pengumpulan tugas menerima hasil dari salah satu lingkungan. Pastikan objek prasyarat tersedia dan tetap gunakan schema latihan, bukan schema produksi.
Output contoh adalah prediksi berdasarkan dataset, bukan bukti bahwa kode telah dijalankan pada akun Anda. Periksa koneksi, hak membuat objek, autocommit dan panel DBMS_OUTPUT. Slash pada baris sendiri adalah pemisah mode skrip klien tertentu, bukan statement PL/SQL.
Gunakan tabel pertemuan02 dan data pertemuan03 atau setup index sekali. Periksa keadaan data bila latihan sebelumnya pernah di-commit. Jangan menjalankan ulang CREATE TABLE/INSERT atau menghapus data secara buta.
Langkah 1 — IF, ELSIF dan nested IF
DECLARE
v_stok NUMBER := 20;
v_jumlah NUMBER := 2;
v_status VARCHAR2(12) := 'BARU';
BEGIN
IF v_jumlah IS NULL OR v_jumlah <= 0 THEN
DBMS_OUTPUT.PUT_LINE('Jumlah tidak valid');
ELSIF v_stok IS NULL THEN
DBMS_OUTPUT.PUT_LINE('Stok belum diketahui');
ELSIF v_jumlah > v_stok THEN
DBMS_OUTPUT.PUT_LINE('Stok kurang');
ELSE
IF v_status = 'BARU' THEN
DBMS_OUTPUT.PUT_LINE('Siap diperiksa');
ELSE
DBMS_OUTPUT.PUT_LINE('Status bukan BARU');
END IF;
END IF;
END;
/
Ubah nilai variabel untuk mencapai semua cabang. Kondisi NULL ditangani eksplisit, tidak diasumsikan TRUE atau FALSE.
Langkah 2 — Simple CASE dan searched CASE
DECLARE
v_status VARCHAR2(12) := 'LUNAS';
v_stok NUMBER := 0;
BEGIN
CASE v_status
WHEN 'BARU' THEN DBMS_OUTPUT.PUT_LINE('Menunggu proses');
WHEN 'LUNAS' THEN DBMS_OUTPUT.PUT_LINE('Pembayaran tercatat');
WHEN 'BATAL' THEN DBMS_OUTPUT.PUT_LINE('Dibatalkan');
ELSE DBMS_OUTPUT.PUT_LINE('Status tidak dikenali');
END CASE;
CASE
WHEN v_stok IS NULL THEN DBMS_OUTPUT.PUT_LINE('Stok tidak diketahui');
WHEN v_stok = 0 THEN DBMS_OUTPUT.PUT_LINE('Stok kosong');
WHEN v_stok < 10 THEN DBMS_OUTPUT.PUT_LINE('Stok rendah');
ELSE DBMS_OUTPUT.PUT_LINE('Stok mencukupi');
END CASE;
END;
/
Keduanya adalah CASE statement PL/SQL dan memakai END CASE, bukan sekadar ekspresi CASE pada SELECT.
Langkah 3 — Basic LOOP dengan EXIT WHEN dan EXIT
DECLARE
v_i PLS_INTEGER := 1;
BEGIN
LOOP
DBMS_OUTPUT.PUT_LINE('LOOP i=' || v_i);
EXIT WHEN v_i >= 3;
v_i := v_i + 1;
END LOOP;
v_i := 1;
LOOP
IF v_i > 2 THEN
EXIT;
END IF;
DBMS_OUTPUT.PUT_LINE('EXIT biasa i=' || v_i);
v_i := v_i + 1;
END LOOP;
END;
/
Batas dan perubahan penghitung terlihat jelas. EXIT biasa di dalam IF berbeda sintaks dengan EXIT WHEN.
Langkah 4 — WHILE LOOP dan numeric FOR LOOP
DECLARE
v_i PLS_INTEGER := 1;
BEGIN
WHILE v_i <= 3 LOOP
DBMS_OUTPUT.PUT_LINE('WHILE i=' || v_i);
v_i := v_i + 1;
END LOOP;
FOR k IN 1..3 LOOP
DBMS_OUTPUT.PUT_LINE('FOR k=' || k);
END LOOP;
FOR k IN REVERSE 1..3 LOOP
DBMS_OUTPUT.PUT_LINE('FOR turun k=' || k);
END LOOP;
END;
/
WHILE memeriksa sebelum badan; FOR menaikkan indeks otomatis dan REVERSE menurunkannya. Jangan assign ke indeks k.
Langkah 5 — Tiga exception bawaan dalam subblok
DECLARE
v_nama pelanggan_demo.nama%TYPE;
v_hasil NUMBER;
v_pembagi NUMBER := 0;
BEGIN
BEGIN
SELECT nama INTO v_nama FROM pelanggan_demo WHERE 1=0;
EXCEPTION
WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('Tidak ada pelanggan cocok');
END;
BEGIN
SELECT nama INTO v_nama FROM pelanggan_demo;
DBMS_OUTPUT.PUT_LINE('Hanya satu pelanggan pada schema ini');
EXCEPTION
WHEN TOO_MANY_ROWS THEN DBMS_OUTPUT.PUT_LINE('Lebih dari satu pelanggan');
WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('Tabel pelanggan kosong');
END;
BEGIN
v_hasil := 100 / v_pembagi;
DBMS_OUTPUT.PUT_LINE('Baris ini tidak dijalankan jika pembagi nol');
EXCEPTION
WHEN ZERO_DIVIDE THEN DBMS_OUTPUT.PUT_LINE('Pembagian dengan nol ditolak');
END;
DBMS_OUTPUT.PUT_LINE('Percobaan selesai pada blok luar');
END;
/
Seed menjamin kasus banyak pelanggan; query pertama selalu kosong dan pembagi nol selalu memicu ZERO_DIVIDE. Tidak ada klaim output telah dijalankan Oracle.
Langkah 6 — Custom exception dan RAISE eksplisit
DECLARE
e_stok_kurang EXCEPTION;
v_stok NUMBER := 2;
v_diminta NUMBER := 3;
BEGIN
IF v_diminta > v_stok THEN
RAISE e_stok_kurang;
END IF;
DBMS_OUTPUT.PUT_LINE('Stok memenuhi permintaan');
EXCEPTION
WHEN e_stok_kurang THEN
DBMS_OUTPUT.PUT_LINE('Permintaan ditolak: stok kurang');
END;
/
Handler menangani hanya custom exception ini. Pesan memenuhi permintaan tidak berjalan ketika RAISE dieksekusi.
Langkah 7 — RAISE_APPLICATION_ERROR: uji harga dua desimal
DECLARE
v_harga NUMBER;
BEGIN
FOR i IN 1..5 LOOP
v_harga := CASE i
WHEN 1 THEN 0
WHEN 2 THEN -1
WHEN 3 THEN NULL
WHEN 4 THEN 15000.25
ELSE 15000.251
END;
BEGIN
IF v_harga IS NULL OR v_harga <= 0 OR v_harga <> ROUND(v_harga,2) THEN
RAISE_APPLICATION_ERROR(-20001, 'Harga wajib positif dan maksimal dua desimal');
END IF;
DBMS_OUTPUT.PUT_LINE('Valid: ' || v_harga);
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -20001 THEN
DBMS_OUTPUT.PUT_LINE('Ditolak: ' || SQLERRM);
ELSE
RAISE;
END IF;
END;
END LOOP;
END;
/
NUMBER tanpa skala mempertahankan masukan desimal berlebih sampai validasi. Kasus yang valid tetap terlihat; handler menaikkan ulang error tak terduga, tanpa COMMIT atau ROLLBACK.
Langkah 8 — Kesalahan aplikasi diteruskan ke client
BEGIN
RAISE_APPLICATION_ERROR(-20002, 'Contoh kegagalan yang diteruskan ke pemanggil');
END;
/
Jalankan terpisah: error aplikasi memang diharapkan karena tidak ada handler lokal. Catat pesan aktual; jangan menganggap runner berhenti sebagai kesalahan bahan ajar.
Tugas / latihan
Pada XE ATAU FreeSQL schema pribadi, uji semua cabang IF/ELSIF/nested IF dan dua CASE; buat tabel kondisi input dan output aktual.
Tulis LOOP, WHILE dan FOR yang dibatasi jelas; gunakan EXIT serta EXIT WHEN, lalu jelaskan alasan loop berhenti.
Jalankan uji tiga exception bawaan, custom exception dan validasi RAISE_APPLICATION_ERROR. Sertakan kasus harga NULL, nol, negatif, dua desimal dan lebih dari dua desimal; tidak perlu mengubah tabel.
Pertanyaan analisis
Mengapa handler yang hanya mencetak berhasil lalu mengabaikan WHEN OTHERS berbahaya bagi pemanggil? Jelaskan kapan RAISE kembali diperlukan.
Mengapa NUMBER(12,2) pada variabel masukan dapat merusak uji deteksi desimal berlebih, dan bagaimana kontrak transaksi harus tetap dimiliki pemanggil?
Pengumpulan
Tugas boleh dikerjakan di Oracle XE lokal atau FreeSQL dengan login; cukup pilih salah satu. Kumpulkan satu laporan melalui LMS/kanal yang ditetapkan dosen. Cantumkan Nama, NPM, pertemuan dan lingkungan yang dipakai. Sertakan kode SQL/PLSQL sebagai teks, output aktual atau pesan error, serta jawaban analisis.
Jika FreeSQL menyediakan tautan berbagi yang dapat diakses dosen, tautan boleh ditambahkan sebagai bukti pendamping, bukan pengganti hasil eksekusi yang terdokumentasi. Jangan membagikan password, token atau koneksi pribadi.
Hasil yang belum dieksekusi diberi label “prediksi”. Screenshot ilustrasi browser bukan bukti praktikum Oracle.
Panduan XE21c digunakan untuk konteks instalasi lokal; dokumentasi SQL/PLSQL untuk konsep bahasa. Versi FreeSQL/editor dapat berbeda, sehingga periksa fitur dan pesan aktual.