Collections dan Records PL/SQL

5.15. Apa itu Record?

Sebuah record adalah kumpulkan item-item data yang saling berhubungan dan disimpan di dalam fields, dan masing-masing memiliki nama dan tipe data sendiri. Bayangkan kita memiliki berbagai macam data tentang karyawan seperti nama, gaji, dan tanggal masuk kerja. Item-item ini secara logikal berelasi namun tidak sama dalam hal tipe. Record yang  mengandung field untuk setiap item mengijinkan kita untuk memperlakukan data sebagai unit logikal. Dengan demikian, records memudahkan kita untuk mengatur dan merepresentasikan informasi.

Attribute %ROWTYPE mengijinkan kita untuk mendeklarasikan record yang merepresentasikan baris data di dalam database table. Namun, kita tidak dapat menentukan tipe-tipe data untuk field-field di dalam record atau mendeklarasikan field-field milik kita sendiri. Tipe data RECORD menghilangkan batasan-batasan ini dan mengijinkan kita untuk mendefinisikan record-record kita sendiri.

5.15.1. Mendefinisikan dan Mendeklarasikan Records

Untuk menciptakan records, kita mendefinisikan tipe RECORD, lalu mendeklarasikan records dengan tipe tersebut. Kita dapat mendefinisikan tipe-tipe RECORD di dalam bagian deklaratif dari setiap blok PL/SQL, subprogram, atau package menggunakan sintaks:

TYPE type_name IS RECORD (field_declaration[,field_declaration]…);

dimana field_declaration terdiri dari:

field_name field_type [[NOT NULL] {:= | DEFAULT} expression]

dan dimana type_name merupakan penentu tipe kemudian untuk mendeklarasikan records. Sedangkan field_type merupakan tipe data PL/SQL kecuali REF CURSOR, dan expression menghasilkan nilai dengan tipe sama dengan field_type.

Catatan: Tidak seperti VARRAY dan tipe-tipe (nested) TABLE, tipe-tipe RECORD tidak dapat di-CREATE dan disimpan di dalam database.

Kita dapat menggunakan %TYPE dan %ROWTYPE untuk menentukan tipe-tipe field. Di dalam contoh berikut ini, kita mendefinisikan tipe RECORD dengan nama DeptRec:

DECLARE
  TYPE DeptRec IS RECORD (
  dept_id dept.deptno%TYPE,
  dept_name VARCHAR2(14),
  dept_loc VARCHAR2(13));
BEGIN
  ...
END;

Perhatikan bahwa deklarasi field adalah seperti deklarasi variable. Setiap field memiliki nama yang unik dan tipe data tertentu. Jadi, nilai dari record sebenarnya adalah kumpulan nilai-nilai, yang terdiri dari tipe-tipe yang lebih sederhana.

Seperti ditunjukkan oleh contoh berikut ini, PL/SQL mengijinkan kita untuk mendefinisikan records yang mengandung objects, collections, dan records lain (disebut nested records). Namun, tipe-tipe object tidak dapat memiliki attributes bertipe RECORD.

DECLARE
  TYPE TimeRec IS RECORD (seconds SMALLINT, minutes SMALLINT, hours SMALLINT);
  TYPE FlightRec IS RECORD (flight_no INTEGER, plane_id VARCHAR2(10), captain Employee, -- mendeklarasikan object
  passengers PassengerList, -- mendeklarasikan varray
  depart_time TimeRec, -- mendeklarasikan nested record
  airport_code VARCHAR2(10));
BEGIN
  ...
END;

Contoh selanjutnya menunjukkan bahwa kita dapat menentukan tipe RECORD di dalam klausa RETURN dari spesifikasi function. Hal ini memperbolehkan function untuk menghasilkan (mengembalikan nilai) dengan user-defined record dengan tipe sama.

DECLARE
  TYPE EmpRec IS RECORD (emp_id NUMBER(4), last_name VARCHAR2(10),
  dept_num NUMBER(2), job_title VARCHAR2(9), salary NUMBER(7,2));
  ...
  FUNCTION nth_highest_salary (n INTEGER) RETURN EmpRec IS ...
BEGIN
  ...
END;

5.15.1. Mendeklarasikan Records

Sekali kita mendefinisikan tipe RECORD, kita dapat mendeklarasikan records dengan tipe tersebut, seperti ditunjukkan oleh contoh berikut ini. Identifier item_info merepresentasikan keseluruhan record.

DECLARE
  TYPE StockItem IS RECORD (item_no INTEGER(3), description VARCHAR2(50),
  quantity INTEGER, price REAL(7,2));
  item_info StockItem; -- mendeklarasikan record
BEGIN
  ...
END;

Seperti halnya variable-variable scalar, user-defined records (record-record yang didefinisikan sendiri oleh user) dapat dideklarasikan sebagai parameter-parameter formal dari procedures dan functions. Contohnya adalah sebagai berikut:

DECLARE
  TYPE EmpRec IS RECORD (emp_id emp.empno%TYPE, last_name VARCHAR2(10),
  job_title VARCHAR2(9), salary NUMBER(7,2));
  ...
  PROCEDURE raise_salary (emp_info EmpRec);
BEGIN
  ...
END;

5.15.2. Menginisialisasi Records

Contoh di bawah ini menunjukkan bahwa kita dapat menginisialisasi record di dalam definisi tipe-nya. Ketika kita mendeklarasikan record dengan tipe TimeRec, ketiga field-nya mengasumsikan bahwa nilai awalnya adalah nol.

DECLARE
  TYPE TimeRec IS RECORD (secs SMALLINT := 0, mins SMALLINT := 0, hrs SMALLINT := 0);
BEGIN
  ...
END;

Contoh berikutnya menunjukkan bahwa kita dapat memaksakan constraint NOT NULL terhadap field, sehingga mencegah pemberian nilai null terhadap field tersebut. Field-field yang dideklarasikan sebagai NOT NULL harus diinisialisasi.

DECLARE
  TYPE StockItem IS RECORD (item_no INTEGER(3) NOT NULL := 999, description VARCHAR2(50),
  quantity INTEGER, price REAL(7,2));
BEGIN
  ...
END;

5.15.3. Mereferensi Records

Tidak seperti elemen-elemen di dalam collection, yang diakses dengan menggunakan subscript-subscript, field-field di dalam record diakses melalui namanya. Untuk mereferensi field-field tunggal, kita menggunakan notasi titik dan sintaks berikut:

record_name.field_name

Sebagai contoh, kita mereferensi hire_date di dalam record emp_info seperti berikut:

emp_info.hire_date…

Ketika memanggil function yang menghasilkan user-defined record, kita menggunakan sintaks berikut ini untuk mereferensi field-field di dalam record:

function_name(parameter_list).field_name

Sebagai contoh, pemanggilan function nth_highest_sal berikut ini mereferensi field salary di dalam record emp_info:

DECLARE
  TYPE EmpRec IS RECORD (emp_id NUMBER(4), job_title VARCHAR2(9), salary NUMBER(7,2));
  middle_sal NUMBER(7,2);
  FUNCTION nth_highest_sal (n INTEGER) RETURN EmpRec IS
  emp_info EmpRec;
BEGIN
  ...
  RETURN emp_info; -- menghasilkan record
END;
BEGIN
  middle_sal:= nth_highest_sal(10).salary; -- memanggil function
  ...
END;

Ketika memanggil function tanpa parameter, kita menggunakan sintaks:

function_name().field_name - perhatikan parameter kosong

Untuk mereferensi nested fields di dalam record yang dihasilkan oleh function, kita menggunakan notasi titik tambahan. Sintaksnya:

function_name(parameter_list).field_name.nested_field_name

Untuk lebih jelasnya, pemanggilan function item berikut ini mereferensi kepada nested field minutes di dalam record item_info:

DECLARE
  TYPE TimeRec IS RECORD (minutes SMALLINT, hours SMALLINT);
  TYPE AgendaItem IS RECORD (priority INTEGER, subject VARCHAR2(100), duration TimeRec);
  FUNCTION item (n INTEGER) RETURN AgendaItem IS
    item_info AgendaItem;
BEGIN
  ...
  RETURN item_info; -- menghasilkan record
END;
BEGIN
  ...
  IF item(3).duration.minutes > 30 THEN ... -- memanggil function
END;

Juga, kita menggunakan notasi titik tambahan untuk mereferensi attributes dari object yang tersimpan di dalam field, seperti ditunjukkan oleh contoh berikut ini:

DECLARE
  TYPE FlightRec IS RECORD (flight_no INTEGER, plane_id VARCHAR2(10),
  captain Employee, -- mendeklarasikan object
  passengers PassengerList, -- mendeklarasikan varray
  depart_time TimeRec, -- mendeklarasikan nested record
  airport_code VARCHAR2(10));
  flight FlightRec;
BEGIN
  ...
  IF flight.captain.name = 'H Rawlins' THEN ...
END;

5.15.4. Memberikan Nilai-nilai Null Terhadap Records

Untuk mengatur field-field di dalam record menjadi null, secara sederhana kita bisa memberikannya nilai dari record tak terinisialisasi dari tipe yang sama, seperti ditunjukkan oleh contoh berikut ini:

DECLARE
  TYPE EmpRec IS RECORD (emp_id emp.empno%TYPE, job_title VARCHAR2(9),
  salary NUMBER(7,2));
  emp_info EmpRec;
  emp_null EmpRec;
BEGIN
  emp_info.emp_id:= 7788;
  emp_info.job_title:= 'ANALYST';
  emp_info.salary:= 3500;
  emp_info:= emp_null; -- me-null-kan seluruh fields di dalam emp_info
  ...
END;

5.15.5. Memberikan Nilai Kepada Records

Kita dapat memberikan nilai dari ekspresi kepada field tertentu di dalam record dengan menggunakan sintaks berikut ini:

record_name.field_name := expression;

Di dalam contoh berikut ini, kita mengkonversi nama karyawan menjadi huruf besar:

emp_info.ename := UPPER(emp_info.ename);

Dibandingkan harus memberikan nilai-nilai secara terpisah kepada setiap field di dalam record, kita dapat memberikan nilai-nilai kepada seluruh field sekali saja. Hal ini dapat dilakukan dengan dua cara. Pertama, kita dapat memberikan satu user-defined record ke lainnya jika mereka memiliki tipe data yang sama. Memiliki field-field yang sesuai saja tidaklah cukup. Mari kita perhatikan contoh berikut ini:

DECLARE
  TYPE DeptRec IS RECORD (dept_num NUMBER(2), dept_name VARCHAR2(14));
  TYPE DeptItem IS RECORD (dept_num NUMBER(2), dept_name VARCHAR2(14));
  dept1_info DeptRec;
  dept2_info DeptItem;
BEGIN
  ...
  dept1_info := dept2_info; -- tidak boleh; tipe-tipe data berbeda
END;

Seperti ditunjukkan oleh contoh berikutnya, kita dapat memberikan record %ROWTYPE kepada user-defined record jika field-field mereka sesuai di dalam jumlah dan urutannya, serta field-field terkait memiliki tipe-tipe data yang kompatibel:

DECLARE
 TYPE DeptRec IS RECORD (dept_num NUMBER(2), dept_name VARCHAR2(14),
      location VARCHAR2(13));
 dept1_info DeptRec;
 dept2_info dept%ROWTYPE;
BEGIN
  SELECT *
  INTO dept2_info
  FROM dept
  WHERE deptno = 10;
  dept1_info:= dept2_info;
  ...
END;

Kedua, kita dapat menggunakan perintah SELECT atau FETCH untuk mengambil nilai-nilai kolom dan memberikannya ke record, seperti ditunjukkan oleh contoh di bawah ini. Kolom-kolom di dalam select-list harus tampil dengan urutan yang sama dengan field-field di dalam record kita.

DECLARE
  TYPE DeptRec IS RECORD (dept_num NUMBER(2), dept_name VARCHAR2(14),
       location VARCHAR2(13));
  dept_info DeptRec;
BEGIN
  SELECT *
  INTO dept_info
  FROM dept
  WHERE deptno = 20;
  ...
END;

Namun, kita tidak dapat memberikan daftar nilai-nilai kepada record dengan menggunakan perintah pemberian nilai. Sintaks berikut ini tidak diperbolehkan:

record_name := (value1, value2, value3, …); — tidak diperbolehkan

Contoh di bawah ini menunjukkan kepada kita bahwa kita dapat memberikan satu nested record kepada lainnya jika mereka memiliki tipe data yang sama. Pemberian-pemberian nilai seperti ini diperbolehkan bahkan jika record-record yang melingkupinya memiliki tipe-tipe data yang berbeda.

DECLARE
  TYPE TimeRec IS RECORD (mins SMALLINT, hrs SMALLINT);
  TYPE MeetingRec IS RECORD (
  day DATE,
  time_of TimeRec, -- nested record
  room_no INTEGER(4));
  TYPE PartyRec IS RECORD (
  day DATE,
  time_of TimeRec, -- nested record
  place VARCHAR2(25));
  seminar MeetingRec;
  party PartyRec;
BEGIN
  ...
  party.time_of:= seminar.time_of;
END;

5.15.6. Membandingkan Records

Records tidak dapat diuji dalam hal null-nya, kesamaannya, atau ketidaksamaannya. Sebagai contoh, kondisi-kondisi IF berikut ini tidak diperbolehkan:

BEGIN
  ...
  IF emp_info IS NULL THEN ... -- pelanggaran
  IF dept2_info > dept1_info THEN ... -- pelanggaran
END;


 

Pages: 1 2 3 4 5 6 7 8 9 10 11 12

 

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)

 

Related Articles

 

Comments

[…] Silahkan melanjutkan membaca pembahasan Collections dan Records PL/SQL […]

[…] Data PL/SQL - 3,145 viewsPL/SQL Subprograms - 2,742 viewsMengontrol Akses User - 2,717 viewsCollections dan Records PL/SQL - 2,654 viewsMenampilkan Data - 2,572 viewsPendahuluan - 2,555 […]

Leave a comment

(required)

(required)


*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word