Tipe-tipe Data PL/SQL
Setiap konstanta, variable, dan parameter memiliki tipe data (atau tipe), yang menentukan bentuk penyimpanan, constraint, dan jangkauan yang valid dari nilai-nilai. PL/SQL menyediakan berbagai macam tipe-tipe data. Sebagai contoh, kita dapat menggunakan tipe-tipe data mulai dari integer, floating point, character, Boolean, date, collection, reference, dan LOB. Sebagai tambahan, PL/SQL mengijinkan kita untuk mendefinisikan sub-tipe kita sendiri. Pembahasan kali ini mencakup tipe-tipe dasar yang seringkali digunakan program-program PL/SQL. Pembahasan selanjutnya mencakup lebih banyak tipe-tipe khusus.
Pembahasan kali ini mendiskusikan topik-topik berikut ini:
- Predefined Datatypes
- User-Defined Subtypes
- Datatype Conversion
3.1. Predefined Datatypes
Tipe scalar tidak memiliki komponen-komponen internal. Tipe composite memiliki komponen-komponen internal yang dapat dimanipulasi secara tersendiri. Tipe reference menyimpan nila-nilai, yang disebut pointers, yang menunjuk item-item program lainnya. Tipe LOB menyimpan nilai-nilai, yang disebut lob locators, yang menentukan lokasi dari objek-objek yang besar (image grafis sebagai contoh) yang tersimpan out-of-line.
Gambar 3-1 menunjukkan predefined datatypes yang tersedia untuk kita gunakan. Tipe-tipe scalar terbagi menjadi empat bagian, yang mana menyimpan angka, karakter, Boolean, dan data tanggal/waktu.

Gambar 3-1 Built-in Datatypes
3.1.1. Number Types
Tipe-tipe Number mengijinkan kita untuk menyimpan data numerik (integers, real numbers, dan floating-point numbers), merepresentasikan kuantitas, dan melakukan kalkulasi / perhitungan.
3.1.1.1 BINARY_INTEGER
Kita menggunakan tipe data BINARY_INTEGER untuk menyimpan signed integers (integers bertanda). Besarnya jangkauan adalah -2**31..2**31. Seperti nilai-nilai PLS_INTEGER, nilai-nilai BINARY_INTEGER membutuhkan lebih sedikit tempat penyimpanan dibandingkan dengan nilai-nilai NUMBER. Namun, kebanyakan operasi-operasi BINARY_INTEGER lebih lambat daripada operasi-operasi PLS_INTEGER.
3.1.1.1.1 BINARY_INTEGER Subtypes
Base type adalah tipe data yang berasal dari tempat dimana subtype berasal. Subtype berhubungan dengan base type dengan constraint dan selanjutnya mendefinisikan subset dari nilai-nilai. Untuk kenyamanan kita, PL/SQL telah mendefinisikan subtypes BINARY_INTEGER sebagai berikut:
NATURAL NATURALN POSITIVE POSITIVEN SIGNTYPE
Sub-sub tipe NATURAL dan POSITIVE mengijinkan kita untuk membatasi variable integer ke nilai-nilai non-negatif atau positif. NATURALN dan POSITIVEN mencegah pemberian null kepada variable integer. SIGNTYPE mengijinkan kita untuk membatasi variable integer ke nilai-nilai -1, 0, and 1, yang berguna di dalam logika pemrograman tri-state.
3.1.1.2. NUMBER
Kita menggunakan tipe data NUMBER untuk menyimpan fixed-point atau floating-point numbers. Besarnya jangkauan adalah 1E-130..10E125. Jika nilai dari ekspresi turun ke luar dari jangkauan ini, kita mendapatkan error numeric overflow atau underflow. Kita dapat menentukan precision, yang merupakan total jumlah digit, dan scale, yang merupakan jumlah digit ke kanan dari titik desimal. Sintaksnya sebagai berikut:
NUMBER[(precision, scale)]
Untuk mendeklarasikan fixed-point numbers, dimana kita harus menentukan scale, gunakan bentuk berikut:
NUMBER(precision,scale)
Untuk mendeklarasikan floating-point numbers, dimana kita harus menentukan precision atau scale karena decimal point (titik desimal) dapat ”float” (mengambang) ke posisi tertentu, gunakan bentuk berikut:
NUMBER
Kita tidak dapat menggunakan konstanta atau variable untuk menentukan precision dan scale; kita harus menggunakan integer literals. Nilai presisi maksimum untuk NUMBER adalah digit desimal 38. Jika kita tidak menentukan precision, defaultnya adalah 38 atau nilai maksimum yang didukung oleh sistem kita, yang bisa saja lebih kecil.
Scale, yang dapat memiliki rentang dari -84 sampai 127, menentukan dimana pembulatan muncul. Sebagai contoh, skala 2 dibulatkan ke ratusan terdekat (3.456 menjadi 3.46). Skala negatif dibulatkan ke kiri dari titik desimal. Sebagai contoh, skala -3 dibulatkan ke ribuan terdekat (3456 menjadi 3000). Skala 0 dibulatkan ke seluruh angka. Jika kita tidak menentukan scale, maka defaultnya adalah 0.
3.1.1.2.1. NUMBER Subtypes
Kita dapat menggunakan sub-sub tipe NUMBER berikut ini untuk kompatibilitas dengan tipe-tipe ANSI/ISI dan IBM atau ketika kita menghendaki nama yang lebih deskriptif:
DEC DECIMAL DOUBLE PRECISION FLOAT INTEGER INT NUMERIC REAL SMALLINT
Gunakan sub-sub tipe DEC, DECIMAL, dan NUMERIC untuk mendeklarasikan fixed-point numbers dengan presisi maksimum 38 digit desimal.
Gunakan sub-sub tipe DOUBLE PRECISION dan FLOAT untuk mendeklarasikan floating-point numbers dengan presisi maksimum 126 digit binary, yang secara kasar sama dengan 38 digit desimal. Atau, gunakan sub tipe REAL untuk mendeklarasikan floating-point numbers dengan presisi maksimum 63 digit binary, yang secara kasar sama dengan 18 digit desimal.
Gunakan sub-sub tipe INTEGER, INT, dan SMALLINT untuk mendeklarasikan integers dengan presisi maksimum dari 38 digit desimal.
3.1.1.3. PLS_INTEGER
Kita menggunakan tipe data PLS_INTEGER untuk menyimpan integers bertanda (signed integers). Besar jangkauannya adalah -2**31..2**31. Nilai-nilai PLS_INTEGER membutuhkan tempat menyimpanan yang lebih sedikit dibandingkan nilai-nilai NUMBER. Juga, operasi-operasi PLS_INTEGER menggunakan machine arithmetic, sehingga mereka lebih cepat daripada operasi-operasi NUMBER dan BINARY_INTEGER, yang menggunakan library arithmetic. Untuk efisiensi, gunakan PLS_INTEGER untuk seluruh proses perhitungan yang masuk ke dalam jarak jangkauannya.
Meskipun PLS_INTEGER dan BINARY_INTEGER memiliki jarak jangkauan yang sama, mereka tidak sepenuhnya kompatibel. Ketika perhitungan PLS_INTEGER meluap, muncul exception. Namun, ketika perhitungan BINARY_INTEGER meluap, tidak muncul exception jika hasilnya diberikan ke variable NUMBER.
Karena perbedaan kecil dalam hal semantik ini, kita mungkin ingin melanjutkan penggunaan BINARY_INTEGER di dalam aplikasi-aplikasi lama untuk alasan kompatibilitas. Di dalam aplikasi-aplikasi baru, selalu gunakan PLS_INTEGER untuk performa lebih baik.
3.1.2. Character Types
Tipe-tipe karakter mengijinkan kita meyimpan data alfanumerik, merepresentasikan kata-kata dan teks, dan memanipulasi kumpulan karakter.
3.1.2.1. CHAR
Kita menggunakan tipe data CHAR untuk menyimpan data karakter yang memiliki panjang tetap (fixed-length). Bagaimana data direpresentasikan secara internal bergantung pada database character set. Tipe data CHAR menyediakan parameter opsional yang mengijinkan kita untuk menentukan ukuran maksimum hingga 32767 bytes. Kita dapat menentukan ukuran dalam hubungan bytes atau characters, dimana setiap karakter mengandung satu atau lebih bytes, bergantung pada proses encoding terhadap character set. Sintaksnya adalah sebagai berikut:
CHAR[(maximum_size [CHAR | BYTE] )]
Kita tidak dapat menggunakan konstanta atau variable simbolik untuk menentukan ukuran maksimum; kita harus menggunakan integer literal dalam jangkauan 1..32767.
Jika kita tidak menentukan ukuran maksimum, maka diset default 1. Jika kita menentukan ukuran maksimum dalam bytes daripada characters, variable CHAR(n) bisa jadi terlalu kecil untuk menyimpan n multibyte characters. Untuk menghindari kemungkinan ini, gunakan notasi CHAR (n CHAR) sehingga variable dapat menangani n characters di dalam database character set, bahkan jika beberapa karakter itu mengandung multiple bytes. Ketika kita menentukan panjang di dalam characters, batas atasnya tetap 32767 bytes. Jadi untuk double-byte dan multibyte character sets, kita hanya dapat menentukan ½ atau 1/3 sebanyak karakter dengan single-byte character set.
Meskipun variable-variable karakter PL/SQL dapat relatif panjang, luas maksimum dari kolom bertipe CHAR adalah 2000 bytes. Jadi, kita tidak dapat menambahkan nilai-nilai CHAR lebih panjang dari 2000 bytes ke dalam kolom bertipe CHAR.
Kita dapat menambahkan suatu nilai CHAR(n) ke dalam kolom LONG karena luas maksimum kolom LONG adalah 2**31 bytes atau dua gigabytes. Namun, kita tidak dapat menampilkan nilai lebih panjang dari 32767 bytes dari kolom LONG ke dalam variable CHAR(n).
Ketika kita tidak menggunakan pengkualifikasi CHAR atau BYTE, nilai default ditentukan oleh setting initialization parameter NLS_LENGTH_SEMANTICS. Ketika procedure PL/SQL di-compile, setting dari parameter ini dicatat, sehingga setting yang sama digunakan ketika procedure di-compile setelah di-invalidasi.
CHAR Subtype CHAR Subtype (sub tipe CHAR) yaitu CHARACTER memiliki jangkauan nilai yang sama seperti tipe dasarnya (base type). Sehingga, CHARACTER hanya merupakan nama lain dari CHAR. Kita dapat menggunakan sub tipe ini untuk kompatibilitas dengan tipe-tipe ANSI/ISO dan IBM atau ketika kita menginginkan identifier lebih deskriptif dari CHAR.
3.1.2.2. LONG dan LONG RAW
Kita menggunakan tipe data LONG untuk menyimpan string karakter yang memiliki panjang bervariasi (variable-length). Tipe data LONG seperti tipe data VARCHAR2, kecuali bahwa ukuran maksimum LONG adalah 32760 bytes.
Kita menggunakan tipe data LONG RAW untuk menyimpan binary data atau byte strings. Data LONG RAW sama seperti LONG, kecuali bahwa LONG RAW tidak diinterpretasikan (interpreted) oleh PL/SQL. Ukuran maksimum LONG RAW adalah 32760 bytes.
Mulai Oracle9i, variable-variable LOB dapat digunakan secara bergantian dengan variable-variable LONG dan LONG RAW. Oracle merekomendasikan migrasi data LONG ke tipe CLOB, dan LONG RAW ke tipe BLOB.
Kita dapat menambahkan suatu nilai LONG ke kolom bertipe LONG karena lebar maksimum kolom LONG adalah 2**31 bytes. Namun, kita tidak dapat menampilkan nilai lebih panjang dari 32760 bytes dari kolom LONG ke variable LONG.
Demikian juga, kita dapat menambahkan suatu nilai LONG RAW ke kolom bertipe LONG RAW karena lebar maksimum kolom LONG RAW adalah 2**31 bytes. Namun, kita tidak dapat menampilkan nilai lebih panjang dari 32760 bytes dari kolom LONG RAW ke dalam variable LONG RAW.
Kolom-kolom LONG dapat menyimpan text, arrays of characters, atau bahkan short documents (dokumen singkat). Kita dapat mereferensi ke kolom-kolom LONG dalam perintah-perintah UPDATE, INSERT, dan (kebanyakan) SELECT, tetapi tidak di dalam expressions, SQL function calls, atau klausa-klausa SQL tertentu seperti WHERE, GROUP BY, dan CONNECT BY.
Catatan: Dalam perintah-perintah SQL, PL/SQL mengikat nilai-nilai LONG sebagai VARCHAR2, tidak sebagai LONG. Namun, jika panjang dari batas VARCHAR2 melampaui lebar maksimum kolom VARCHAR2 (4000 bytes). Oracle mengkonversi tipe yang terikat itu ke LONG secara otomatis, lalu menampilkan pesan error karena kita tidak dapat melewatkan nilai-nilai LONG ke fungsi-fungsi SQL.
3.1.2.3. RAW
Kita menggunakan tipe data RAW untuk menyimpan binary data atau byte strings. Sebagai contoh, variable RAW dapat menyimpan urutan karakter grafis atau gambar terdigitalisasi. Data RAW seperti data VARCHAR2, kecuali bahwa PL/SQL tidak menginterpretasi data raw. Demikian juga, Oracle Net tidak melakukan konversi character set ketika kita mentransmisikan data raw dari satu sistem ke lainnya.
Tipe data RAW membawa parameter yang dibutuhkan yang mengijinkan kita untuk menentukan ukuran maksimum hingga 32767 bytes. Sintaksnya adalah:
RAW(maximum_size)
Kita tidak dapat menggunakan konstanta simbolik atau variable untuk menentukan ukuran maksimum; kita harus menggunakan literal integer dalam jangkauan 1..32767.
Lebar maksimum dari kolom (pada database) bertipe RAW adalah 2000 bytes. Jadi, kita tidak dapat menambahkan nilai-nilai RAW lebih panjang dari 2000 bytes ke dalam kolom bertipe RAW. Kita dapat menambahkan suatu nilai RAW ke dalam kolom bertipe LONG RAW karena lebar maksimum kolom bertipe LONG RAW adalah 2**31 bytes. Namun, kita tidak dapat menampilkan nilai lebih panjang dari 32767 bytes dari kolom bertipe LONG RAW ke dalam variable RAW.
3.1.2.4. ROWID dan UROWID
Secara internal, setiap tabel di database memiliki pseudocolumn ROWID, yang menyimpan nilai-nilai biner (binary) yang disebut rowids. Setiap rowid merepresentasikan alamat penyimpanan dari sebuah baris (row). Sebuah logical rowid mengidentifikasi baris di dalam index-organized table. Tipe data ROWID hanya dapat menyimpan pysical rowids. Namun, tipe data UROWID (universal rowid) dapat menyimpan physical, logical, atau foreign (non-Oracle) rowids.
Saran: Gunakan tipe data ROWID hanya untuk kompatibilitas ke belakang dengan aplikasi-aplikasi lama. Untuk aplikasi-aplikasi baru, gunakan tipe data UROWID.
Ketika kita menampilkan atau mengambil rowid ke dalam variable, kita dapat menggunakan function built-in ROWIDTOCHAR, yang mengkonversi nilai ke dalam 18-byte character string. Sebaliknya, function CHARTOROWID mengkonversi ROWID character string ke dalam rowid. Jika proses konversi gagal karena character string tidak merepresentasikan rowid yang valid, PL/SQL menampilkan predefined exception SYS_INVALID_ROWID. Hal ini juga diterapkan untuk proses-proses konversi implisit (konversi yang secara otomatis dilakukan oleh Oracle).
Untuk mengkonversi antara variable-variable UROWID dan character strings, gunakan perintah-perintah assignment biasa tanpa melakukan pemanggilan function. Nilai-nilai secara implisit dikonversi antara UROWID dan tipe-tipe karakter.
3.1.2.4.1. Physical Rowids
Physical rowids menyediakan akses cepat ke baris-baris data (rows) tertentu di dalam table. Selama baris data tersebut ada, physical rowid-nya tidak akan berubah. Efisien dan stabil, physical rowids berguna untuk menampilkan kumpulan baris-baris data, beroperasi pada seluruh set, dan lalu memodifikasi subset-nya. Sebagai contoh, kita dapat membandingkan variable UROWID dengan pseudocolumn ROWID di dalam klausa WHERE pada perintah UPDATE atau DELETE untuk mengidentifikasi baris terakhir yang dihasilkan dari sebuah cursor.
Sebuah physical rowid dapat memiliki dua bentuk. Sebuah bentuk 10-byte extended rowid mendukung alamat relatif terhadap blok-blok pada tablespace dan dapat mengidentifikasi table-table terpartisi (partitioned tables) atau tidak (non-partitioned tables). Sebuah bentuk 6-byte restricted rowid menyediakan kompatibilitas ke belakang (terhadap versi-versi Oracle sebelumnya).
Extended rowids menggunakan base-64 encoding dari alamat fisik untuk setiap baris data yang dipilih. Sebagai contoh, dalam SQL*Plus (yang secara implisit mengkonversi rowids ke character strings), query
SQL> SELECT rowid, ename FROM emp WHERE empno = 7788;
dapat menghasilkan baris berikut:
ROWID ENAME ------------------ ---------- AAAAqcAABAAADFNAAH SCOTT
Format tersebut, OOOOOOFFFBBBBBBRRR, terdiri dari empat bagian:
- OOOOOO: Nomor objek data (AAAAqc dalam contoh di atas) menentukan database segment. Schema objects dalam segmen yang sama, seperti cluster dari table-table, memiliki nomor objek data (data object number) yang sama.
- FFF: Nomor file (AAB dalam contoh diatas) menentukan data file yang mengandung baris data (row) tersebut. Nomor file (file number) adalah unique di dalam database.
- BBBBBB: Nomor blok (AAADFN dalam contoh di atas) menentukan data block yang mengandung baris data (row) tersebut. Nomor blok (block number) adalah relatif terhadap data file-nya, tidak terhadap tablespace. Jadi, dua baris data (rows) di dalam tablespace yang sama namun di dalam data file yang berbeda dapat memiliki nomor block (block number) yang sama.
- RRR: Nomor baris / row number (AAH dalam contoh di atas) menentukan row di dalam block.
3.1.2.4.2. Logical Rowids
Logical rowids menyediakan akses cepat terhadap baris-baris data (rows) tertentu. Oracle menggunakannya untuk membangun index kedua pada index-organized tables. Tidak memiliki alamat fisik permanen, logical rowid dapat berpindah di antara blok-blok data (data blocks) ketika baris-baris data ditambahkan. Namun, jika lokasi fisik baris data berubah, logical rowid-nya tetap valid.
Logical rowid dapat memasukkan guess, yang menentukan lokasi blok dari baris data pada saat guess diciptakan. Dibandingkan melakukan full key search, Oracle menggunakan guess untuk mencari blok secara langsung. Namun, jika terdapat penambahan baris-baris data baru, guess dapat menjadi usang dan menurunkan kecepatan akses terhadap baris-baris data. Untuk memperoleh guess yang fresh, kita dapat membagun ulang (rebuild) indek kedua tersebut.
Kita dapat menggunakan pseudocolumn ROWID untuk menampilkan logical rowids dari sebuah index-organized table. Juga, kita dapat menambahkan logical rowids ke dalam kolom bertipe UROWID, yang memiliki ukuran maksimum 4000 bytes.
Perintah ANALYZE membantu kita mengikuti keusangan guesses. Hal ini berguna untuk aplikasi-aplikasi yang menyimpan rowids dengan guesses di dalam sebuah kolom UROWID, lalu menggunakan rowids untuk menampilkan baris-baris data.
Catatan: Untuk memanipulasi rowids, kita dapat menggunakan package yang telah disediakan yaitu DBMS_ROWID.
3.1.2.5. VARCHAR2
Kita menggunakan tipe data VARCHAR2 untuk menyimpan data karakter dengan panjang berubah-ubah (variable-length). Bagaimana data direpresentasikan secara internal bergantung pada database character set. Tipe data VARCHAR2 menyediakan parameter yang diperlukan yang menentukan ukuran maksimum hingga 32767 bytes. Sintaksnya adalah sebagai berikut:
VARCHAR2(maximum_size [CHAR | BYTE])
Kita tidak dapat menggunakan konstanta simbolik atau variable untuk menentukan ukuran maksimum; kita harus menggunakan integer literal dalam jangkauan 1..32767.
Variable-variable VARCHAR2 kecil dioptimasi untuk performa, dan yang lebih besar dioptimasi untuk penggunaan memory yang lebih efisien. Cutoff point-nya adalah 2000 bytes. Untuk VARCHAR2 yang berukuran 2000 bytes atau lebih panjang, PL/SQL secara dinamis mengalokasikan hanya memory yang cukup untuk menyimpan nilai sebenarnya. Untuk variable VARCHAR2 yang lebih pendek daripada 2000 bytes, PL/SQL mengalokasikan panjang variable yang dideklarasikan secara penuh. Sebagai contoh, jika kita memberikan nilai yang 500-byte yang sama kepada variable VARCHAR2 (2000 bytes) serta kepada variable VARCHAR2 (1999 bytes), yang pertama akan mengambil 500 bytes sedangkan yang terakhir akan mengambil 1999 bytes.
Jika kita menentukan nilai maksimum dalam bytes dibandingkan characters, variable VARCHAR2(n) mungkin terlalu kecil untuk menyimpan n multibyte characters. Untuk menghindari kemungkinan ini, gunakan notasi VARCHAR2 (n CHAR) sehingga variable tersebut dapat menampung n characters dalam database character set, bahkan jika beberapa dari karakter-karakter tersebut mengandung multiple bytes. Ketika kita menentukan panjang dalam characters, batas atasnya masih tetap 32767 bytes. Jadi untuk double-byte dan multibyte character sets, kita hanya dapat menentukan 1/2 dan 1/3 sebanyak character dengan single-byte character set.
Meskipun variable character dari PL/SQL dapat memiliki panjang relatif, lebar maksimum dari kolom VARCHAR (pada database) adalah 4000 bytes. Sehingga, kita tidak dapat menambahkan nilai-nilai VARCHAR2 lebih panjang dari 4000 bytes ke dalam kolom bertipe VARCHAR2 di database.
Kita dapat menambahkan suatu nilai VARCHAR2(n) ke dalam kolom bertipe LONG karena lebar maksimum kolom bertipe LONG adalah 2**31 bytes. Namun, kita tidak dapat menampulkan nilai lebih panjang dari 32767 bytes dari kolom LONG ke dalam variable VARCHAR2(n).
Ketika kita tidak menggunakan pengkualifikasi CHAR atau BYTE, nilai default ditentukan oleh setting dari initialization parameter NLS_LENGTH_SEMANTICS. Ketika procedure PL/SQL dikompilasi, setting dari parameter ini direkam, sehingga setting yang sama digunakan ketika procedure di rekompilasi ulang setelah sedang diinvalidasi.
VARCHAR2 Subtypes Sub-sub tipe VARCHAR2 di bawah ini memiliki nilai jangkauan yang sama sebagaimana tipe dasarnya. Sebagai contoh, VARCHAR hanya merupakan nama lain dari VARCHAR2.
STRING
VARCHAR
Kita dapat menggunakan sub-sub tipe ini untuk kompatibilitas dengan ANSI/ISO dan tipe-tipe IBM.
Catatan: Saat ini, VARCHAR merupakan sinonim (nama lain) dari VARCHAR2. Namun, pada rilis-rilis PL/SQL di masa yang akan datang, untuk mengakomodasi standar-standar SQL yang muncul, VARCHAR mungkin akan menjadi tipe data yang lain dengan semantik perbandingan yang berbeda. Sehingga, merupakan ide yang bagus untuk menggunakan VARCHAR2 daripada VARCHAR.
3.1.3. National Character Types
Karakter set one-byte ASCII dan EBCDIC yang secara luas digunakan cukup memadai untuk merepresentasikan alfabet Roman, namun beberapa Asia, seperti Japanese, mengandung ribuan karakter. Bahasa-bahasa ini memerlukan dua atau tiga bytes untuk merepresentasikan setiap karakter. Untuk berhubungan dengan bahasa-bahasa lain, Oracle menyediakan dukungan globalisasi, yang mengijinkan kita untuk memproses data karakter single-byte dan multibyte dan mengkonversi diantara kumpulan-kumpulan karakter. Ia juga mengijinkan aplikasi-aplikasi kita berjalan di dalam lingkungan-lingkungan bahasa yang berbeda.
Dengan dukungan globalisasi, format-format angka dan tanggal secara otomatis mengadaptasi konvensi-konvensi bahasa yang ditentukan untuk sebuah user session. Sehingga, users di seluruh dunia dapat berinteraksi dengan Oracle di dalam bahasa-bahasa asli mereka.
PL/SQL mendukung dua karakter set yang disebut database character set, yang digunakan sebagai identifier dan source code, dan national character set, yang digunakan untuk data bahasa nasional (national language data). Tipe-tipe data NCHAR dan NVARCHAR2 menyimpan string-string karakter dari national character set.
Catatan: Ketika mengkonversi data CHAR atau VARCHAR2 diantara database dengan character set yang berbeda, yakinkan bahwa data berisi string-string yang telah dikonfirmasi secara baik.
3.1.3.1. Comparing UTF8 and AL16UTF16 Encodings
National character set merepresentasikan data sebagai Unicode, menggunakan encoding UTF8 atau AL16UTF16.
Setiap karakter di dalam encoding AL16UTF16 mengambil 2 bytes. Hal ini membuatnya sederhana untuk menghitung panjang-panjang string untuk menghindari kesalahan proses pemotongan karakter ketika menggabungkan bahasa-bahasa pemrograman yang berbeda, namun memerlukan ongkos penyimpanan ekstra untuk menyimpan string-string yang dibentuk oleh kebanyakan karakter-karakter ASCII.
Setiap karakter dalam encoding UTF8 mengambil 1, 2, atau 3 bytes. Hal ini mengijinkan kita untuk dapat menampung lebih banyak karakter-karakter ke dalam variable atau kolom pada table, namun hanya jika kebanyakan karakter-karakter dapat direpresentasikan dalam single byte. Ia memperkenalkan kemungkinan dari kesalahan pemotongan ketika mentransfer data ke buffer dengan ukuran bytes.
Oracle Corporation merekomendasikan kita untuk menggunakan encoding AL16UTF16 pada prakteknya, untuk realibilitas maksimum. Jika kita perlu menentukan berapa banyak bytes yang diperlukan untuk menampung string Unicode, gunakan function LENGTHB dibandingkan LENGTH.
3.1.3.2. NCHAR
Kita menggunakan tipe data NCHAR untuk menyimpan fixed-length national character data. Bagaimana data direpresentasikan secara internal bergantung pada national character set yang telah ditentukan ketika database kita ciptakan, yang mungkin menggunakan variable-width encoding (UTF8) atau fixed-width encoding (AL16UTF16). Karena tipe ini dapat selalu mengakomodasi multibyte characters, kita dapat menggunakannya untuk menampung suatu data karakter Unicode.
Tipe data NCHAR menerima parameter opsional yang mengijinkan kita untuk menentukan ukuran maksimum dalam karakter-karakter. Sintaksnya adalah sebagai berikut:
NCHAR[(maximum_size)]
Karena batas physical adalah 32767 bytes, nilai maksimum yang dapat kita tentukan untuk panjang adalah 32767/2 pada AL16UTF16 encoding, dan 32767/3 dalam UTF8 encoding.
Kita tidak dapat menggunakan konstanta simbolik atau variable untuk menentukan ukuran maksimum; kita harus menggunakan integer literal.
Jika kita tidak menentukan ukuran maksimum, nilai default-nya adalah 1. Nilai tersebut selalu merepresentasikan jumlah karakter, tidak seperti CHAR, yang dapat ditentukan dalam characters atau bytes.
my_string NCHAR(100); -- ukuran maksimum adalah 100 karakter
Lebar maksimum dari kolom NCHAR adalah 2000 bytes. Jadi, kita tidak dapat menambahkan nilai NCHAR lebih panjang dari 2000 bytes ke dalam kolom NCHAR.
Jika nilai NCHAR lebih pendek dari lebar yang telah didefinisikan untuk kolom NCHAR, Oracle menambahkan spasi di belakangnya hingga mencapai panjang yang didefinisikan.
Kita dapat menukar nilai-nilai CHAR dan NCHAR dalam perintah-perintah dan ekspresi-ekspresi. Selalu aman untuk menukar nilai CHAR menjadi nilai NCHAR, namun menukar nilai NCHAR menjadi CHAR mungkin akan menyebabkan kehilangan data jika character set untuk nilai CHAR tidak dapat merepresentasikan seluruh karakter-karakter di dalam nilai NCHAR. Kehilangan data seperti ini dapat terjadi dalam karakter-karakter yang biasanya terlihat seperti tanya tanya (?).
3.1.3.3. NVARCHAR2
Kita menggunakan tipe data NVARCHAR2 untuk menyimpan data karakter Unicode yang memiliki panjang bervariasi (variable-length). Bagaimana data direpresentasikan secara internal bergantung kepada national character set yang ditentukan saat database diciptakan, yang dapat menggunakan variable-width encoding (UTF8) atau fixed-width encoding (AL16UTF16). Karena tipe ini selalu dapat mengakomodasi karakter multibyte, kita dapat menggunakannya untuk menampung suatu data karakter Unicode.
Tipe data NVARCHAR2 menerima parameter yang diperlukan yang menentukan ukuran maksimum dalam karakter. Sintaksnya adalah:
NVARCHAR2(maximum_size)
Karena batas fisik adalah 32767 bytes, nilai maksimum yang dapat kita tentukan untuk panjangnya adalah 32767/2 dalam encoding AL16UTF16, dan 32767/3 dalam encoding UTF8.
Kita tidak dapat menggunakan konstanta simbolik atau variable untuk menentukan ukuran maksimum; kita harus menggunakan integer literal.
Ukuran maksimum selalu merepresentasikan jumlah karakter, tidak seperti VARCHAR2 yang dapat ditentukan baik dalam karakter maupun bytes.
my_string NVARCHAR2(200); -- ukuran maksimum adalah 200 karakter
Lebar maksimum dari kolom NVARCHAR2 adalah 4000 bytes. Sehingga, kita tidak dapat menambahkan nilai-nilai NVARCHAR2 lebih panjang dari 4000 bytes ke dalam kolom NVARCHAR2.
Kita dapat menukar nilai-nilai VARCHAR2 dan NVARCHAR2 dalam perintah-perintah dan ekspresi-ekspresi. Selalu aman untuk menukar nilai VARCHAR2 ke dalam nilai NVARCHAR2, namun menukar nilai NVARCHAR2 ke dalam nilai VARCHAR2 dapat menyebabkan kehilangan data jika character set untuk VARCHAR2 tidak dapat merepresentasikan seluruh karakter di dalam nilai NVARCHAR2. Kehilangan data seperti ini dapat terjadi dalam karakter-karakter yang biasanya terlihat seperti tanya tanya (?).
3.1.4. LOB Types
Tipe-tipe data LOB (large objects) seperti BFILE, BLOB, CLOB, dan NCLOB mengijinkan kita untuk menyimpan blok-blok dari data yang tidak terstruktur (seperti teks, gambar grafis, video klip, dan suara) hingga mencapai ukuran empat gigabytes. Dan, tipe-tipe data ini menyediakan akses yang efisien, random, dan piece-wise terhadap data.
Tipe-tipe LOB berbeda dengan tipe-tipe LONG dan LONG RAW dalam beberapa hal. Sebagai contoh, tipe-tipe LOB (kecuali NCLOB) dapat menjadi atribut-atribut untuk object type, namun tidak demikian dengan tipe-tipe LONG. Ukuran maksimum dari LOB adalah empat gigabytes, namun ukuran maksimum dari LONG adalah dua gigabytes. Juga, tipe-tipe LOB mendukung akses secara random terhadap data, namun tipe-tipe LONG hanya mendukung akses sekuensial.
Tipe-tipe LOB menyimpan lob locators, yang menunjuk ke objek berukuran besar yang tersimpan dalam file eksternal, in-line (di dalam baris data) atau out-of-line (di luar baris data). Kolom-kolom pada database yang bertipe BLOB, CLOB, NCLOB, atau BFILE menyimpan locators. Data BLOB, CLOB, dan NCLOB tersimpan pada database di dalam atau di luar baris data. Data BFILE tersimpan pada file-file sistem operasi di luar database.
PL/SQL beroperasi pada LOB melalui locators. Sebagai contoh, ketika kita menampilkan nilai-nilai kolom BLOB, hanya locator yang dihasilkan. Jika kita mendapatkannya selama transaksi, LOB locator mengandung transaction ID, jadi kita tidak dapat menggunakannya untuk meng-update LOB tersebut pada transaksi lainnya. Demikian juga, kita tidak dapat menyimpan LOB locator selama pada satu session, lalu menggunakannya pada session yang lain.
Mulai Oracle 9i, kita dapat juga mengkonversi tipe-tipe CLOB ke tipe-tipe CHAR dan VARCHAR2 dan sebaliknya, atau tipe-tipe BLOB ke RAW dan sebaliknya, yang mengijinkan kita untuk menggunakan tipe-tipe LOB pada banyak perintah-perintah dan function-function SQL dan PL/SQL. Untuk membaca, menulis dan melakukan operasi piecewise terhadap tipe-tipe LOB, kita dapat menggunakan package DBMS_LOB.
3.1.4.1. BFILE
Kita menggunakan tipe data BFILE untuk menyimpan large binary objects dalam file-file pada sistem operasi di luar database. Setiap variable BFILE menyimpan file locator, yang menunjuk kepada large binary object pada server. Locator mengandung directory alias, yang menentukan full path names (logical path names tidak didukung).
BFILE bersifat read-only, sehingga kita tidak dapat memodifikasinya. Ukuran BFILE bergantung pada sistem namun tidak dapat melebihi empat gigabytes (2**32 – 1 bytes). Database Administrator harus memastikan bahwa BFILE yang diberikan tersedia dan Oracle memiliki hak baca (read permission) terhadapnya. Sistem operasi yang mengatur integritas file.
BFILE tidak ikut serta dalam transaksi, tidak dapat di-recover, dan tidak dapat di-replikasi. Jumlah maksimum dari BFILE yang terbuka ditentukan oleh initialization parameter SESSION_MAX_OPEN_FILES, dan bergantung kepada sistem.
3.1.4.2. BLOB
Kita menggunakan tipe data BLOB untuk menyimpan large binary object dalam database, in-line atau out-of line. Setiap variable BLOB menyimpan sebuah locator, yang menunjuk kepada large binary object. Ukuran BLOB tidak dapat melebihi empat gigabytes.
BLOB ikut serta secara penuh dalam transaksi, dapat di-recover, dan dapat di-replikasi. Perubahan yang dilakukan melalui package DBMS_LOB dapat di-commit atau di-rollback. BLOB locator dapat digunakan pada beberapa transaksi (hanya dapat dibaca atau read-only), namun tidak dapat digunakan pada beberapa session.
3.1.4.3. CLOB
Kita menggunakan tipe data CLOB untuk menyimpan blok besar (large blocks) dari data karakter di dalam database, in-line atau out-of-line. Kedua character set, baik fixed-width maupun variable-width sama-sama didukung oleh tipe data CLOB. Setiap variable CLOB menyimpan sebuah locator, yang menunjuk kepada blok besar dari data karakter. Ukuran CLOB tidak dapat melebihi empat gigabytes.
CLOB ikut serta penuh dalam transaksi, dapat di-recover, dan dapat di-replikasi. Perubahan yang dilakukan melalui package DBMS_LOB dapat di-commit atau di-rollback. CLOB locator dapat digunakan pada beberapa transaksi (hanya dapat dibaca atau read-only), namun tidak dapat digunakan pada beberapa session.
3.1.4.4. NCLOB
Kita menggunakan tipe data NCLOB untuk menyimpan blok besar (large blocks) dari data karakter di dalam database, in-line atau out-of-line. Kedua character set, baik fixed-width maupun variable-width sama-sama didukung oleh tipe data NCLOB. Setiap variable NCLOB menyimpan sebuah locator, yang menunjuk kepada blok besar dari data NCHAR. Ukuran NCLOB tidak dapat melebihi empat gigabytes.
NCLOB ikut serta penuh dalam transaksi, dapat di-recover, dan dapat di-replikasi.
Perubahan yang dilakukan melalui package DBMS_LOB dapat di-commit atau di-rollback. NCLOB locator dapat digunakan pada beberapa transaksi (hanya dapat dibaca atau read-only), namun tidak dapat digunakan pada beberapa session.
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.
3.1.5. Boolean Type
3.1.5.1. BOOLEAN
Kita menggunakan tipe data BOOLEAN untuk menyimpan nilai-nilai logikal TRUE, FALSE, dan NULL. Hanya operasi-operasi logik yang diperbolehkan untuk variable-variable BOOLEAN.
Tipe data BOOLEAN tidak menerima parameter. Hanya nilai TRUE, FALSE, dan NULL yang dapat diberikan ke variable BOOLEAN. Kita tidak dapat menambahkan nilai TRUE dan FALSE ke dalam kolom pada database. Juga, kita tidak dapat menampilkan atau menempatkan nilai-nilai ke dalam variable BOOLEAN.
3.1.6. Datetime and Interval Types
Tipe-tipe pada bagian ini mengijinkan kita untuk menyimpan dan memanipulasi tanggal, waktu, dan interval (periode waktu). Variable yang memiliki tipe data tanggal/waktu menyimpan nilai-nilai yang disebut datetimes; variable yang memiliki tipe-tipe data interval menyimpan nilai-nilai yang disebut dengan interval. Datetime atau interval terdiri dari field-field, yang menentukan nilai-nilainya. Daftar berikut ini menunjukkan nilai-nilai yang valid untuk setiap field: 
Kecuali TIMESTAMP WITH LOCAL TIMEZONE, tipe-tipe ini seluruhnya merupakan bagian dari standar SQL92.
3.1.6.1. DATE
Kita menggunakan tipe data DATE untuk menyimpan fixed-length datetimes (tanggal dan waktu dengan panjang tetap), termasuk waktu dari hari dalam detik sejak tengah malam. Porsi tanggal di-default ke hari pertama dari bulan berjalan; porsi waktu di-default ke tengah malam. Function tanggal SYSDATE menghasilkan tanggal dan waktu saat ini.
Tip: Untuk membandingkan tanggal-tanggal, untuk menghiraukan porsi waktu dari setiap tanggal, gunakan hasil function TRUNC(date_variable) pada perbandingan, operasi-operasi GROUP BY, dan seterusnya.
Tanggal-tanggal yang valid berkisar antara 1 Januari 4712 BC hingga 31 Desember 9999 AD. Tanggal Julian (Julian date) adalah jumlah hari sejak 1 Januari 4712 BC. Tanggal-tanggal Julian mengijinkan penanggalan berkelanjutan dari referensi yang umum. Kita dapat menggunakan model format tanggal ‘J’ dengan function TO_DATE dan TO_CHAR untuk mengkonversi antara nilai-nilai DATE dan nilai persamaan Julian-nya.
Di dalam ekspresi-ekspresi date, PL/SQL secara otomatis mengkonversi nilai-nilai karakter di dalam format tanggal default ke nilai-nilai DATE. Format tanggal default ditentukan oleh initialization parameter Oracle NLS_DATE_FORMAT. Sebagai contoh, nilai defaultnya mungkin ‘DD-MM-YY’, yang terdiri dari dua digit angka untuk hari, singkatan nama bulan, dan dua digit terakhir dari tahun.
Kita dapat menambah dan mengurangi tanggal. Contohnya, perintah berikut ini menghasilkan jumlah hari sejah seorang karyawan diperkerjakan:
SELECT SYSDATE - hiredate INTO days_worked FROM emp WHERE empno = 7499;
Dalam ekspresi-ekspresi aritmatika, PL/SQL menginterpretasikan literal-literal integer sebagai hari-hari. Sebagai contoh, SYSDATE+1 adalah besok.
3.1.6.2. TIMESTAMP
Tipe date TIMESTAMP, yang merupakan perluasan dari tipe data DATE, menyimpan tahun, bulan, hari, menit, dan detik. Sintaksnya:
TIMESTAMP[(precision)]
dimana parameter opsional precision menentukan jumlah digit di dalam sebagian kecil dari field detik. Kita tidak dapat menggunakan konstanta simbolik atau variable untuk menentukan precision; kita harus menggunakan literal integer dalam jangkauan 0..9. Default-nya adalah 6.
Format default timestamp ditentukan oleh initialization parameter Oracle NLS_TIMESTAMP_FORMAT.
Pada contoh berikut ini, kita mendeklarasikan variable bertipe TIMESTAMP, lalu memberikan nilai literal terhadapnya:
DECLARE checkout TIMESTAMP(3); BEGIN checkout := ’1999-06-22 07:48:53.275’; ... END;
Dalam contoh ini, bagian kecil dari field detik adalah 0.275.
3.1.6.3. TIMESTAMP WITH TIME ZONE
Tipe data TIMESTAMP WITH TIMEZONE, yang memperluas tipe data TIMESTAMP, dengan menambahkan time-zone displacement. Perbedaan time-zone merupakan perbedaan (dalam jam dan menit) antara waktu local dengan Coordinated Universal Time (UTC) – dahulu Greenwich Mean Time. Sintaksnya adalah:
TIMESTAMP[( precision)] WITH TIME ZONE
dimana parameter opsional precision menentukan jumlah digit di dalam sebagian kecil field detik. Kita tidak dapat menggunakan konstanta simbolik atau variable untuk menentukan precision; kita harus menggunakan literal integer dalam jangkauan 0..9. Default-nya adalah 6.
Format default timestamp ditentukan oleh initialization parameter Oracle NLS_TIMESTAMP_TZ_FORMAT.
Pada contoh berikut ini, kita mendeklarasikan variable bertipe TIMESTAMP WITH TIME ZONE, lalu memberikan nilai literal terhadapnya:
DECLARE logoff TIMESTAMP(3) WITH TIME ZONE; BEGIN logoff := '1999-10-31 09:42:37.114 +02:00'; ... END;
Pada contoh ini, perbedaan time-zone adalah +02:00.
Kita juga dapat menentukan time zone dengan menggunakan nama simbolik. Spesifikasi dapat termasuk bentuk panjang seperti ‘US/Pacific’, singkatan seperti ‘PDT’, atau kombinasi keduanya. Sebagai contoh, literal-literal berikut ini seluruhnya merepresentasikan waktu yang sama. Bentuk ketiga paling dapat diandalkan karena ia menentukan aturan-aturan untuk mengikuti pada titik ketika berganti menjadi waktu siang hari.
TIMESTAMP '1999-04-15 8:00:00 -8:00' TIMESTAMP '1999-04-15 8:00:00 US/Pacific' TIMESTAMP '1999-10-31 01:30:00 US/Pacific PDT'
Kita dapat mencari nama-nama yang tersedia untuk time zone dalam data dictionary views V$TIMEZONE_NAMES pada kolom TIMEZONE_REGION dan TIMEZONE_ABBR.
Dua nilai-nilai TIMESTAMP WITH TIME ZONE dianggap identik jika mereka merepresentasikan saat yang sama dalam UTC, dengan menghiraukan perbedaan time-zine. Sebagai contoh, kedua nilai berikut dianggap identik karena, dalam UTC, 8:00 AM Pacific Standard Time adalah sama dengan 11:00 AM Eastern Standard Time:
'1999-08-29 08:00:00 -8:00' '1999-08-29 11:00:00 -5:00'
3.1.6.4. TIMESTAMP WITH LOCAL TIME ZONE
Tipe data TIMESTAMP WITH LOCAL TIME ZONE, yang memperluas tipe data TIMESTAMP, dengan menambahkan time-zone displacement. Perbedaan time-zone merupakan perbedaan (dalam jam dan menit) antara waktu local dengan Coordinated Universal Time (UTC) – dahulu Greenwich Mean Time. Kita juga dapat menggunakan time zone bernama, seperti dengan TIMESTAMP WITH TIME ZONE. Sintaksnya adalah:
TIMESTAMP[( precision)] WITH LOCAL TIME ZONE
dimana parameter opsional precision menentukan jumlah digit di dalam sebagian kecil field detik. Kita tidak dapat menggunakan konstanta simbolik atau variable untuk menentukan precision; kita harus menggunakan literal integer dalam jangkauan 0..9. Default-nya adalah 6.
Tipe data ini berbeda dengan TIMESTAMP WITH TIME ZONE bahwa ketika kita menambahkan nilai ke dalam kolom pada database, nilai tersebut dinormalisasi ke database time zone, dan perbedaan time-zone tidak disimpan dalam kolom. Ketika kita menampilkan nilai tersebut, Oracle menghasilkannya dalam time zone pada local session kita.
Pada contoh berikut ini, kita mendeklarasikan variable bertipe TIMESTAMP WITH TIME ZONE:
DECLARE logoff TIMESTAMP(3) WITH LOCAL TIME ZONE; BEGIN ... END;
Kita tidak dapat memberikan nilai-nilai literal kepada variable dengan tipe ini.
3.1.6.5. INTERVAL YEAR TO MONTH
Kita menggunakan tipe data INTERVAL YEAR TO MONTH untuk menyimpan dan memanipulasi interval-interval dari tahun dan bulan. Sintaksnya:
INTERVAL YEAR[( precision)] TO MONTH
dimana parameter opsional precision menentukan jumlah digit di dalam field tahun. Kita tidak dapat menggunakan konstanta simbolik atau variable untuk menentukan precision; kita harus menggunakan literal integer dalam jangkauan 0..4. Default-nya adalah 2.
Dalam contoh berikut ini, kita mendeklarasikan variable bertipe INTERVAL YEAR TO MONTH, lalu memberikan nilai 101 tahun dan 3 bulan kepadanya:
DECLARE lifetime INTERVAL YEAR(3) TO MONTH; BEGIN lifetime := INTERVAL '101-3' YEAR TO MONTH; -- interval literal lifetime := '101-3'; -- implicit conversion from character type lifetime := INTERVAL '101' YEAR; -- Can specify just the years lifetime := INTERVAL '3' MONTH; -- Can specify just the months ... END;
3.1.6.6. INTERVAL DAY TO SECOND
Kita menggunakan tipe data INTERVAL DAY TO SECOND untuk menyimpan dan memanipulasi interval-interval dari hari, jam, menit, dan detik. Sintaksnya adalah:
INTERVAL DAY[( leading_precision)] TO
SECOND[( fractional_seconds_precision)]
dimana leading_precision dan fractional_seconds_precision menentukan jumlah digit dalam field hari dan detik. Dalam kedua kasus ini, kita tidak dapat menggunakan konstanta simbolik atau variable untuk menentukan precision; kita harus menggunakan literal integer dalam jangkauan 0..9. Defaultnya adalah 2 dan 6.
Dalam contoh berikut, kita mendeklarasikan tipe INTERVAL DAY TO SECOND:
DECLARE lag_time INTERVAL DAY(3) TO SECOND(3); BEGIN IF lag_time > INTERVAL '6' DAY THEN ... ... END;
3.1.7. Datetime and Interval Arithmetic
PL/SQL mengijinkan kita untuk mengkonstruksi ekspresi-ekspresi datetime dan interval. Daftar berikut menunjukkan operator-operator yang dapat kita gunakan untuk ekspresi-ekspresi tersebut:
Kita juga dapat memanipulasi nilai datetime menggunakan berbagi function, seperti EXTRACT.
3.1.8. Avoiding Truncation Problems Using Date and Time Subtypes
Presisi-presisi default untuk beberapa tipe-tipe tanggal dan waktu adalah kurang dari presisi maksimum. Sebagai contoh, default untuk DAY TO SECOND adalah DAY(2) TO SECOND (6), dimana nilai presisi tertinggi adalah DAY(9) TO SECOND (9). Untuk menghindari pemotongan ketika memberikan nilai variable dan parameter pada procedure dari tipe-tipe ini, kita dapat mendeklarasikan variable-variable dan parameter-parameter procedure dengan sub-sub tipe berikut ini, yang menggunakan nilai-nilai presisi maksimum:
TIMESTAMP_UNCONSTRAINED TIMESTAMP_TZ_UNCONSTRAINED TIMESTAMP_LTZ_UNCONSTRAINED YMINTERVAL_UNCONSTRAINED DSINTERVAL_UNCONSTRAINED
3.2. User-Defined Subtypes
Setiap tipe dasar PL/SQL menentukan kumpulan nilai dan kumpulan operator yang dapat diaplikasikan terhadap item-item dengan tipe tersebut. Sub-sub tipe menentukan kumpulan operator yang sama dengan tipe dasar mereka namun hanya subset dari nilai-nilainya. Jadi, subtipe tidak memperkenalkan tipe baru; ia hanya menempatkan aturan opsional di atas tipe dasarnya.
Subtipe dapat meningkatkan reliabilitas, menyediakan kompatibilitas dengan tipe-tipe ANSI/ISO, dan meningkatkan keterbacaan dengan mengindikasikan peruntukan penggunaan konstanta dan variable. PL/SQL telah mendefinisikan beberapa subtipe dalam package STANDARD. Sebagai contoh, PL/SQL mendefinisikan sub-sub tipe CHARACTER dan INTEGER seperti ini:
SUBTYPE CHARACTER IS CHAR; SUBTYPE INTEGER IS NUMBER(38,0); -- allows only whole numbers
Subtipe CHARACTER menentukan kumpulan nilai-nilai yang sama dengan tipe dasarnya, yaitu CHAR, sehingga CHARACTER merupakan unconstrained subtype. Namun, subtipe INTEGER menentukan hanya subset dari nilai-nilai tipe dasarnya, yaitu NUMBER, sehingga INTEGER merupakan constrained subtype.
3.2.1. Defining Subtypes
Kita dapat mendefinisikan subtipe kita sendiri dalam bagian declarative dari suatu blok PL/SQL, subprogram, atau package dengan menggunakan sintaks berikut
SUBTYPE subtype_name IS base_type[(constraint)] [NOT NULL];
dimana subtype_name merupakan penentu tipe yang digunakan dalam deklarasi-deklarasi berikutnya, base_type merupakan tipe data scalar atau user-defined PL/SQL, dan constraint diaplikasikan hanya terhadap tipe dasar yang dapat menentukan presisi dan skala atau ukuran maksimum.
Beberapa contohnya:
DECLARE SUBTYPE BirthDate IS DATE NOT NULL; -- based on DATE type SUBTYPE Counter IS NATURAL; -- based on NATURAL subtype TYPE NameList IS TABLE OF VARCHAR2(10); SUBTYPE DutyRoster IS NameList; -- based on TABLE type TYPE TimeRec IS RECORD (minutes INTEGER, hours INTEGER); SUBTYPE FinishTime IS TimeRec; -- based on RECORD type SUBTYPE ID_Num IS emp.empno%TYPE; -- based on column type
Kita dapat menggunakan %TYPE atau %ROWTYPE untuk menentukan tipe dasar. Ketika %TYPE menyediakan tipe data dari kolom pada database, subtype menurunkan constraint ukuran(jika ada) dari kolom tersebut. Akan tetapi, subtipe tidak menurunkan beberap bentuk constraint seperti NOT NULL.
3.2.2. Using Subtypes
Sekali kita mendefinisikan subtipe, kita dapat mendeklarasikan item dengan tipe tersebut. Dalam contoh di bawah ini, kita mendeklarasikan variable dengan tipe Counter. Perhatikan bagaimana nama subtipe mengindikasikan penggunaan variable.
DECLARE SUBTYPE Counter IS NATURAL; rows Counter;
Contoh berikutnya menunjukkan bahwa kita dapat membatasi subtipe user-defined ketika mendeklarasikan variable dengan tipe tersebut:
DECLARE SUBTYPE Accumulator IS NUMBER; total Accumulator(7,2);
Subtipe dapat meningkatkan reliabilitas dengan mendeteksi nilai-nilai yang out-of-range (berada di luar jangkauan). Dalam contoh dibawah ini, kita membatasi subtipe Numeral untuk menyimpan integer dengan jangkauan -9..9. Jika program kita berusaha menyimpan nilai di luar jangkauan tersebut ke dalam variable Numeral, PL/SQL menampilkan exception.
DECLARE SUBTYPE Numeral IS NUMBER(1,0); x_axis Numeral; -- magnitude range is -9 .. 9 y_axis Numeral; BEGIN x_axis := 10; -- raises VALUE_ERROR ... END;
3.2.2.1. Type Compatibility
Subtipe yang tidak ber-constraint dapat ditukar dengan tipe dasarnya. Sebagai contoh, berdasarkan deklarasi di berikut ini, nilai dari amount dapat diberikan kepada total tanpa konversi:
DECLARE SUBTYPE Accumulator IS NUMBER; amount NUMBER(7,2); total Accumulator; BEGIN ... total := amount; ... END;
Sub-sub tipe berbeda dapat ditukar satu sama lain jika mereka memiliki tipe dasar yang sama. Pada contoh berikut, nilai dari finished dapat diberikan kepada debugging:
DECLARE SUBTYPE Sentinel IS BOOLEAN; SUBTYPE Switch IS BOOLEAN; finished Sentinel; debugging Switch; BEGIN ... debugging := finished; END;
Sub-sub tipe yang berbeda dapat juga saling ditukar jika tipe dasar mereka adalah sama dalam hal keluarga tipe datanya. Pada contoh berikut, nilai verb dapat diberikan ke sentence:
DECLARE SUBTYPE Word IS CHAR(15); SUBTYPE Text IS VARCHAR2(1500); verb Word; sentence Text(150); BEGIN ... sentence := verb; ... END;
3.3. Datatype Conversion
Suatu saat kadang diperlukan konversi nilai dari satu tipe data ke tipe data lainnya. Sebagai contoh, jika kita ingin memeriksa rowid, kita harus mengkonversinya ke string karakter.
3.3.1. Explicit Conversion
Untuk mengkonversi nilai dari satu tipe data ke tipe data lain, kita menggunakan function-function built-in. Sebagai contoh, untuk mengkonversi nilai CHAR ke nilai DATE atau NUMBER, kita menggunakan function TO_DATE atau TO_NUMBER. Sebaliknya, untuk mengkonversi nilai DATE atau NUMBER ke nilai CHAR, kita menggunakan function TO_CHAR.
3.3.2. Implicit Conversion
Ketika diperlukan, PL/SQL dapat mengkonversi tipe data dari sebuah nilai secara implisit. Hal ini mengijinkan kita menggunakan literal-literal, variable-variable, dan parameter-parameter dari satu tipe ketika tipe yang lain diharapkan. Dalam contoh di bawah ini, variable CHAR dari start_time dan finish_time menyimpan nilai-nilai string yang merepresentasikan jumlah detik lewat tengah malam. Perbedaan antara nilai-nilai tersebut harus diberikan ke variable elapsed_time. Sehingga, PL/SQL mengkonversi nilai-nilai CHAR ke nilai-nilai NUMBER secara otomatis:
DECLARE start_time CHAR(5); finish_time CHAR(5); elapsed_time NUMBER(5); BEGIN /* Get system time as seconds past midnight. */ SELECT TO_CHAR(SYSDATE,'SSSSS') INTO start_time FROM sys.dual; -- do something /* Get system time again. */ SELECT TO_CHAR(SYSDATE,'SSSSS') INTO finish_time FROM sys.dual; /* Compute elapsed time in seconds. */ elapsed_time := finish_time - start_time; INSERT INTO results VALUES (elapsed_time, ...); END;
Sebelum memberikan nilai kolom yang ditampilkan kepada variable, PL/SQL akan, jika perlu, mengkonversi nilai dari tipe data sumbernya ke tipe data dari variable yang akan menerimanya. Hal ini terjadi, sebagai contoh, ketika kita menampilkan nilai kolom DATE dan memberikannya ke variable VARCHAR2.
Demikian juga, sebelum memberikan nilai dari variable kepada kolom di database, PL/SQL akan, jika perlu, mengkonversi nilai dari tipe data variable ke tipe data dari kolom targetnya. Jika PL/SQL tidak dapat menentukan konversi implisit mana yang dibutuhkan, kita akan mendapatkan pesan kesalahan kompilasi (compilation error). Dalam kasus seperti ini, kita harus menggunakan function untuk mengkonversi tipe data. Tabel 3-1 menunjukkan konversi implisit mana yang dapat dilakukan oleh PL/SQL.
Catatan:
- Tabel hanya menampilkan daftar tipe-tipe yang memiliki representasi berbeda. Tipe yang memiliki representasi sama, seperti CLOB dan NCLOB, CHAR dan NCHAR2, serta VARCHAR dan VARCHAR2, dapat saling berganti satu sama lain.
- Untuk mengkonversi antara CLOB dan NCLOB, kita harus menggunakan function-function konversi TO_CLOB dan TO_NCLOB.
- TIMESTAMP, TIMESTAMP WITH TIME ZONE, TIMESTAMP WITH LOCAL TIME ZONE, INTERVAL DAY TO SECOND, dan INTERVAL YEAR TO MONTH seluruhnya dapat dikonversi menggunakan aturan yang sama seperti tipe DATE. Namun, karena representasi internal mereka yang berbeda-beda, tipe-tipe ini tidak selalu dapat dikonversi satu sama lain.

Tabel 3-1 Konversi-konversi Implisit
Merupakan tanggung jawab kita untuk memastikan bahwa nilai-nilai dapat dikonversi. Sebagai gambaran, PL/SQL dapat mengkonversi nilai CHAR ‘02-JUN-92′ ke nilai DATE, namun tidak dapat mengkonversi nilai CHAR ‘YESTERDAY’ ke nilai DATE. Mirip dengan hal tersebut, PL/SQL tidak dapat mengkonversi nilai VARCHAR2 yang mengandung karakter-karakter alphabetic ke nilai NUMBER.
3.3.3. Implicit versus Explicit Conversion
Secara umum, mempercayakan kepada konversi-konversi implisit tipe data merupakan praktek pemrograman yang buruk karena mereka dapat menghambat performa dan mungkin dapat terjadi perubahan antara rilis software yang satu dengan berikutnya. Juga, konversi-konversi implisit merupakan context-sensitive dan oleh karena itu tidak selalu dapat diprediksi. Sebaiknya gunakan function-function konversi tipe data yang telah disediakan oleh PL/SQL. Dengan begitu, aplikasi-aplikasi kita akan menjadi lebih dapat diandalkan dan mudah dipelihara.
3.3.4. Date Values
Ketika kita menampilkan nilai kolom DATE ke variable CHAR atau VARCHAR2, PL/SQL harus mengkonversi nilai biner internal menjadi nilai karakter. Sehingga, PL/SQL memanggil function TO_CHAR, yang menghasilkan string karakter dalam format default tanggal. Untuk mendapatkan informasi lain seperti waktu atau tanggal Julian, kita harus memanggil function TO_CHAR dengan menggunakan format mask.
Proses konversi juta diperlukan ketika kita menambahkan nilai CHAR atau VARCHAR2 ke kolom DATE. Jadi, PL/SQL memanggil function TO_DATE, yang menerima format tanggal default. Untuk menambahkan tanggal ke format-format lain, kita harus memanggil function TO_DATE dengan menggunakan format mask.
3.3.5. RAW and LONG RAW Values
Ketika kita menampilkan nilai kolom RAW atau LONG RAW ke dalam variable CHAR atau VARCHAR2, PL/SQL harus mengkonversi nilai biner internal ke nilai karakter. Dalam kasus ini, PL/SQL menghasilkan setiap byte biner dari data RAW atau LONG RAW sebagai pasangan dari karakter-karakter. Setiap karakter merepresentasikan ekuivalen heksadesimal dari suatu nibble (setengah byte). Sebagai contoh, PL/SQL menghasilkan byte biner 11111111 sebagai pasangan dari karakter-karakter ’FF’. Function ROWTOHEX melakukan konversi yang sama.
Konversi juga diperlukan ketika kita menambahkan nilai CHAR atau VARCHAR2 ke dalam kolom RAW atau LONG RAW. Setiap pasang dari karakter-karakter di dalam variable harus merepresentasikan ekuivalen heksadesimal dari byte biner. Jika salah satu karakter tidak merepresentasikan ekuivalen heksadesimal dari nibble, PL/SQL akan menampilkan pesan exception.
Silahkan melanjutkan membaca pembahasan Struktur Kontrol 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, Uranus dsb. |


































