Wednesday, July 15, 2026

 

Package vs Procedure: Kapan Sebaiknya Pakai yang Mana?

Kalau baru mulai belajar PL/SQL, biasanya kita sering membuat procedure.

Wajar sih.

Procedure:

  • Mudah dibuat
  • Mudah diuji
  • Cocok untuk kebutuhan kecil

Tapi setelah beberapa tahun bekerja, saya mulai sering bertemu dengan package.

Dan jujur saja, dulu saya sempat bingung:

"Kalau procedure sudah jalan, kenapa harus pakai package?"


Awalnya Semua Terlihat Sama

Misalnya ada procedure sederhana:

CREATE OR REPLACE PROCEDURE update_salary (
  p_emp_id NUMBER,
  p_amount NUMBER
)
IS
BEGIN
  UPDATE employees
     SET salary = salary + p_amount
   WHERE employee_id = p_emp_id;
END;
/

Tidak ada yang salah.

Procedure ini:

  • Mudah dipanggil
  • Mudah dibaca
  • Mudah dipahami

Masalah Mulai Muncul Saat Program Bertambah

Beberapa bulan kemudian biasanya muncul:

  • Procedure update gaji
  • Procedure hitung bonus
  • Procedure validasi data
  • Function cek grade karyawan
  • Function hitung pajak

Jumlah object mulai banyak.

Lalu muncul pertanyaan:

"Procedure ini masih satu kelompok dengan yang mana ya?"


Di Sini Package Mulai Berguna

Misalnya:

CREATE OR REPLACE PACKAGE employee_pkg AS

  PROCEDURE update_salary(
    p_emp_id NUMBER,
    p_amount NUMBER);

  FUNCTION get_bonus(
    p_emp_id NUMBER)
    RETURN NUMBER;

END employee_pkg;
/

Sekarang semuanya punya rumah yang sama.

Saat melihat:

employee_pkg.update_salary(...)
employee_pkg.get_bonus(...)

Kita langsung tahu:

"Oh, ini fungsi yang berhubungan dengan employee."


Keuntungan yang Paling Saya Rasakan

Bukan soal performa dulu.

Yang paling terasa justru:

1. Lebih Mudah Dicari

Kalau ada masalah terkait employee:

Saya langsung buka:

employee_pkg

Tidak perlu mencari puluhan procedure terpisah.


2. Kode Lebih Terorganisir

Project besar biasanya hidup bertahun-tahun.

Kalau semua object berdiri sendiri:

  • Sulit dirawat
  • Sulit dicari
  • Sulit dipahami developer baru

Package membantu menjaga kerapihan.


3. Shared Variable dan Logic

Ini salah satu fitur yang dulu jarang saya manfaatkan.

Package bisa memiliki variable yang digunakan bersama oleh beberapa procedure atau function di dalamnya.

Tidak selalu diperlukan.

Tapi untuk kasus tertentu sangat membantu.


Apakah Procedure Sudah Tidak Perlu?

Tentu masih perlu.

Saya pribadi masih membuat procedure biasa untuk:

  • Script sederhana
  • Utility kecil
  • Pekerjaan sekali pakai
  • Proof of concept

Tidak semua hal harus dimasukkan ke package.


Catatan Pengalaman Kerja

Di salah satu project lama, jumlah procedure sudah ratusan.

Saat ada bug:

  • Nama object mirip-mirip
  • Sulit mengetahui hubungan antar program
  • Waktu debugging jadi lebih lama

Setelah banyak logic dipindahkan ke package:

  • Struktur lebih jelas
  • Developer baru lebih cepat memahami sistem
  • Maintenance lebih nyaman

Prinsip yang Saya Pakai Sekarang

Kalau logic:

  • Kecil
  • Berdiri sendiri
  • Tidak berkembang

Saya pakai procedure biasa.

Kalau logic:

  • Satu domain yang sama
  • Banyak function terkait
  • Akan terus berkembang

Saya mulai mempertimbangkan package.


Penutup

Dulu saya mengira package itu cuma "wadah procedure".

Setelah beberapa tahun bekerja, saya sadar:

Package bukan soal gaya coding.

Tapi soal menjaga kode tetap masuk akal ketika sistem semakin besar.

Dan semakin lama saya bekerja dengan Oracle, semakin sering saya menghargai kode yang mudah dirawat dibanding kode yang sekadar berjalan.

Sampai catatan Rabu berikutnya 👋

Wednesday, February 25, 2026

 Ini topik yang kelihatannya dasar,

tapi jujur… saya dulu sering kepleset di sini.

Kodenya jalan.
Tidak error.
Tapi hasilnya tidak sesuai harapan.


Contoh Kasus yang Sering Terjadi

DECLARE v_total NUMBER := 0; BEGIN FOR i IN 1..5 LOOP DECLARE v_total NUMBER := 10; BEGIN v_total := v_total + i; END; END LOOP; DBMS_OUTPUT.PUT_LINE(v_total); END;

Di kepala saya dulu:

“v_total akan bertambah terus.”

Hasilnya?
👉 tetap 0.


Kenapa Bisa Begitu?

Karena ada dua v_total berbeda:

  • Satu di blok luar

  • Satu lagi di blok dalam

Variabel di blok dalam:

  • Menimpa nama

  • Tapi tidak mengubah variabel luar

Ini bukan bug.
Ini cara kerja scope.


Kesalahan yang Dulu Sering Saya Lakukan

Saya sering:

  • Pakai nama variabel yang sama

  • Bikin blok DECLARE kecil tanpa sadar

  • Lalu bingung kenapa nilainya “nggak nyampe keluar”

Dan ini sering kejadian di:

  • Loop

  • Exception

  • Sub-block kecil


Versi yang Lebih Aman

Biasanya saya sekarang:

  • Deklarasi variabel di level atas

  • Hindari DECLARE tambahan kecuali perlu

DECLARE v_total NUMBER := 0; BEGIN FOR i IN 1..5 LOOP v_total := v_total + i; END LOOP; DBMS_OUTPUT.PUT_LINE(v_total); END;

Lebih jelas.
Lebih minim kejutan.


Catatan Pengalaman Kerja

Di satu debugging, saya pernah:

  • Fokus ke query

  • Fokus ke logic

  • Padahal masalahnya cuma scope variabel

Begitu sadar:

“Oh… ini variabel yang beda.”

Debug selesai dalam 2 menit.


Prinsip Sederhana yang Saya Pakai Sekarang

Kalau hasil aneh tapi:

  • Tidak ada error

  • Logic kelihatannya benar

Saya langsung cek:

  1. Scope variabel

  2. Apakah ada blok DECLARE tersembunyi

  3. Nama variabel yang sama

Sering kali jawabannya ada di situ.


Penutup

PL/SQL itu bahasa yang rapi,
tapi tetap punya jebakan kecil.

Variable scope mungkin kelihatan sepele,
tapi bisa bikin logika melenceng jauh.

Sampai catatan Rabu berikutnya 👋

Wednesday, February 18, 2026

 


Kalau sudah lama main PL/SQL, pasti familiar dengan ini:

EXCEPTION WHEN OTHERS THEN NULL; END;

Kelihatan rapi.
Tidak error.
Procedure “aman”.

Tapi justru di situlah masalahnya.


Kenapa WHEN OTHERS Sering Dipakai?

Jawaban jujurnya:

  • Biar nggak error

  • Biar job tidak gagal

  • Biar user tidak komplain

Dan saya juga dulu sering pakai.
Sampai suatu hari… kena batunya.


Kasus Nyata

Ada job malam:

  • Tidak pernah gagal

  • Log bersih

  • Tapi data tidak lengkap

Setelah dicek:

  • Ada error constraint

  • Tapi tertelan oleh WHEN OTHERS THEN NULL

Job dianggap sukses.
Data diam-diam rusak.

Dan ini yang paling berbahaya.


Contoh Pola Berbahaya

BEGIN INSERT INTO orders_backup SELECT * FROM orders; EXCEPTION WHEN OTHERS THEN NULL; END;

Kalau gagal:

  • Tidak ada pesan

  • Tidak ada log

  • Tidak ada yang tahu

Kecuali… user komplain keesokan harinya.


WHEN OTHERS yang Lebih Bertanggung Jawab

Kalau memang harus pakai WHEN OTHERS,
minimal lakukan ini:

EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLERRM); RAISE; END;

Atau simpan ke tabel log:

EXCEPTION WHEN OTHERS THEN INSERT INTO error_log (error_date, error_message) VALUES (SYSDATE, SQLERRM); RAISE; END;

Sekarang:

  • Error tetap tercatat

  • Job tetap jujur gagal

  • Debugging jauh lebih mudah


Kapan WHEN OTHERS Masih Masuk Akal?

Ada kasus tertentu, misalnya:

  • Cleanup process

  • Logging tambahan

  • Error non-kritis yang memang boleh dilewati

Tapi tetap:

  • Jangan kosong

  • Selalu ada jejak


Kebiasaan Lama yang Saya Tinggalkan

Dulu saya sering mikir:

“Yang penting nggak error.”

Sekarang saya lebih takut:

“Error tapi nggak ketahuan.”

PL/SQL itu bukan cuma soal jalan,
tapi soal kejujuran sistem.


Prinsip Pribadi Sekarang

Kalau lihat kode:

  • WHEN OTHERS THEN NULL

Saya langsung bertanya:

  1. Error apa yang mau disembunyikan?

  2. Apa dampaknya kalau error ini terjadi?

  3. Siapa yang tahu kalau ini gagal?

Kalau tidak ada jawaban jelas,
biasanya kode itu perlu diubah.


Penutup

WHEN OTHERS itu alat terakhir,
bukan jalan pintas.

Lebih baik job gagal dengan jelas
daripada sukses tapi bohong.

Sampai catatan Rabu berikutnya 👋

Wednesday, February 11, 2026

 Kalau sudah lama ngoding PL/SQL, cursor itu terasa “alami”.

Rapi, terstruktur, dan kelihatan profesional.

Masalahnya… tidak selalu perlu.


Contoh Pola yang Dulu Sering Saya Pakai

FOR rec IN ( SELECT employee_id, salary FROM employees ) LOOP DBMS_OUTPUT.PUT_LINE(rec.employee_id || ' - ' || rec.salary); END LOOP;

Tidak salah.
Tapi sering kali overkill.


Kasus Nyata

Di satu proses report:

  • Datanya ribuan

  • Hasilnya cuma dipindahkan ke tabel lain

Tetap pakai cursor + loop.

Hasilnya:

  • Jalan

  • Tidak error

  • Tapi lambat


Alternatif yang Lebih Sederhana

Kalau tujuannya cuma memindahkan atau memproses data massal:

INSERT INTO report_table (employee_id, salary) SELECT employee_id, salary FROM employees;

Tanpa loop.
Tanpa cursor.
Lebih ramah performa.


Kapan Cursor Masih Masuk Akal?

Cursor masih penting kalau:

  • Ada logic kompleks per baris

  • Banyak IF / kondisi khusus

  • Proses per record memang beda-beda

Tapi kalau:

  • Logic sama

  • Datanya banyak

  • Bisa diselesaikan SQL

Cursor biasanya bukan pilihan terbaik.


Kesalahan yang Dulu Sering Saya Lakukan

Saya dulu sering mikir:

“Kalau pakai cursor, berarti lebih aman.”

Padahal:

  • Aman ≠ efisien

  • Rapi ≠ cepat

Setelah beberapa kali kena masalah performa,
saya mulai biasakan:

SQL dulu, cursor belakangan.


Prinsip Sederhana yang Sekarang Saya Pakai

Sebelum pakai cursor, saya selalu tanya:

  1. Bisa pakai satu SQL?

  2. Perlu loop?

  3. Datanya besar atau kecil?

Kalau jawabannya:

  • Bisa SQL

  • Tidak perlu loop

  • Data besar

👉 cursor saya coret.


Penutup

Cursor bukan musuh.
Tapi juga bukan solusi untuk semua hal.

PL/SQL itu soal memilih alat yang pas,
bukan sekadar yang paling familiar.

Sampai catatan Rabu berikutnya 👋

Wednesday, February 4, 2026

 Ini salah satu kebiasaan lama yang sering “lolos review”.

Procedure:

  • Jalan normal

  • Tidak error

  • Bahkan terasa aman

Padahal… dampaknya bisa panjang.


Contoh yang Sering Saya Temui

FOR rec IN ( SELECT order_id FROM orders WHERE status = 'NEW' ) LOOP UPDATE orders SET status = 'PROCESS' WHERE order_id = rec.order_id; COMMIT; END LOOP;

Secara logika:

  • Setiap data langsung disimpan

  • Kalau gagal, yang lain sudah aman

Secara sistem:
👉 ini mimpi buruk performa


Kenapa COMMIT di Loop Itu Bermasalah?

Setiap COMMIT:

  • Menulis redo log

  • Melepas undo

  • Sinkron ke disk

Kalau loop:

  • 1.000 baris → 1.000 COMMIT

  • 10.000 baris → 10.000 COMMIT

Tidak heran kalau:

  • I/O naik

  • Session lain melambat

  • Database terasa “berat”

Dan tidak ada error sama sekali.


“Tapi Saya Takut Datanya Setengah Jalan…”

Ini alasan paling sering.

Dan memang valid dalam kasus tertentu.

Tapi sebelum taruh COMMIT di loop, tanyakan dulu:

  1. Apakah datanya benar-benar besar?

  2. Apakah bisa di-rollback bersama?

  3. Apakah failure-nya sering?

Sering kali jawabannya: tidak.


Pola yang Lebih Aman

Kalau memungkinkan:

FOR rec IN ( SELECT order_id FROM orders WHERE status = 'NEW' ) LOOP UPDATE orders SET status = 'PROCESS' WHERE order_id = rec.order_id; END LOOP; COMMIT;

Atau lebih baik lagi:

UPDATE orders SET status = 'PROCESS' WHERE status = 'NEW'; COMMIT;

Satu commit.
Lebih bersih.
Lebih ringan.


Kapan COMMIT di Loop Masih Masuk Akal?

Ada, tapi jarang.

Biasanya kalau:

  • Proses sangat panjang (jam-an)

  • Data independen per baris

  • Failure sebagian masih bisa diterima

Dan itupun:

  • Commit per batch (misalnya tiap 1.000 baris)

  • Bukan setiap baris


Catatan Pengalaman Kerja

Saya pernah menemukan job malam yang:

  • Tidak pernah error

  • Tapi membuat backup melambat

Setelah dicek:

  • Ada COMMIT di loop

  • Data puluhan ribu

Setelah diubah:

  • Commit per batch

  • Waktu eksekusi turun drastis

  • Beban server lebih stabil


Prinsip yang Saya Pegang Sekarang

Kalau lihat:

  • COMMIT di loop
    dan

  • Data bukan kecil

Saya langsung curiga.

Bukan salah,
tapi sering tidak perlu.


Penutup

COMMIT itu penting,
tapi tempatnya juga penting.

PL/SQL bukan cuma soal “jalan atau tidak”,
tapi soal bagaimana dampaknya ke sistem.

Sampai catatan Rabu berikutnya 👋

Popular Posts