PL/SQL Packages
Perlu kita ingat bersama, initialization part dari sebuah package hanya dijalankan sekali saja, saat pertama kali kita mereferensi kepada package tersebut. Jadi, di dalam contoh terakhir, hanya satu baris data yang ditambahkan ke dalam database table emp_audit. Demikian juga, variable number_hired diinisialisasi hanya sekali.
Setiap kali procedure hire_employee dipanggil, variabel number_hired di-update. Namun, perhitungan yang dipegang oleh number_hired bersifat spesifik terhadap session. Yaitu, perhitungan tersebut merefleksikan jumlah karyawan baru yang diproses oleh satu user, bukan jumlah yang diproses oleh seluruh user.
Dalam contoh berikutnya, kita mem-package-kan beberapa transaksi perbankan yang mirip. Mari kita asumsikan bahwa transaksi-transaksi debit dan kredit dimasukkan setelah jam-jam kerja melalui ATM (Automatic Teller Machine), kemudian diaplikasikan terhadap rekening pada keesokan harinya.
CREATE PACKAGE bank_transactions AS /* Declare externally visible constant. */ minimum_balance CONSTANT REAL := 100.00; /* Declare externally callable procedures. */ PROCEDURE apply_transactions; PROCEDURE enter_transaction ( acct INT, kind CHAR, amount REAL); END bank_transactions;
CREATE PACKAGE BODY bank_transactions AS
/* Declare global variable to hold transaction status. */
new_status VARCHAR2(70) := ’Unknown’;
/* Use forward declarations because apply_transactions
calls credit_account and debit_account, which are not
yet declared when the calls are made. */
PROCEDURE credit_account (acct INT, credit REAL);
PROCEDURE debit_account (acct INT, debit REAL);
/* Fully define procedures specified in package. */
PROCEDURE apply_transactions IS
/* Apply pending transactions in transactions table
to accounts table. Use cursor to fetch rows. */
CURSOR trans_cursor IS
SELECT acct_id, kind, amount FROM transactions
WHERE status = 'Pending'
ORDER BY time_tag
FOR UPDATE OF status; -- to lock rows
BEGIN
FOR trans IN trans_cursor LOOP
IF trans.kind = 'D' THEN
debit_account(trans.acct_id, trans.amount);
ELSIF trans.kind = 'C' THEN
credit_account(trans.acct_id, trans.amount);
ELSE
new_status := 'Rejected';
END IF;
UPDATE transactions SET status = new_status
WHERE CURRENT OF trans_cursor;
END LOOP;
END apply_transactions;
PROCEDURE enter_transaction ( /* Add a transaction to transactions table. */ acct INT, kind CHAR, amount REAL) IS BEGIN INSERT INTO transactions VALUES (acct, kind, amount, 'Pending', SYSDATE); END enter_transaction;
/* Define local procedures, available only in package. */
PROCEDURE do_journal_entry (
/* Record transaction in journal. */
acct INT,
kind CHAR,
new_bal REAL) IS
BEGIN
INSERT INTO journal
VALUES (acct, kind, new_bal, sysdate);
IF kind = 'D' THEN
new_status := 'Debit applied';
ELSE
new_status := 'Credit applied';
END IF;
END do_journal_entry;
PROCEDURE credit_account (acct INT, credit REAL) IS
/* Credit account unless account number is bad. */
old_balance REAL;
new_balance REAL;
BEGIN
SELECT balance INTO old_balance FROM accounts
WHERE acct_id = acct
FOR UPDATE OF balance; -- to lock the row
new_balance := old_balance + credit;
UPDATE accounts SET balance = new_balance
WHERE acct_id = acct;
do_journal_entry(acct, 'C', new_balance);
EXCEPTION
WHEN NO_DATA_FOUND THEN
new_status := 'Bad account number';
WHEN OTHERS THEN
new_status := SUBSTR(SQLERRM,1,70);
END credit_account;
PROCEDURE debit_account (acct INT, debit REAL) IS
/* Debit account unless account number is bad or
account has insufficient funds. */
old_balance REAL;
new_balance REAL;
insufficient_funds EXCEPTION;
BEGIN
SELECT balance INTO old_balance FROM accounts
WHERE acct_id = acct
FOR UPDATE OF balance; -- to lock the row
new_balance := old_balance - debit;
IF new_balance >= minimum_balance THEN
UPDATE accounts SET balance = new_balance
WHERE acct_id = acct;
do_journal_entry(acct, 'D', new_balance);
ELSE
RAISE insufficient_funds;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
new_status := 'Bad account number';
WHEN insufficient_funds THEN
new_status := 'Insufficient funds';
WHEN OTHERS THEN
new_status := SUBSTR(SQLERRM,1,70);
END debit_account;
END bank_transactions;
Dalam package ini, initialization part digunakan.
9.6. Private Versus Public Items dalam Packages
Marilah kita lihat kembali package emp_actions. Package body-nya mendeklarasikan sebuah variable bernama number_hired, yang diinisialisasi dengan nol. Tidak seperti item-item yang di deklarasikan di dalam spec dari emp_actions, item-item yang dideklarasikan di dalam body tersebut terbatas untuk digunakan di dalam package tersebut. Dengan demikian, PL/SQL code di luar package tersebut tidak dapat mereferensi variable number_hired. Item-item seperti ini disebut private.
Namun, item-item yang dideklarasikan di dalam spec dari emp_actions, seperti halnya exception invalid_salary, terlihat dari luar package. Dengan demikian, sebuah PL/SQL code dapat mereferensi terhadap exception invalid_salary tersebut. Item-item seperti ini disebut public.
Ketika kita harus memelihara item-item melalui sebuah session atau diantara transaksi-transaksi, kita letakkan mereke di dalam declarative part dari package body tersebut. Sebagai contoh, nilai dari number_hired ialah tetap diantara pemanggilan terhadap hire_employee di dalam session yang sama. Nilai tersebut akan hilang ketika session tersebut berakhir.
Jika kita harus membuat item-item menjadi public, kita letakkan mereka di dalam package spec. Sebagai contoh, konstanta minimum_balance yang di deklarasikan di dalam spec dari package bank_transactions tersedia untuk digunakan secara umum.
| Buku ini membahas berbagai macam tip dan trik yang sangat berguna bagi Anda pembaca pengguna database Oracle. Pemula, mahasiswa, programmer, maupun database administrator yang mengharapkan solusi cepat dalam menangani permasalahan-permasalahan dalam penggunaan database Oracle dapat membaca buku ini. Anda tidak harus membaca buku ini secara urut karena buku ini di susun berdasarkan topik permasalahan, dan Anda dapat membaca topik-topik yang sesuai dengan permasalahan yang Anda hadapi. Dapat di beli di toko buku Gramedia, Gunung Agung, Uranus, Karisma dsb. Harga Rp. 24.800,- (157 halaman) |


[…] Silahkan melanjutkan membaca pembahasan PL/SQL Packages […]