Dasar-dasar PL/SQL
Pada pembahasan sebelumnya kita telah mengenal sedikit banyak tentang PL/SQL. Pembahasan kali ini fokus kepada aspek-aspek skala-kecil dari PL/SQL, yaitu dasar-dasar PL/SQL. Seperti setiap bahasa pemrograman lainnya, PL/SQL memiliki character set (kumpulan karakter), reserved words (kata-kata yang telah dipesan dan tidak boleh kita gunakan, misalnya: procedure, function, dsb), tanda baca, tipe-tipe data, sintaks tertentu, dan aturan yang tetap dalam hal penggunaan dan formasi penulisan sintaks. Kita menggunakan elemen-elemen dasar dari PL/SQL untuk merepresentasikan objek-objek di dunia nyata serta operasi-operasinya.
Kali ini kita akan membahas topik-topik berikut ini:
- Character Set
- Lexical Units
- Declarations
- PL/SQL Naming Conventions
- Scope and Visibility of PL/SQL Identifiers
- Variable Assignment
- PL/SQL Expressions and Comparisons
- Built-In Functions
2.1. Character Set
Kita menulis program PL/SQL dalam baris teks dengan menggunakan kumpulan karakter tertentu. Kumpulan karakter PL/SQL terdiri dari:
- the upper- and lower-case letters A .. Z and a .. z
- the numerals 0 .. 9
- the symbols ( ) + - * / < > = ! ~ ^ ; : . ’ @ % , ” # $ & _ | { } ? [ ]
- tabs, spaces, and carriage returns
PL/SQL tidak case-sensitive, sehingga huruf kecil sama dengan huruf besar kecuali di dalam string atau character literals.
2.2. Lexical Units
Baris teks PL/SQL mengandung kumpulan-kumpulan karakter yang disebut dengan lexical units, dimana dapat diklasifikasikan menjadi:
- delimiters (simbol sederhana atau gabungan)
- identifiers, which include reserved words (identifier dan kata-kata yang telah dipesan oleh PL/SQL)
- literals
- comments (komentar)
Untuk meningkatkan kemudahan pembacaan, kita dapat memisahkan lexical units dengan spasi. Pada kenyataannya, kita harus memisahkan identifier-identifier yang berdekatan dengan spasi atau tanda baca. Baris berikut ini tidak diperbolehkan karena reserved words END dan IF digabung:
IF x > y THEN high := x; ENDIF; -- tidak diperbolehkan
Namun, kita tidak bisa menyertakan spasi di dalam lexical units kecuali untuk string literals dan komentar. Sebagai contoh, baris berikut ini tidak diperbolehkan karena gabungan simbol assignment (:=) dipisah:
count : = count + 1; -- tidak diperbolehkan
Untuk menunjukkan struktur, kita dapat memecah baris-baris dengan menggunakan enter dan baris-baris yang menjorok ke dalam dengan menggunakan spasi atau tab. Bandingkan kemudahaan pembacaan dari kedua perintah-perintah IF berikut ini:
IF x>y THEN max:=x; ELSE max:=y; END IF;
atau
IF x > y THEN max := x; ELSE max := y; END IF;
2.2.1. Delimiters
Delimiter adalah simbol sederhana atau gabungan yang memiliki arti khusus bagi PL/SQL. Sebagai contoh, kita dapat menggunakan delimiters untuk merepresentasikan operasi-operasi aritmatika seperti penjumlahan dan pengurangan. Simbol sederhana terdiri dari satu karakter. Daftarnya adalah sebagai berikut:
+ addition operator
% attribute indicator
‘ character string delimiter
. component selector
/ division operator
( expression or list delimiter
) expression or list delimiter
: host variable indicator
, item separator
* multiplication operator
” quoted identifier delimiter
= relational operator
< relational operator
> relational operator
@ remote access indicator
; statement terminator
- subtraction/negation operator
Simbol gabungan terdiri dari dua karakter. Daftarnya adalah sebagai berikut:
:= assignment operator
=> association operator
|| concatenation operator
** exponentiation operator
<< label delimiter (begin)
>> label delimiter (end)
/* multi-line comment delimiter (begin)
*/ multi-line comment delimiter (end)
.. range operator
<> relational operator
!= relational operator
~= relational operator
^= relational operator
<= relational operator
>= relational operator
– single-line comment indicator
2.2.2. Identifiers
Kita menggunakan identifiers untuk menamai item-item dan unit-unit program PL/SQL, termasuk constants (konstanta), variables, exceptions, cursors, cursor variables, subprograms, dan packages. Beberapa contoh identifiers adalah sebagai berikut:
X t2 phone# credit_limit LastName oracle$number
Suatu identifier terdiri dari huruf yang secara opsional diikuti oleh huruf-huruf, angka-angka, simbol-simbol dollar, garis-garis bawah, dan tanda-tanda angka. Karakter-karakter lain seperti tanda penghubung, garis miring, dan spasi tidak diperbolehkan, seperti yang ditunjukkan oleh contoh-contoh di bawah ini:
mine&yours -- tidak diperbolehkan karena ampersand debit-amount -- tidak diperbolehkan karena hyphen on/off -- tidak diperbolehkan karena slash user id -- tidak diperbolehkan karena space
Contoh-contoh lain menunjukkan diperbolehkannya gabungan simbol dollar, garis bawah, dan tanda-tanda angka:
money$$$tree SN## try_again_
Kita dapat menggunakan huruf besar, huruf kecil, atau gabungan keduanya untuk menulis identifier. PL/SQL tidak case-sensitive kecuali di dalam string dan character literals. Jadi, jika perbedaan antara identifier-identifier hanyalah masalah besar kecilnya huruf, maka PL/SQL akan menganggapnya sama, seperti ditunjukkan oleh contoh berikut ini:
lastname LastName -- sama dengan lastname LASTNAME -- sama dengan lastname dan LastName
Ukuran sebuah identifier tidak dapat melebihi 30 karakter. Namun, setiap karakter, termasuk tanda dollar, garis bawah, dan tanda angka, memiliki arti tersendiri. Sebagai contoh, PL/SQL akan menganggap identifier-identifier berikut ini berbeda satu sama lain:
lastname last_name
Identifier sebaiknya deskriptif. Jangan menggunakan nama-nama yang tidak jelas, seperti cpm. Sebaiknya gunakan nama-nama yang memiliki arti seperti cost_per_thousand.
2.2.2.1. Reserved Words
Beberapa identifier, yang disebut dengan reserved words, memiliki arti khusus untuk PL/SQL, dan sebaiknya tidak kita definisikan ulang. Sebagai contoh, kata-kata BEGIN dan END, yang mana digunakan untuk menandai bagian executable dari suatu blok atau subprogram, merupakan reserved words. Seperti ditunjukkan oleh contoh berikut ini, jika kita berusaha mendefinisikan ulang reserved word, kita akan mendapatkan error:
DECLARE end BOOLEAN; -- tidak diperbolehkan; menyebabkan compilation error
Namun, kita dapat menyertakan reserved words di dalam sebuah identifier, seperti contoh berikut ini:
DECLARE end_of_game BOOLEAN; -- diperbolehkan
Seringkali, reserved words ditulis di dalam huruf besar untuk memudahkan pembacaan. Namun, seperti halnya identifier-identifier PL/SQL lainnya, reserved words dapat juga ditulis di dalam huruf kecil atau gabungan huruf kecil dan besar.
2.2.2.2. Predefined Identifiers
Identifiers yang secara global dideklarasikan di dalam package STANDARD, seperti halnya exception INVALID_NUMBER, dapat dideklarasikan ulang. Namun, mendeklarasikan ulang predefined identifiers merupakan kesalahan karena deklarasi lokal kita akan menolak deklarasi global.
2.2.2.3. Quoted Identifiers
Untuk fleksibilitas, PL/SQL mengijinkan kita untuk menutup identifiers dengan tanda petik dua. Quoted identifiers jarang dibutuhkan, namun sesekali mereka dapat berguna. Mereka dapat mengandung suatu sequence dari printable characters termasuk spasi, tetapi tidak termasuk tanda petik ganda. Sehingga, identifier-identifier berikut ini valid:
"X+Y" "last name" "on/off switch" "employee(s)" "*** header info ***"
Ukuran maksimum dari quoted identifier adalah 30 karakter tidak termasuk tanda petik ganda. Meskipun diperbolehkan, penggunaan reserved words PL/SQL yang diapit tanda petik ganda merupakan cara pemrograman yang buruk.
Beberapa reserved words PL/SQL bukan merupakan reserved words bagi SQL. Sebagai contoh, kita dapat menggunakan reserved words PL/SQL seperti TYPE di dalam perintah CREATE TABLE untuk menamai kolom pada database. Tetapi, jika perintah SQL pada program kita mengacu kepada kolom tersebut, kita akan mendapatkan pesan kesalahan, seperti ditunjukkan oleh contoh berikut ini:
SELECT acct, type, bal INTO ... -- menyebabkan compilation error
Untuk mencegah terjadinya kesalahan, apitlah kolom di dalam huruf kapital tersebut dengan tanda petik ganda, seperti contoh berikut:
SELECT acct, "TYPE", bal INTO ...
Nama kolom tidak dapat tampak dalam huruf kecil atau gabungan huruf kecil dan besar (kecuali ia dedefinisikan seperti itu dalam perintah CREATE TABLE). Sebagai contoh, perintah berikut adalah salah:
SELECT acct, "type", bal INTO ... -- menyebabkan compilation error
Alternatifnya, ktia dapat menciptakan view untuk mengubah nama-nama kolom yang bermasalah tersebut, dan kemudian menggunakan view tersebut, bukannya base table-nya di dalam perintah-perintah SQL.
2.2.3. Literals
Literal merupakan numerik, karakter, string, atau nilai Boolean eksplisit, yang tidak direpresentasikan oleh identifier. Literal numerik 147 dan literal Boolean FALSE adalah contohnya.
2.2.3.1. Numeric Literals
Dua jenis numeric literals dapat digunakan di dalam ekspresi-ekspresi aritmatika: integer dan real. Literal integer adalah angka tanpa tanda desimal, serta dapat bernilai positif atau negatif. Beberapa contohnya adalah:
030 6 -14 0 +32767
Literal real adalah angka dengan tanda desimal, serta dapat bernilai positif atau negatif. Beberapa contohnya adalah:
6.6667 0.0 -12.0 3.14159 +8300.00 .5 25.
PL/SQL menganggap angka-angka seperti 12.0 dan 25. sebagai real meskipun mereka memiliki nilai-nilai integer.
Literal-literal numerik tidak dapat mengandung tanda-tanda dollar atau koma, tetapi dapat ditulis dengan menggunakan notasi scientific. Secara sederhana kita dapat menambahkan angka dengan E (atau e) kemudian secara opsional dapat diikuti oleh tanda-tanda integer. Beberapa contohnya adalah:
2E5 1.0E-7 3.14159e0 -1E38 -9.5e-3
E berarti “sepuluh kali terhadap pangkat dari”. Seperti pada contoh berikut, angka setelah E merupakan pangkat dari 10 dimana angka sebelum E harus dikalikan (tanda asterisk ganda (** ) merupakan operator eksponensial):
5E3 = 5 * 10**3 = 5 * 1000 = 5000
Angka setelah E juga berkorespondensi terhadap jumlah tempat untuk poin desimal. Pada contoh terakhir, desimal poin implisit menempati tiga tempat ke kanan. Dalam contoh ini, ia menempati tiga tempat ke kiri:
5E-3 = 5 * 10**-3 = 5 * 0.001 = 0.005
Seperti ditunjukkan oleh contoh berikut ini, jika nilai literal numerik berkurang dan keluar dari jangkauan 1E-130 .. 10E125, kita akan mendapatkan pesan error.
DECLARE n NUMBER; BEGIN n := 10E127; -- menyebabkan error 'numeric overflow or underflow'
2.2.3.2. Character Literals
Literal karakter merupakan karakter individual yang diapit oleh tanda petik tunggal. Literal-literal karakter termasuk seluruh karakter cetak dalam kumpulan karakter PL/SQL: huruf-huruf, angka-angka, spasi-spasi, dan simbol-simbol khusus. Beberapa contohnya adalah:
'Z' '%' '7' ' ' 'z' '('
PL/SQL adalah case sensitive dalam literal-literal karakter. Sebagai contoh, PL/SQL menganggap bahwa literal-literal ‘Z’ dan ‘z’ adalah berbeda. Juga, literal-literal ‘0’..’9’ tidak sama dengan literal-literal integer tetapi dapat digunakan dalam ekspresi-ekspresi aritmatika karena mereka secara implisit dapat dikonversi menjadi integer.
2.2.3.3. String Literals
Nilai karakter dapat direpresentasikan oleh identifier atau seara eksplisit ditulis sebagai literal string, dimana terdiri dari nol atau lebih karakter-karakter yang diapit oleh tanda petik tunggal. Beberapa contohnya adalah:
'Hello, world!' 'XYZ Corporation' '10-NOV-91' 'He said "Life is like licking honey from a thorn."' '$1,000,000'
Seluruh literal-literal string kecuali string null (”) memiliki tipe data CHAR.
Telah dijelaskan bahwa tanda petik tunggal men-delimit literal-literal string, maka bagaimana kita merepresentasikan tanda petik tunggal di dalam string? Seperti ditunjukkan oleh contoh berikut ini, kita menulis dua tanda petik tunggal, yang mana tidak sama dengan jika kita menulis satu tanda petik ganda:
'Don''t leave without saving your work.'
PL/SQL adalah case sensitive di dalam literal-literal string. Sebagai contoh, PL/SQL menganggap literal-literal berikut ini berbeda satu sama lain:
'baker' 'Baker'
2.2.3.4. Boolean Literals
Literal boolean merupakan nilai predefined TRUE, FALSE, dan NULL (yang berarti nilai yang hilang, tidak diketahui, atau tidak dapat diaplikasikan). Harap diingat, literal-literal Boolean merupakan sebuah nilai, bukan string. Sebagai contoh, NULL bernilai tidak kurang dari angka 25.
2.2.3.5. Datetime Literals
Literal-literal datetime (tanggal dan waktu) memiliki banyak bentuk bergantung kepada tipe datanya. Sebagai contoh:
DECLARE d1 DATE := DATE '1998-12-25'; t1 TIMESTAMP := TIMESTAMP '1997-10-22 13:01:01'; t2 TIMESTAMP WITH TIME ZONE := TIMESTAMP '1997-01-31 09:26:56.66+02:00'; -- Tiga tahun dan dua bulan -- (Untuk presisi yang lebih besar, kita menggunakan day-to-second interval) i1 INTERVAL YEAR TO MONTH := INTERVAL '3-2' YEAR TO MONTH; -- Five days, four hours, three minutes, two and 1/100 seconds i2 INTERVAL DAY TO SECOND := INTERVAL '5 04:03:02.01' DAY TO SECOND; ...
Kita dapat juga menentukan apakah interval yang dibelikan adalah YEAR TO MONTH atau DAY TO SECOND. Sebagai contoh, current_timestamp – current_timestamp secara default akan menghasilkan nilai bertipe INTERVAL DAY TO SECOND. Kita dapat menentukan tipe interval dengan menggunakan bentuk-bentuk:
- (interval_expression) DAY TO SECOND
- (interval_expression) YEAR TO MONTH
2.2.4. Comments
PL/SQL compiler mengabaikan komentar-komentar, tetapi sebaiknya kita tidak. Menambahkan komentar pada program kita meningkatkan kemampuan pembacaan program dan membantu kita dalam mengerti alur sebuah program. Secara umum, kita menggunakan komentar-komentar untuk mendeskripsikan tujuan dan penggunaan dari setiap bagian program. PL/SQL mendukung dua bentuk komentar: single-line dan multi-line.
2.2.4.1. Single-Line Comments
Single-line comments diawali dengan tanda penghubung ganda (–) dimanapun dalam garis dan hingga akhir baris. Beberapa contohnya adalah sebagai berikut:
-- pemrosesan dimulai SELECT sal INTO salary FROM emp -- mendapatkan gaji terakhir WHERE empno = emp_id; bonus := salary * 0.15; -- menghitung total bonus
Perlu dicatat bahwa komentar-komentar dapat tampak di dalam perintah pada akhir baris.
Ketika kita mengetes dan men-debug program, kita mungkin ingin men-disable baris kode program. Contoh berikut ini menunjukkan bagaimana kita dapat membuat baris menjadi komentar:
-- DELETE FROM emp WHERE comm IS NULL;
2.2.4.2. Multi-line Comments
Multi-line comments diawali dengan slash-asterisk (/*), diakhiri dengan asterisk-slash (*/), dan dapat berupa beberapa baris. Beberapa contohnya adalah:
BEGIN
...
/* Menghitung bonus 15% untuk karyawan dengan rating tertinggi. */
IF rating > 90 THEN
bonus := salary * 0.15 /* bonus berdasarkan gaji */
ELSE
bonus := 0;
END IF;
...
/* Baris berikut ini menghitung luas lingkaran menggunan pi, yang mana merupakan area antara lingkar dan diameter. */ area := pi * radius**2; END;
Kita dapat menggunakan multi-line comment delimiters untuk mengubah seluruh bagian program menjadi komentar, seperti ditunjukkan oleh contoh berikut ini:
/* LOOP FETCH c1 INTO emp_rec; EXIT WHEN c1%NOTFOUND; ... END LOOP; */
2.2.4.3. Batasan-batasan Comments
Kita tidak dapat menyarangkan komentar-komentar. Juga, kita tidak dapat menggunakan single-line comments di dalam blok PL/SQL yang akan diproses secara dinamis oleh program Oracle Precompiler karena end-of-line characters akan diabaikan. Sebagai hasilnya, single-line comments menjangkau hingga akhir blok, tidak hanya hingga akhir baris. Sehingga, lebih baik kita menggunakan multi-line comments.
2.3. Declarations
Program yang kita buat menyimpan nilai-nilai di dalam variable dan konstanta. Ketika program dieksekusi, nilai variable dapat berubah, sedangkan nilai konstanta tetap.
Kita dapat mendeklarasikan variable dan konstanta di dalam bagian declarative pada setiap blok PL/SQL, subprogram, atau package. Deklarasi mengalokasikan space penyimpanan untuk nilai, menentukan tipe datanya, dan menamai lokasi penyimpanan sehingga kita dapat mereferensi terhadapnya. Beberapa contohnya adalah sebagai berikut:
birthday DATE; emp_count SMALLINT := 0;
Deklarasi pertama menamai variable dengan tipe DATE. Deklarasi kedua menamai variable dengan tipe SMALLINT dan menggunakan assignment operator untuk memberikan nilai inisial nol untuk variable.
Contoh-contoh berikut ini menunjukkan bahwa ekspresi yang mengikuti assignment operator dapat menjadi keputusan yang kompleks dan dapat merefer kepada variable yang telah diinisialisasi sebelumnya:
pi REAL := 3.14159; radius REAL := 1; area REAL := pi * radius**2;
Secara default, variable diinisialisasi dengan nilai NULL. Sehingga, deklarasi-deklarasi berikut ini adlaah sama:
birthday DATE; birthday DATE := NULL;
Pada deklarasi konstanta, keyword CONSTANT harus diletakkan sebelum tipe data, seperti ditunjukkan oleh contoh berikut ini:
credit_limit CONSTANT REAL := 5000.00;
Deklarasi ini menamai konstanta dengan tipe REAL dan memberikan nilai awal (yang juga merupakan nilai akhir) 5000. Konstanta harus diinisialisasi pada saat pendeklarasiannya. Jika tidak, kita akan mendapatkan pesan kesalahan ketika deklarasi dielaborasi. (Pemrosesan deklarasi oleh PL/SQL compiler disebut dengan elaboration).
2.3.1. Menggunakan DEFAULT
Kita dapat menggunakan keyword DEFAULT dibandingkan dengan menggunakan assignment operator untuk menginisialisasi variable. Sebagai contoh, deklarasi
blood_type CHAR := 'O';
dapat ditulis kembali menjadi:
blood_type CHAR DEFAULT 'O';
Gunakan DEFAULT untuk variable-variable yang memiliki nilai khusus. Gunakan assignment operator untuk variable-variable (seperti counter dan akumulator) yang tidak memiliki nilai khusus. Beberapa contohnya adalah:
hours_worked INTEGER DEFAULT 40; employee_count INTEGER := 0;
Kita dapat juga menggunakan DEFAULT untuk menginisialisasi parameter-parameter subprogram, parameter-parameter cursor, dan field-field dalam user-defined record.
2.3.2. Menggunakan NOT NULL
Disamping memberikan nilai awal, deklarasi dapat menentukan constraint NOT NULL, seperti ditunjukkan oleh contoh berikut:
acct_id INTEGER(4) NOT NULL := 9999;
Kita tidak dapat memberikan nilai null kepada variable yang telah didefinisikan sebagai NOT NULL. Jika kita mencobanya, PL/SQL akan menampilkan predefined exception VALUE_ERROR. Constraint NOT NULL harus diikuti oleh klausa inisialisasi. Sebagai contoh, deklarasi berikut ini tidak diperbolehkan:
acct_id INTEGER(5) NOT NULL; -- tidak diperbolehkan; tidak diinisialisasi
Dalam deklarasi NATURALN dan POSITIVEN, penentu tipe (type specifier) harus diikuti oleh klausa inisialisasi. Jika tidak, kita akan mendapatkan pesan kesalahan. Sebagai contoh, deklarasi berikut ini tidak diperbolehkan:
line_items POSITIVEN; -- tidak diperbolehkan; tidak diinisialisasi
2.3.3. Menggunakan %TYPE
Attribute %TYPE menyediakan tipe data untuk variable dan database column. Dalam contoh berikut, %TYPE menyediakan tipe data dari variable:
credit REAL(7,2); debit credit%TYPE;
Variable-variable yang dideklarasikan menggunakan %TYPE diperlakukan seperti variable-variable yang dideklarasikan menggunakan datatype specifier. Sebagai contoh, pada deklarasi sebelumnya, PL/SQL memperlakukan debit seperti variable bertipe data REAL(7,2). Contoh berikut ini menunjukkan bahwa deklarasi %TYPE dapat mengandung klausa inisialisasi:
balance NUMBER(7,2); minimum_balance balance%TYPE := 10.00;
Attribute %TYPE terutama sekali berguna ketika mendeklarasikan variable-variable yang mengacu kepada database column. Kita dapat mereferensi table dan column, atau kita dapat mereferensi owner, table, dan column, seperti pada contoh ini
my_dname scott.dept.dname%TYPE;
Menggunakan %TYPE untuk mendeklarasikan my_dname memiliki dua keuntungan. Pertama, tidak tidak perlu tahu tipe data sesungguhnya dari dname. Kedua, jika definisi database untuk dname berubah, tipe data my_dname berubah mengikuti perubahan dname.
Namun, variable-variable %TYPE tidak mewarisi constraint NOT NULL dari column yang diacunya. Dalam contoh berikutnya, meskipun database column empno didefinisikan sebagai NOT NULL, kita dapat memberikan nilai null kepada variable my_empno:
DECLARE my_empno emp.empno%TYPE; ... BEGIN my_empno := NULL; -- hal ini diperbolehkan dan dapat bekerja
2.3.4. Menggunakan %ROWTYPE
Attribute %ROWTYPE menyediakan tipe record yang merepresentasikan row (baris data) dalam table (atau view). Record dapat menyimpan seluruh baris data yang dipilih dari table atau dihasilkan dari cursor atau variable bertipe cursor. Dalam contoh berikut, kita mendeklarasikan dua record. Record pertama menyimpan baris data yang diambil dari table emp. Record kedua menyimpan baris data yang dihasilkan dari cursor c1.
DECLARE emp_rec emp%ROWTYPE; CURSOR c1 IS SELECT deptno, dname, loc FROM dept; dept_rec c1%ROWTYPE;
Kolom-kolom dalam baris data dan field-field terkait di dalam record memiliki nama dan tipe data yang sama. Namun, field-field di dalam record %ROWTYPE tidak mewarisi constraint NOT NULL pada column.
Dalam contoh berikut ini, kita menampilkan nilai-nilai kolom ke dalam record emp_rec:
BEGIN SELECT * INTO emp_rec FROM emp WHERE ...
Nilai-nilai column yang dihasilkan oleh perintah SELECT disimpan pada field-field. Untuk merefer field, kita menggunakan dot notation (.). Sebagai contoh, kita dapat merefer field deptno dengan cara berikut:
IF emp_rec.deptno = 20 THEN ...
Kita juga dapat memberikan nilai dari ekspresi kepada field tertentu, seperti contoh berikut ini:
emp_rec.ename := 'JOHNSON'; emp_rec.sal := emp_rec.sal * 1.15;
Pada contoh terakhir berikut ini, kita menggunakan %ROWTYPE untuk mendefinisikan packaged cursor:
CREATE PACKAGE emp_actions AS CURSOR c1 RETURN emp%ROWTYPE; -- declare cursor specification ... END emp_actions; CREATE PACKAGE BODY emp_actions AS CURSOR c1 RETURN emp%ROWTYPE IS -- define cursor body SELECT * FROM emp WHERE sal > 3000; ... END emp_actions;
2.3.4.1. Aggregate Assignment
Deklarasi %ROWTYPE tidak dapat mengandung klausa inisialisasi. Namun, ada dua jalan untuk memberikan nilai-nilai ke seluruh field-field di dalam record sekali. Pertama, PL/SQL mengijinkan aggregate assignment diantara seluruh record-record jika deklarasi mereka merefer kepada table atau cursor yang sama. Sebagai contoh, proses pemberian nilai berikut ini diperbolehkan:
DECLARE
dept_rec1 dept%ROWTYPE;
dept_rec2 dept%ROWTYPE;
CURSOR c1 IS SELECT deptno, dname, loc FROM dept;
dept_rec3 c1%ROWTYPE;
BEGIN
...
dept_rec1 := dept_rec2;
Namun, karena dept_rec2 berbasiskan pada table dan dept_rec3 berbasiskan kepada cursor, assignment berikut ini tidak diperbolehkan:
dept_rec2 := dept_rec3; -- tidak diperbolehkan
Kedua, kita dapat memberikan nilai dari suatu daftar column kepada record dengan menggunakan perintah SELECT atau FETCH, seperti ditunjukkan oleh contoh berikut ini. Nama-nama column harus tampak pada urutan dimana mereka didefinisikan oleh perintah CREATE TABLE atau CREATE VIEW.
DECLARE dept_rec dept%ROWTYPE; ... BEGIN SELECT * INTO dept_rec FROM dept WHERE deptno = 30; ... END;
Namun, kita tidak dapat memberikan memberikan nilai kumpulan kolom kepada record dengan menggunakan perintah assignment. Jadi, sintaks berikut ini tidak diperbolehkan:
record_name := (value1, value2, value3, ...); -- tidak diperbolehkan
2.3.4.2. Menggunakan Aliases
Kumpulan item-item hasil dari cursor yang terasosiasi dengan %ROWTYPE harus memiliki nama yang sederhana, atau jika mereka adalah ekspresi, harus memiliki alias. Pada contoh berikut ini, kita menggunakan alias yang disebut wages:
DECLARE
CURSOR my_cursor IS
SELECT sal + NVL(comm, 0) wages, ename FROM emp;
my_rec my_cursor%ROWTYPE;
BEGIN
OPEN my_cursor;
LOOP
FETCH my_cursor INTO my_rec;
EXIT WHEN my_cursor%NOTFOUND;
IF my_rec.wages > 2000 THEN
INSERT INTO temp VALUES (NULL, my_rec.wages, my_rec.ename);
END IF;
END LOOP;
CLOSE my_cursor;
END;
2.3.5. Batasan-batasan Declarations
PL/SQL tidak memperbolehkan referensi kedepan (forward references). Kita harus mendeklarasikan variable atau konstanta sebelum menggunakannya pada perintah-perintah yang lain, termasuk perintah-perintah declarative lainnya. Sebagai contoh, deklarasi maxi berikut ini tidak diperbolehkan:
maxi INTEGER := 2 * mini; -- tidak diperbolehkan mini INTEGER := 15;
Namun, PL/SQL tidak memperbolehkan forward declaration dari subprogram.
Beberapa bahasa mengijinkan kita untuk mendeklarasikan daftar variable-variable yang memiliki tipe data yang sama. PL/SQL tidak mengijinkan hal ini. Sebagai contoh, deklarasi berikut ini tidak diperbolehkan:
i, j, k SMALLINT; -- tidak diperbolehkan
Kita harus mendeklarasikan setiap variable secara terpisah:
i SMALLINT; j SMALLINT; k SMALLINT;
2.4. PL/SQL Naming Conventions
Ketentuan penamaan yang sama berlaku untuk seluruh item-item dan unit-unit program PL/SQL termasuk konstanta, variable, cursor, cursor variable, exception, procedure, function, dan package. Nama dapat sederhana, memenuhi syarat, dari tempat lain, atau keduanya. Sebagai contoh, kita mungkin menggunakan procedure raise_salary dengan berbagai cara berikut:
raise_salary(...); -- simple emp_actions.raise_salary(...); -- qualified raise_salary@newyork(...); -- remote emp_actions.raise_salary@newyork(...); -- qualified and remote
Pada kasus pertama, kita secara sederhana menggunakan nama procedure. Kasus kedua, kita harus menentukan nama menggunakan dot notation karena procedure diletakkan di dalam package bernama emp_actions. Pada kasus ketiga, menggunakan remote access indicator (@), kita merefer database link newyork karena procedure terletak pada remote database. Sedangkan pada kasus keempat, kita mengguankan nama procedure dan merefer database link.
2.4.1. Synonyms
Kita dapat menciptakan synonym untuk menyediakan transparansi terhadap remote schema objects seperti table, sequence, view, standalone subprogram, package, dan object type. Namun, kita tidak dapat menciptakan synonym untuk item-item yang dideklarasikan di dalam subprogram atau package. Termasuk konstanta, variable, cursor, cursor variable, exception, dan subprogram ter-package.
2.4.2. Scoping
Didalam jangkauan yang sama, seluruh identifier yang dideklarasikan harus unik. Sehingga, meskipun tipe-tipe data mereka berbeda, variable-variable dan parameter-parameter tidak dapat berbagi nama yang sama. Pada contoh berikut ini, deklarasi kedua tidak diperbolehkan:
DECLARE valid_id BOOLEAN; valid_id VARCHAR2(5); -- tidak diperbolehkan adanya duplicate identifier
2.4.3. Case Sensitivity
Seperti hanya seluruh identifier, nama dari konstanta, variable, dan parameter tidak case-sensitive. Sebagai contoh, PL/SQL mengganggap nama-nama berikut adalah sama:
DECLARE zip_code INTEGER; Zip_Code INTEGER; -- same as zip_code
2.4.4. Name Resolution
Dalam kemungkinan adanya kerancuan perintah-perintah SQL, nama-nama kolom database memiliki hak lebih tinggi diatas nama-nama variable lokal dan parameter-parameter formal. Sebagai contoh, perintah DELETE berikut ini menghapus seluruh karyawan dari table emp, tidak hanya ‘KING’, karena Oracle mengasumsikan bahwa kedua enames di dalam klausa WHERE mengacu kepada kolom di database:
DECLARE ename VARCHAR2(10) := 'KING'; BEGIN DELETE FROM emp WHERE ename = ename; ...
Pada kasus seperti ini, untuk menghindari kerancuan, awali nama-nama dari variable lokal dan parameter-parameter format dengan my_. seperti contoh berikut ini:
DECLARE my_ename VARCHAR2(10);
Atau, gunakan label blok untuk mengkualifikasi referensi, seperti dalam
<<main>> DECLARE ename VARCHAR2(10) := 'KING'; BEGIN DELETE FROM emp WHERE ename = main.ename;
Contoh berikutnya menunjukkan bahwa kita dapat menggunakan nama subprogram untuk mengkualifikasi referensi ke variable-variable lokal dan parameter-parameter formal:
FUNCTION bonus (deptno IN NUMBER, ...) RETURN REAL IS job CHAR(10); BEGIN SELECT ... WHERE deptno = bonus.deptno AND job = bonus.job;
2.5. Scope dan Visibility dari PL/SQL Indentifiers
Referensi kepada identifier ditetapkan berdasarkan jangkauan dan jarak pandang. Scope dari identifier adalah pada daerah program unit (blok, subprogram, atau package) dari mana kita dapat mereferensi terhadap identifier tersebut. Identifier visible / tampak hanya di dalam daerah-daerah dari mana kita dapat mereferensi identifier tersebut menggunakan nama yang tidak terkualifikasi. Gambar 2-1 menunjukkan jangkauan dan jarak pandang dari variable bernama x, yang dideklarasikan di dalam blok yang menutupnya, lalu dideklarasikan ulang di dalam sub-blok.
Identifier-identifier yang dideklarasikan di dalam blok PL/SQL dianggap lokal terhadap blok dan global terhadap sub-blok-nya. Jika identifier global dideklarasikan ulang di dalam sub-blok, kedua identifier-identifier tersebut tetap di dalam jangkauan. Menyertai sub-blok, bagaimanapun juga, hanya identifier lokal yang terlihat, karena kita harus menggunakan nama yang terkualifikasi untuk merefer kepada identifier global.
Meskipun kita tidak dapat mendeklarasikan identifier dua kali di dalam blok yang sama, kita dapat mendeklarasikan identifier yang dama di dalam dua blok yang berbeda. Dua item yang direpresentasikan oleh identifier adalah berbeda, dan perubahan yang terjadi pada salah satunya tidak mempengaruhi yang lain. Namun, blok tidak dapat merefer identifier-identifier yang dideklarasikan di dalam blok-blok yang lain pada level yang sama karena identifier-identifier tersebut tidak lokal dan tidak juga global terhadap blok tersebut.

Gambar 2.1. Scope dan Visibility
Contoh berikut ini menggambarkan aturan-aturan jangkauan. Perlu diingat bahwa identifier-identifier yang dideklarasikan di dalam satu sub-blok tidak dapat direferensi atau digunakan di dalam sub-blok yang lain. Hal ini dikarenakan blok tidak dapat menggunakan atau mereferensi identifier-identifier di dalam blok-blok lain pada level yang sama.
DECLARE
a CHAR;
b REAL;
BEGIN
-- identifiers tersedia disini: a (CHAR), b
DECLARE
a INTEGER;
c REAL;
BEGIN
-- identifiers tersedia disini: a (INTEGER), b, c
END;
DECLARE
d REAL;
BEGIN
-- identifiers tersedia disini: a (CHAR), b, d
END;
-- identifiers tersedia disini: a (CHAR), b
END;
Pemanggilan kembali terhadap identifier-identifier global tersebut dapat dideklarasikan ulang di dalam sub-blok, yang pada akhirnya deklarasi lokal berlaku dan sub-blok tidak dapat mereferensi identifier global kecuali kita menggunakan nama yang terkualifikasi. Pengkualifikasi dapat berupa label dari blok yang menyertainya, seperti ditunjukkan oleh contoh berikut ini:
<<outer>>
DECLARE
birthdate DATE;
BEGIN
DECLARE
birthdate DATE;
BEGIN
...
IF birthdate = outer.birthdate THEN ...
END;
...
END;
Seperti ditunjukkan oleh contoh berikut ini, pengkualifikasi dapat juga berupa nama dari subprogram yang mengapitnya:
PROCEDURE check_credit (...) IS rating NUMBER; FUNCTION valid (...) RETURN BOOLEAN IS rating NUMBER; BEGIN ... IF check_credit.rating < 3 THEN ... END; BEGIN ... END;
Namun, di dalam jangkauan yang sama, label dan subprogram tidak dapat memiliki nama yang sama.
Oracle Magazine contains technology strategy articles, sample code, tips, Oracle and partner news, how to articles for developers and DBAs, and more. Oracle (NASDAQ: ORCL) is the world’s largest enterprise software company.
For more information about Oracle, please visit their Web site at http://www.oracle.com. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
2.6. Variable Assignment
Variable dan konstanta diinisialisasi setiap saat blok atau subprogram diinputkan. Secara default, variable diberi nilai awal NULL. Kecuali kita secara langsung memberikan nilai awal terhadap variable tersebut, nilainya tidak didefinisikan:
DECLARE count INTEGER; BEGIN -- COUNT dimulai dengan nilai NULL. -- Sehingga ekspresi 'COUNT + 1' juga null. -- Lalu setelah pemberian nilai ini, COUNT tetap NULL. count := count + 1;
Untuk menghindari hasil-hasil yang tidak diharapkan, jangan pernah mereferensi ke variable sebelum kita memberikan nilai kepadanya.
Kita dapat menggunakan perintah-perintah assignment untuk memberikan nilai ke variable. Sebagai contoh, perintah berikut ini memberikan nilai baru ke variable bonus, dan menimpa nilai lamanya:
bonus := salary * 0.15;
Ekspresi yang mengikuti operator assignment dapat menjadi kompleks, tetapi ia harus menghasilkan tipe data yang sama dengan atau dapat dikonversi ke tipe data dari variable.
2.6.1. Assigning Boolean Values
Hanya nilai-nilai TRUE, FALSE, dan NULL yang dapt diberikan ke variable bertipe Boolean. Sebagai contoh, deklarasi berikut ini
DECLARE done BOOLEAN;
perintah-perintah berikut ini diperbolehkan:
BEGIN done := FALSE; WHILE NOT done LOOP ... END LOOP;
Ketika diaplikasikan ke ekspresi, operator-operator relasional menghasilkan nilai Boolean. Sehingga pemberikan nilai berikut ini diperbolehkan:
done := (count > 500);
2.6.2. Assigning SQL Query Result to a PL/SQL Variable
Kita dapat menggunakan perintah SELECT untuk mengharuskan Oracle memberikan nilai-nilai ke variable. Untuk setiap item di dalam daftar select, mereka harus berkaitan, variable type-compatible di dalam INTO. Contohnya adalah sebagai berikut:
DECLARE emp_id emp.empno%TYPE; emp_name emp.ename%TYPE; wages NUMBER(7,2); BEGIN -- memberikan nilai terhadap emp_id disini SELECT ename, sal + comm INTO emp_name, wages FROM emp WHERE empno = emp_id; ... END;
Namun, kita tidak dapat menampilkan nilai-nilai kolom ke variable Boolean.
2.7. PL/SQL Expression and Comparisons
Ekspresi dibangun dengan menggunakan operand dan operator. Operand adalah variable, konstanta, literal, atau function call yang menambah nilai terhadap ekspresi. Contoh dari ekspresi aritmatika sederhana adalah sebagai berikut:
- X / 2 + 3
Operator-operator unary seperti negation operator (-) beroperasi pada satu operand; operator-operator binary seperti division operator (/) beroperasi pada dua operand. PL/SQL tidak memiliki operator-operator ternary.
Ekspresi-ekspresi paling sederhana terdiri dari variable tunggal, yang menghasilkan nilai secara langsung. PL/SQL mengevaluasi (menemukan nilai terkini dari) ekspresi dengan mengkombinasikan nilai-nilai dari operand dengan jalan yang ditentukan oleh operator-operator. Hal ini selalu menghasilkan nilai dan tipe data tunggal. PL/SQL menentukan tipe data dengan memeriksa ekspresi dan konteks dimana ia muncul.
Operator Precedence
Operasi-operasi di dalam ekspresi terjadi dalam perintah khusus bergantung kepada prioritasnya. Table 2-1 menunjukkan perintah default dari operasi-operasi dari awal sampai akhir (dari atas ke bawah).

Table 2-1 Urutan operasi
Operator-operator dengan prioritas lebih tinggi diaplikasikan pertama. Di dalam contoh di bawah ini, kedua ekspresi menghasilkan 8 karena pembagian memiliki prioritas lebih tinggi dibandingkan penjumlahan. Operator-operator dengan prioritas yang sama diaplikasikan di dalam urutan khusus.
5 + 12 / 4 12 / 4 + 5
Kita dapat menggunakan tanda kurung untuk mengontrol urutan evaluasi. Sebagai contoh, ekspresi berikut ini menghasilkan 7, bukan 11, karena tanda kurung mengesampingkan urutan prioritas default:
(8 + 6) / 2
Pada contoh berikutnya, pengurangan di dilakukan sebelum pembagian karena sub-ekspresi yang paling dalam selalu dievaluasi pertama kali:
100 + (20 / 5 + (7 - 3))
Contoh berikut ini menunjukkan bahwa kita dapat selalu menggunakan tanda-tanda kurung untuk meningkatkan keterbacaan, bahkan ketika mereka tidak diperlukan:
(salary * 0.05) + (commission * 0.25)
2.7.1. Logical Operators
Operator-operator logikal AND, OR, dan NOT mengikuti logika tiga keadaan yang ditunjukkan dalam Table 2-2. AND dan OR adalah operator-operator binary; sedangkan NOT adalah operator unary.

Table 2-2. Table Kebenaran
Seperti ditunjukkan oleh table kebenaran, AND menghasilkan TRUE hanya jika kedua operand-nya bernilai true. Sedangkan OR menghasilkan TRUE jika salah satu dari operand-nya bernilai true. NOT menghasilkan nilai kebalikan (negasi logikal) dari operand-nya. Sebagai contoh, NOT TRUE menghasilkan FALSE.
NOT NULL menghasilkan NULL karena null tidak dapat ditentukan.Bahkan jika kita mengaplikasikan operator NOT terhadap null, hasilnya juga tidak dapat ditentukan. Kita harus berhati-hati. Null dapat menyebabkan nilai-nilai yang tidak diharapkan.
2.7.1.1. Order or Evaluation
Ketika kita tidak menggunakan tanda kurung untuk menentukan urutan evaluasi, prioritas operator ditentukan oleh urutannya. Bandingkan ekspresi-ekspresi berikut ini:
NOT (valid AND done) | NOT valid AND done
Jika variable-variable Boolean valid dan done memiliki nilai FALSE, ekspresi pertama menghasilkan TRUE. Namun, ekspresi kedua menghasilkan FALSE because NOT memiliki prioritas lebih tinggi dibandingkan AND. Dengan demikian, ekspresi kedua sama dengan:
(NOT valid) AND done
Di dalam contoh berikut ini, perlu diingat bahwa ketika valid memiliki nilai FALSE, seluruh ekspresi menghasilkan FALSE tanpa memperhatikan nilai dari done.
valid AND done
Serupa dengan kasus diatas, dalam contoh berikut ini, ketika valid memiliki nilai TRUE, seluruh ekspresi menghasilkan TRUE tanpa memperhatikan nilai done:
valid OR done
2.7.1.2. Short-Circuit Evaluation
Ketika mengevaluasi ekspresi logika, PL/SQL menggunakan short-circuit evaluation. Jadi, PL/SQL menghentikan mengevaluasi ekspresi segera setelah hasilnya dapat ditentukan. Hal ini mengijinkan kita menulis ekspresi-ekspresi yang mungkin sebaliknya menyebabkan kesalahan. Perhatikan ekspresi OR berikut ini:
DECLARE
...
on_hand INTEGER;
on_order INTEGER;
BEGIN
..
IF (on_hand = 0) OR ((on_order / on_hand) < 5) THEN
...
END IF;
END;
Ketika nilai dari on_hand adalah nol, operand sebelah kiri menghasilkan TRUE, sehingga PL/SQL tidak perlu mengevaluasi operand kanan. Jika PL/SQL mengevaluasi kedua operand sebelum menerapkan operator OR, operand kanan akan menyebabkan error division by zero. Dalam beberapa kasus, merupakan praktek pemrograman yang buruk untuk mempercayakan pada evaluasi short-circuit.
2.7.1.3. Comparison Operators
Operator pembanding membandingkan satu ekspresi dengan lainnya. Hasilnya selalu true, false, atau null. Biasanya, kita menggunakan operator-operator pembanding di dalam perintah-perintah pengontrol kondisi di dalam klausa WHERE dari perintah-perintah manipulasi data SQL. Berikut ini beberapa contohnya:
IF quantity_on_hand > 0 THEN UPDATE inventory SET quantity = quantity - 1 WHERE part_number = item_number; ELSE ... END IF;
2.7.1.4. Relational Operators
Operator-operator relasional mengijinkan kita untuk membandingkan ekspresi-ekspresi kompleks. Daftar berikut ini menunjukkan arti dari setiap operator:
= sama dengan
<>, !=, ~=, ^= tidak sama dengan
< lebih kecil dari
> lebih besar dari
<= lebih kecil dari atau sama dengan
>= lebih besar dari atau sama dengan
2.7.1.5. IS NULL Operator
Operator IS NULL menghasilkan nilai Boolean TRUE jika operand-nya null atau FALSE jika ia bukan null. Perbandingan-perbandingan yang melibatkan null selalu menghasilkan NULL. Sehingga, selalu lakukan pengecekan, seperti berikut:
IF variable IS NULL THEN ...
2.7.1.6. LIKE Operator
Kita menggunakan operator LIKE untuk membandingkan nilai karakter, string, atau CLOB dengan sebuah pola. LIKE menghasilkan nilai Boolean TRUE jika pola-polanya sesuai atau FALSE jika tidak.
Pola-pola yang disesuaikan oleh LIKE dapat mengandung dua karakter bertujuan khusus yang disebut dengan wildcards. Tanda garis bawah (_) menyamakan secara tepat satu karakter; tanda persen (%) menyamakan nol atau lebih karakter. Sebagai contoh, jika nilai ename adalah ‘JOHNSON’, ekspresi berikut ini adalah benar:
ename LIKE 'J%SON'
2.7.1.7. BETWEEN Operator
Operator BETWEEN mengetes apakah suatu nilai berada dalam jangkauan yang telah ditetapkan. Hal ini berarti ”lebih besar dari atau sama dengan nilai rendah dan kurang dari atau sama dengan nilai tinggi”. Sebagai contoh, ekspresi berikut ini salah:
45 BETWEEN 38 AND 44
2.7.1.8. IN Operator
Operator IN memeriksa kumpulan keanggotaan. Hal ini berarti “sama dengan beberapa anggota dari.” Kumpulan tersebut dapat mengandung nilai-nilai null, tetapi mereka diabaikan. Sebagai contoh, perintah berikut tidak menghapus baris-baris dimana kolom ename adalah null:
DELETE FROM emp WHERE ename IN (NULL, 'KING', 'FORD');
Selanjutnya, ekspresi dari bentuk
value NOT IN set
menghasilkan FALSE jika set mengandung null. Sebagai contoh, bukannya menghapus baris di mana kolom ename tidak null dan tidak ‘KING’ , perintah berikut tidak menghapus apa-apa:
DELETE FROM emp WHERE ename NOT IN (NULL, 'KING');
2.7.1.9. Concatenation Operator
Garis vertikal ganda (||) berlaku sebagai operator penggabungan, yang menambahkan satu string (CHAR, VARCHAR2, CLOB, atau tipe Unicode-enabled yang serupa) kepada lainnya. Sebagai contoh, ekspresi
'suit' || 'case'
Menghasilkan nilai berikut:
'suitcase'
Jika kedua operand memiliki tipe data CHAR, operator penggabungan menghasilkan nilai CHAR. Jika salah satu operand bernilai CLOB, operator menghasilkan CLOB sementara (temporary CLOB). Sebaliknya, operator menghasilkan nilai VARCHAR2.
2.7.2. Boolean Expressions
PL/SQL mengijinkan kita untuk membandingkan variable-variable dan konstanta-konstanta baik melalui SQL maupun melalui perintah-perintah prosedural. Perbandingan-perbandingan ini, yang disebut Boolean expressions, terdiri dari ekspresi-ekspresi sederhana atau kompleks yang dipisahkan oleh operator-operator relasional. Seringkali, ekspresi-ekspresi Boolean dihubungkan oleh operator-operator logikal AND, OR, dan NOT. Ekspresi Boolean selalu menghasilkan TRUE, FALSE, dan NULL.
Dalam perintah SQL, ekspresi-ekspresi Boolean mengijinkan kita menentukan baris-baris data di dalam table yang terpengaruh oleh perintah tersebut. Dalam perintah prosedural, ekspresi-ekspresi Boolean merupakan dasar untuk pengontrol kondisional. Terdapat tiga jenis ekspresi-ekspresi Boolean: aritmatika, karakter, dan tanggal.
2.7.2.1. Boolean Arithmetic Expressions
Kita dapat membandingkan nilai-nilai karakter untuk persamaan dan pertidaksamaan. Secara default, perbandingan-perbandingan didasarkan pada nilai-nilai binary dari setiap byte dalam string. Sebagai contoh, beberapa proses pemberian nilai berikut ini
string1 := 'Kathy'; string2 := 'Kathleen';
ekspresi berikut ini adalah benar
string1 > string2
Dengan mengatur initialization parameter NLS_COMP=ANSI, kita dapat membuat perbandingan-perbandingan menggunakan collating sequence oleh initialization parameter NLS_SORT. Collating sequence merupakan urutan internal dari character set dimana jangkauan kode-kode numerik merepresentasikan karakter-karakter individual. Sebuah nilai karakter lebih besar daripada lainnya jika numerik internalnya lebih besar. Setiap bahasa pemrograman bisa memiliki aturan-aturan yang berbeda mengenai dimana karakter-karakter tersebut tampak di dalam collating sequence. Sebagai contoh, huruf beraksen mungkin diurutkan secara berbeda bergantung character set dari database, meskipun nilai binary-nya sama dalam setiap kasus.
Terdapat perbedaan semantik (arti kata) antara tipe-tipe dasar CHAR dan VARCHAR2 yang datang ketika kita membandingkan nilai-nilai karakter.
Banyak tipe-tipe yang dapat dikonversi menjadi tipe-tipe karakter. Sebagai contoh, kita dapat membandingkan, memberikan nilai, dan melakukan operasi-operasi karakter lainnya dengan menggunakan variable-variable CLOB.
2.7.2.2. Boolean Date Expressions
Kita dapat pula membandingkan tanggal. Perbandingan-perbandingan adalah kronologis: jadi, satu tanggal lebih besar daripada lainnya jika ia lebih baru (lebih terkini). Sebagai contoh, pemberian-pemberian nilai ini
date1 := '01-JAN-91'; date2 := '31-DEC-90';
ekspresi berikut ini adalah benar:
date1 > date2
2.7.2.3. Aturan untuk PL/SQL Boolean Expressions
- Secara umum, kita tidak membandingkan angka-angka real untuk persamaan atau pertidaksamaan yang tepat. Angka-angka real tidimpan sebagai nilai-nilai kurang lebih (kira-kira). Jadi, sebagai contoh, kondisi IF berikut ini mungkin tidak menghasilkan TRUE:
count := 1; IF count = 1.0 THEN ... END IF;
- Merupakan ide yang baik untuk menggunakan tanda kurung ketika melakukan perbandingan-perbandingan. Sebagai contoh, ekspresi berikut ini tidak diperbolehkan karena 100 < tax menghasilkan nilai Boolean, yang mana tidak dapat dibandingkan dengan angka 500:
100 < tax < 500 -- not allowedVersi debug-nya adalah sebagai berikut
(100 < tax) AND (tax < 500)
- Variable Boolean sudah memiliki nilai true atau false. Sehingga, perbandingan-perbandingan dengan nilai-nilai Boolean TRUE dan FALSE adalah redundan. Sebagai contoh, asumsikan variable done bertipe BOOLEAN, perintah WHILE
WHILE NOT (done = TRUE) LOOP ... END LOOP;dapat disederhanakan sebagai berikut
WHILE NOT done LOOP ... END LOOP;
- Menggunakan nilai-nilai CLOB dengan operator-operator perbandingan, atau function seperti LIKE dan BETWEEN, dapat menyebabkan diciptakannya LOB temporary. Kita mungkin perlu meyakinkan temporary tablespace kita cukup besar untuk menangani LOB sementara.
2.7.3. CASE Expressions
Ekspresi CASE mendapatkan hasil dari satu atau dua alternatif, dan menghasilkan hasil. Ekspresi CASE menggunakan selector, dan ekspresi yang nilainya menentukan alternatif mana yang dikembalikan. Ekspresi CASE memiliki bentuk sebagai berikut:
CASE selector WHEN expression1 THEN result1 WHEN expression2 THEN result2 ... WHEN expressionN THEN resultN [ELSE resultN+1] END;
Penyeleksi diikuti oleh satu atau lebih klausa WHERE, yang dicek secara berurutan. Nilai dari penyeleksi menentukan klausa mana yang dieksekusi. Klausa WHERE pertama yang sesuai dengan nilai dari penyeleksi menentukan nilai hasilnya, dan klausa WHERE berikutnya tidak lagi dievaluasi. Contohnya sebagai berikut:
DECLARE
grade CHAR(1) := 'B';
appraisal VARCHAR2(20);
BEGIN
appraisal :=
CASE grade
WHEN 'A' THEN 'Excellent'
WHEN 'B' THEN 'Very Good'
WHEN 'C' THEN 'Good'
WHEN 'D' THEN 'Fair'
WHEN 'F' THEN 'Poor'
ELSE 'No such grade’
END;
END;
Klausa opsional ELSE bekerja mirip dengan klausa ELSE dalam perintah IF. Jika nilai dari penyeleksi tidak terdapat pada salah satu dari pilihan-pilihan yang disediakan oleh klausa WHEN, klausa ELSE dieksekusi. Jika tidak ada klausa ELSE yang disediakan dan tidak ada klausa WHEN yang cocok, maka ekspresi menghasilkan NULL.
Alternatif untuk ekspresi CASE adalah perintah CASE, dimana klausa WHEN dapat berupa seluruh blok PL/SQL.
2.7.3.1. Searched CASE Expression
PL/SQL juga menyediakan ekspresi CASE pencarian, yang memiliki bentuk:
CASE WHEN search_condition1 THEN result1 WHEN search_condition2 THEN result2 ... WHEN search_conditionN THEN resultN [ELSE resultN+1] END;
Ekspresi CASE pencarian tidak memiliki penyeleksi. Setiap klausa WHEN mengandung kondisi pencarian yang menghasilkan nilai Boolean, yang mengijinkan kita untuk mengetes perbedaan variable-variable atau banyak kondisi di dalam klausa WHEN tunggal. Contohnya adalah sebagai berikut:
DECLARE
grade CHAR(1);
appraisal VARCHAR2(20);
BEGIN
...
appraisal :=
CASE
WHEN grade = 'A' THEN 'Excellent'
WHEN grade = 'B' THEN 'Very Good'
WHEN grade = 'C' THEN 'Good'
WHEN grade = 'D' THEN 'Fair'
WHEN grade = 'F' THEN 'Poor'
ELSE 'No such grade'
END;
...
END;
Kondisi-kondisi pencarian dievaluasi secara berurutan. Nilai Boolean dari setiap kondisi pencarian menentukan dimana klausa WHEN dieksekusi. Jika kondisi pencarian menghasilkan TRUE, klausa WHEN-nya dieksekusi. Setelah satu klausa WHEN dieksekusi, kondisi-kondisi pencarian lainnya tidak dievaluasi, Jika tidak ada kondisi-kondisi pencarian yang menghasilkan TRUE, klausa opsional ELSE dieksekusi. Jika tidak ada klausa WHEN yang dieksekusi dan tidak ada klausa ELSE yang disediakan, nilai dari ekspresi adalah NULL.
2.7.4. Menangani Nilai-nilai Null dalam Perintah-perintah Perbandingan dan Kondisional
Ketika bekerja dengan null, kita dapat menghindari beberapa kesalahan-kesalahan umum dengan mengingat aturan-aturan berikut ini:
- Perbandingan-perbandingan yang melibatkan null selalu menghasilkan NULL
- Memberikan operator logikal NOT terhadap null menghasilkan NULL
- Dalam perintah-perintah pengontrol kondisi, jika kondisi menghasilkan NULL, perintah-perintah setelahnya tidak akan dieksekusi
- Jika ekspresi di dalam perintah CASE sederhana atau ekspresi CASE menghasilkan NULL, ita tidak dapat dicocokkan dengan menggunakan WHEN NULL. Dalam kasus ini, kita perlu menggunakan sintaks pencarian case dan melakukan test WHEN expression IS NULL.
Dalam contoh beirkut ini, kita mungkin berharap perintah-perintah selanjutkan dieksekusi karena x dan y terlihat tidak sama. Namun, null memiliki tingkat menengak. Apakah x sama dengan y adalah tidak diketahui. Sehingga, kondisi IF menghasilkan NULL dan perintah-perintah selanjutnya akan dilewati (diabaikan).
x := 5; y := NULL; ... IF x != y THEN -- menghasilkan NULL, bukan TRUE sequence_of_statements; -- tidak dieksekusi END IF;
Dalam contoh selanjutnya, kita mungkin berharap perintah-perintah dieksekusi karena a dan b terlihat sama. Namun, lagi, hal ini tidak diketahui, maka kondisi IF menghasilkan NULL dan perintah-perintah selanjutnya akan diabaikan.
a := NULL; b := NULL; ... IF a = b THEN -- menghasilkan NULL, bukan TRUE sequence_of_statements; -- tidak dieksekusi END IF;
2.7.4.1. Operator NOT
Perlu diingat kembali bahwa penerapan operator logikal NOT terhadap null menghasilkan NULL. Sehingga, dua perintah-perintah dibawah ini tidak selalu sama:
IF x > y THEN | IF NOT x > y THEN high := x; | high := y; ELSE | ELSE high := y; | high := x; END IF; | END IF;
Perintah-perintah selanjutnya di dalam klausa ELSE dieksekusi ketika kondisi IF menghasilkan FALSE atau NULL. Jika tidak satupun x atau y merupakan null, ketua perintah IF memberikan nilai yang sama kepada high. Namun, jika salah satu x atau y adalah null, perintah IF yang pertama akan memberikan nilai y kepada high, tetapi perintah IF yang kedua akan memberikan nilai x kepada high.
2.7.4.2. Zero-Length Strings
PL/SQL memperlakukan string zero-length seperti null. Ini termasuk nilai-nilai yang dihasilkan oleh function-function karakter dan ekspresi-ekspresi Boolean. Sebagai contoh, perintah-perintah berikut memberikan null kepada variable-variable target:
null_string := TO_CHAR('');
zip_code := SUBSTR(address, 25, 0);
valid := (name != '');
Sehingga, gunakan operator IS NULL untuk mengetes string-string null, seperti berikut ini:
IF my_string IS NULL THEN ...
2.7.4.3. Concanetation Operator
Operator penggabungan mengabaikan operand-operand null. Sebagai contoh, ekspresi
'apple' || NULL || NULL || 'sauce'
menghasilkan nilai berikut ini:
'applesauce'
2.7.4.4. Functions
Jika argumen null dilewatkan kepada built-in function, null dihesilkan kecuali dalam kasus-kasus berikut.
Function DECODE membandingkan argumen pertamanya dengan satu atau lebih ekspresi-ekspresi pencarian, yang berpasangan dengan ekspresi-ekspresi hasil. Beberapa ekspresi pencarian atau hasil dapat berupa null. Jika pencarian berhasil, hasil yang sesuai dikembalikan. Dalam contoh berikut ini, jika kolom rating adalah null, DECODE menghasilkan nilai 1000:
Function NVL menghasilkan nilai dari argumen keduanya jika argumen pertamanya adalah null. Dalam contoh berikut, jika hire_date adalah null, NVL menghasilkan nilai dari SYSDATE. Sebaliknya, NVL menghasilkan nilai hire_date:
start_date := NVL(hire_date, SYSDATE);
Function REPLACE menghasilkan nilai dari argumen pertamanya jika argumen keduanya null, meskipun argumen opsional ketiganya ada atau tidak. Sebagai contoh, setelah pemberian nilai
new_string := REPLACE(old_string, NULL, my_string);
nilai old_string dan new_string adalah sama.
Jika argumen ketiga adalah null, REPLACE menghasilkan argumen pertamanya dengan setiap hal yang terjadi pada setiap argumen keduanya dihapus. Sebagai contoh, setiap pemberian nilai
syllabified_name := 'Gold-i-locks'; name := REPLACE(syllabified_name, '-', NULL);
nilai dari name adalah ‘goldilocks’
Jika argumen kedua dan ketiganya adalah null, REPLACE secara sederhana menghasilkan argumen pertamanya.
2.8. Built-In Functions
PL/SQL menyediakan banyak function-function yang powerful untuk membantu kita memanipulasi data. Function-function built-in (bawaan) ini terbagi menjadi kategori-kategori berikut:
- error reporting
- number
- character
- datatype conversion
- date
- object reference
- miscellaneous
Tabel 2-3 menunjukkan function-function di dalam setiap kategori.
Kecuali untuk function-function error-reporting SQLCODE dan SQLERRM, kita dapat melihat seluruh function dalam perintah-perintah SQL. Juga, kecuali function-function object-reference DEREF, REF, dan VALUE dan function-function miscellaneous DECODE, DUMP, dan VSIZE, kita dapat menggunakan seluruh function-function dalam perintah-perintah prosedural.
Meskipun fungsi agregat SQL (seperti AVG dan COUNT) dan function-function analitik (seperti CORR dan LAG) tidak disediakan untuk PL/SQL, kita dapat menggunakan mereka dalam perintah-perintah SQL (namun tidak dalam perintah-perintah procedural).

Tabel 2-3 Built-in Functions
Silahkan melanjutkan membaca pembahasan Tipe-tipe Data PL/SQL
| 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 Dasar-dasar PL/SQL […]