[**Belajar SQL**](http://pojokprogrammer.net/tags/belajar-sql) | Dalam database relasional, ada dua hal yang perlu kita pahami, yaitu **normalisasi** data, dan **relasi antar tabel**. Tujuan dari normalisasi adalah menghilangkan rudundansi dan duplikasi data, sehingga kita bisa menghidari kemungkinan masalah saat proses manipulasi data. Aturan-aturan yang harus diikuti pada saat kita mendisain sebuah database agar kita bisa terhindar dari duplikasi data inilah yang disebut normalisasi.

**Bagian pertama dari rangkaian artikel tentang [konsep database relational dan dasar-dasar SQL](http://pojokprogrammer.net/content/konsep-database-relasional-dan-bahasa-sql)**


[**Belajar SQL**](http://pojokprogrammer.net/tags/belajar-sql) | **Bagian pertama dari rangkaian artikel tentang [konsep database relational dan dasar-dasar SQL](http://pojokprogrammer.net/content/konsep-database-relasional-dan-bahasa-sql)**

[Rangkaian artikel](http://pojokprogrammer.net/content/konsep-database-relasional-dan-bahasa-sql) ini ditujukan untuk teman-teman yang ingin mempelajari SQL namun masih baru atau belum memahami sepenuhnya tentang konsep database relasional dan cara memanfaatkan dan membuat SQL dengan baik. Pada artikel pertama ini, pembahasan akan difokuskan pada konsep dasar database relasional dan beberapa hal mendasar yang harus diketahui jika kita ingin membuat sebuah perintah SQL.

### Bagaimana Data Anda Tersimpan di database

Kemampuan kita untuk **memvisualisasikan** bagaimana data tersimpan di database menjadi syarat penting agar kita dapat **menemukembalikan (*retrieve*) data** tersebut dengan mudah dan cepat. Pada saat kita mengambil uang di mesin ATM pada dasarnya kita sedang membaca dan mengubah data tabungan kita di bank. Pada saat kita memesan barang atau membeli tiket secara online pada dasarnya kita juga sedang membaca dan mengubah data. Jadi apapun yang kita lakukan secara elektronis sangat mungkin pada saat yang bersamaan kita sedang berinteraksi dengan database relasional.

Sebuah database relasional menyimpan data dalam bentuk matrix dua dimensi yang kita kenal sebagai **table**. dan setiap table memiliki baris (*row*) dan kolom (*column*). Sedangkan ***Relational Database Management System (RDBMS)*** adalah perangkat lunak yang kita gunakan untuk mengelola data tersebut. RDBMS membantu kita dalam proses pembacaan dan pengubahan data yang tersimpan tanpa kita perlu tahu dimana lokasi data tersebut tersimpan. Yang kita perlukan hanyalah nama table, kolom dan baris mana yang kita perlukan, dan RDBMS akan menemukembalikan-nya (*retrieve*) untuk kita.

Setiap *table* dalam database relasional memiliki nama yang unik untuk membedakan dengan *table* lainnya dalam ***schema*** yang sama. ***Schema*** sendiri adalah kumpulan obyek-obyek – salah satunya *table* – dalam database yang memiliki fungsi bisnis yang sama. Obyek-obyek lainya dapat berupa index, stored procedure, dan lain-lain. Sebagai contoh table *karyawan*, *departemen*, dan *payroll* bisa disatukan dalam satu *schema HR*.

![Struktur database relasional](http://pojokprogrammer.net/sites/default/files/pictures/database/postgres-03.png)

**Gambar 1**: Anatomi tabel database relasional

Setiap *table* minimal memiliki satu kolom, dan tiap-tiap kolom memiliki **tipe data** tertentu sesuai dengan data yang yang ingin disimpan, misalkan untuk menyimpan angka bulat bisa bertipe data integer, dan angka pecahan bisa bertipe data *double* atau *float*. Dan setiap baris dalam sebuah table merepresentasikan sebuah kumpulan data yang unik, berbeda dengan baris yang lain. Setiap kolom dalam sebuah row kita sebut field, dan field bisa saja memiliki nilai tertentu atau tidak memiliki nilai, yang biasa kita sebut *NULL*. *NULL* bukan berarti kosong, spasi, atau nol, tapi *NULL* menandakan ketiadaan nilai dalam field.

### Kunci Relasi yang Baik dan Benar

Sebuah **baris (*row*)** dalam sebuah table **harus bersifat unik**, artinya berbeda dibandingkan dengan seluruh baris lainnya dalam sebuah table yang sama. Misalkan dalam table KARYAWAN seperti contoh di atas, pada suatu saat ada karyawan yang baru saja masuk dan kebetulan bernama Nur Hidayat dan lahir pada tanggal yang sama 26-Sep-1970, maka baris yang sudah ada sebelumnya tidak lagi unik ketika karyawan baru ini masuk. Terjadi **duplikasi data**, namun sebenarnya bukan duplikat karena kita sama-sama tahu bahwa dua baris data tersebut adalah milik dua karyawan yang berbeda. Untuk mengatasi hal ini kita memerlukan sebuah kolom tambahan untuk memastikan bahwa data akan tetap unik meskipun ada karyawan baru yang masuk dengan nama dan tanggal bekerja (*hire date*) yang sama.

![Duplikasi data tanpa adanya primary key](http://pojokprogrammer.net/sites/default/files/pictures/database/postgres-04.png)

**Gambar 2**: Duplikasi data tanpa adanya *primary key*

**Solusinya** adalah primary key. ***Primary key*** adalah sebuah kolom yang dapat memastikan keunikan dari seluruh baris (rows) dalam sebuah table. Ketika sebuah kolom primary key ditambahkan, maka dua buah baris berisikan data *Nur Hidayat* tersebut akan menjadi berbeda, karena baris yang satu memiliki nilai EMPLOYEE_ID 100, dan baris lainnya memiliki nilai EMPLOYEE_ID 101, seperti tampak pada contoh di bawah ini.

![Mengatasi duplikasi data menggunakan primary key](http://pojokprogrammer.net/sites/default/files/pictures/database/postgres-05.png)

**Gambar 3**: Mengatasi duplikasi data menggunakan *primary key*

**Perhatikan** bahwa nilai yang terdapat dalam field EMPLOYEE_ID tidak ada hubungannya sama sekali dengan data dalam row (record) bersangkutan. Primary key seperti ini umumnya angka berurutan (*sequential numbner*) yang dihasilkan oleh sistem (*system-generated*), dan karena dia tidak ada hubungannya dengan data dalam row tersebut, biasanya *key* ini disebut sebagai ***synthetic key*** atau ***surrogate key***. Keuntungan *key* jenis ini adalah kemudahan kita memastikan keunikan setiap row karena sifatnya yang dihasilkan oleh sistem (*system-generated*) dan tidak ada kemungkinan berubah nilai (*immutable*). Dan sangat penting memilih sebuah primary key yang **nilainya tidak pernah berubah**, karena perubahan nilai primary key akan sangat sulit dikelola.

Setiap *table* hanya boleh memiliki sebuah primary key, yang bisa terdiri atas satu atau beberapa field sekaligus. *Primary key* yang terdiri dari beberapa (lebih dari satu) field s=disebut sebagai ***composite key***. Usahakan setiap table memiliki primary key, walaupun bisa jadi ada saja kasus khusus kita tidak memerlukan *primary key*.

### Berelasi dengan *Table* lain

Sesuai dengan namanya – Relational Database Management System – maka **kita bisa merelasikan** (menghubungkan) satu table dengan table lainnya. Penghubungnya adalah ***foreign key***, yaitu sebuah (atau beberapa) kolom yang nilainya berdasarkan isi dari sebuah (atau beberapa) kolom yang merupakan *primary key* di *table* lain. Hubungan antara *primary key* dan *foreign key* inilah yang membuat data yang tersimpan di database kita **rapih dan teratur**

Sebagai contoh, bisa saja kita menambahkan sebuah kolom teks untuk menyimpan nama departemen tempat seorang karyawan ditugaskan. Bisa kita pastikan jika ada beberapa karyawan yang bertugas di departemen yang sama maka kita akan melihat beberapa baris data memiliki nilai foeld departemen yang sama. Dan jika suatu saat ada perubahan kebijakan perusaan di mana nama departemen tersebut berubah, maka kita harus mengubah semua baris yang berisikan departemen tersebut.

Namun, jika kita memisahkan table *EMPLOYEE* dan *DEPARTMENT* ke dalam dua table terpisah, maka kita bisa membuat sebuah relasi antara kedua table terbut menggunakan *foreign key*, sehingga ketika kita perlu mengubah nama departemen yang ada maka kita cukup mengubah satu baris saja di table *DEPARTMENT*. Sebagai contoh adalah kita buat kolom *DEPARTMENT_ID* di table *EMPLOYEE* menjadi *foreign key* yang mengacu pada kolom *DEPARTMENT_ID* yang ada di table *DEPARTMENT*. Kita bisa menemukan nama departemen tempat seorang karyawan ditugaskan dengan melihat field *DEPARTMENT_ID* dan kemudian mencari baris dalam table *DEPARTMENT* yang memiliki nilai *DEPARTMENT_ID* yang sama.

![Relasi antara tabel EMPLOYEE dengan tabel DEPARTMENT](http://pojokprogrammer.net/sites/default/files/pictures/database/postgres-06.png)

**Gambar 4**: Relasi antara tabel EMPLOYEE dengan tabel DEPARTMENT

### Lebih Sedikit, Lebih Baik – Normalisasi

Dalam database relasional, ada dua hal yang perlu kita pahami, yaitu **normalisasi** data, dan **relasi antar tabel**. Tujuan dari normalisasi adalah menghilangkan rudundansi dan duplikasi data, sehingga kita bisa menghidari kemungkinan masalah saat proses manipulasi data. Aturan-aturan yang harus diikuti pada saat kita mendisain sebuah database agar kita bisa terhindar dari duplikasi data inilah yang disebut normalisasi.

Ada banyak bentuk normalisasi, namun normalisasi yang paling umum dikenal adalah 1NF (*Normal Form*) sampai 6NF, dan BCNF. Berdasarkan pengalaman penulis, kebanyakan programmer, analis, dan designer hanya (atau merasa cukup) melakukan normalisasi sampai dengan 3NF saja. Namun itu sepenuhnya tergantung dari si *database designer*.

Pertama-tama, untuk mengubah sebuah tabel menjadi bentuk ***normalisasi 1NF***, maka semua grup kolom/attribut yang berulang harus dipindahkan ke tabel baru. Contoh kasus seperti pada contoh di bawah ini terdapat beberapa kolom lokasi kantor untuk menyimpan informasi karyawan yang bekerja di beberapa lokasi sekaligus.

![Data Karyawan dan Office Location](http://pojokprogrammer.net/sites/default/files/pictures/database/postgres-08.png)

**Gambar 5**: Data Karyawan dan Office Location

Jika kita perhatikan, tersedia 3 (tiga) buah kolom yang bisa digunakan lokasi kantor tempat si karyawan bekerja. Namun bagaimana jika suatu saat ada karyawan yang bekerja di lebih dari 3 (tige) tempat? Apakah kita harus menambahkan satu kolom tambahan lagi?

Untuk menghindari problem seperti ini, maka kita buatkan sebuah tabel baru bernama *EMPLOYEE_LOCATION* dengan menggunakan kolom EMPLOYEE_ID sebagai foreign key yang mengacu ke tabel *EMPLOYEE*, seperti tampak pada gambar di bawah ini.

![Pemisahan Data Karyawan dan Office Location namun belum memenuhi normalisasi 2NF](http://pojokprogrammer.net/sites/default/files/pictures/database/postgres-11.png)

**Gambar 6**: Pemisahan Data Karyawan dan Office Location namun belum memenuhi normalisasi 2NF

Bentuk ***normalisasi 2NF*** berhubungan dengan erat dengan tabel yang memiliki *composite key* dimana *primary key* tabel tersebut tersusun dari dua kolom atau lebih. Dalam 2NF, semua kolom laiannya harus bergantung pada keseluruhan key, dan bukan bergantung hanya pada salah satu kolom dalam *composite key* tersebut.

Tabel *EMPLOYEE_LOCATION* memeiliki kombinasi kolom *EMPLOYEE_ID* dan *OFFICE* sebagai *primary key*. Jadi semua kolom tambahan ke tabel *EMPLOYEE_LOCATION* harus bergantung kepada kombinasi dua kolom tersebut. Pada gambar berikut ini belum memenuhi bentuk normalisasi 2NF karena kolom *OFFICE_PHONE_NUMBER* hanya bergantung pada kolom *OFFICE* saja dan tidak ada hubungannya dengan kolom *EMPLOYEE_ID*. Agar dapat memenuhi bentuk normalisasi 2NF, maka kolom *OFFICE_PHONE_NUMBER* tersebut di atas harus dipndahkan ke tabel baru.

![Hasil normalisasi sampai bentuk 2NF](http://pojokprogrammer.net/sites/default/files/pictures/database/postgres-09.png)

**Gambar 7**: Hasil normalisasi 2NF

Setelah normalisasi 2NF dilakukan, maka selanjutnya kita lakukan normalisasi 3NF, dimana semua kolom yang bukan kunci (*key*) harus merupakan detil, fakta, dan bergantung hanya pada *primary key*. Jika sebuah kolom bergantung kepada kolom lain yang bukan *primary key* maka kolom tersebut harus dipindahkan ke tabel baru. Sebagai contoh gambar di bawah ini menyalahi bentuk normalisasi 3NF, karena kolom *DEPARTMENT_NAME* bergantung pada kolom *DEPARTMENT_ID*, bukan ke *primary key EMPLOYEE_ID*.

![Relasi transitif terhadap kolom employee_id -> dept_id -> dept_name menyalahi bentuk normalisasi 3NF](http://pojokprogrammer.net/sites/default/files/pictures/database/postgres-07.png)

**Gambar 8**: Relasi transitif terhadap kolom *employee_id* -> *dept_id* -> *dept_name* menyalahi bentuk normalisasi 3NF

Untuk memenuhi bentuk normalisasi 3NF maka kita harus mengubah desain database kita menjadi seperti di bawah ini.

![Hasil normalisasi sampai bentuk 3NF](http://pojokprogrammer.net/sites/default/files/pictures/database/postgres-10.png)

**Gambar 9**: Hasil normalisasi 3NF

### Perintah SQL Pertama Anda

Dengan **perintah SQL** kita bisa mendefinisikan tabel yang akan kita gunakan untuk menyimpan data menggunakan perintah *CREATE*. Perintah seperti ini umumnya dikategorikan sebagai perintah **DDL** (***Data Definition Language***). Selain ini kita pastinya juga bisa menambahkan data baru, mengubah data yang sudah ada, menghapus data, dan membaca (temu kembali = *retrieve*) data yang tersimpan di database, biasa disebut sebagai **DML** (***Data Manupulation Laguage***)

Sebagai contoh, perintah SQL DDL berikut ini digunakan untuk membuat tabel *EMPLOYEE*, sekaligus dengan kolom-kolom (atribut) dan tipe datanya:

CREATE TABLE employee (
  employee_id    INTEGER,
  first_name     VARCHAR(50),
  last_name      VARCHAR(50),
  hire_date      DATE,
  salary         NUMERIC(9,2),
  manager        INTEGER,
  dept_id        INTEGER,
  dept_name      VARCHAR(50),
  office_1       VARCHAR(50),
  office_2       VARCHAR(50),
  office_3       VARCHAR(50)
);

Untuk membaca data yang tersimpan di dalam tabel *EMPLOYEE* maka kita menggunakan perintah *SELECT*. Sebagai contoh jika kita ingin mengambil data nama karyawan dan tanggal mulai bekerjanya, maka kita gunakan perintah SQL DML seperti ini:

SELECT first_name, last_name, hire_date
  FROM employee;

Cukup mudah bukan?

### Simpulan

Artikel ini hanyalah pengenalan tentang organisasi dan struktur data di dalam database relasional. Konsep yang seharusnya sudah Anda pahami antara lain meliputi, tabel, kolom, primary key, foreign key, dan normalisasi.

Perintah SQL DDL lengkap untuk artikel ini dapat dilihat di [github](https://github.com/hidayat365/Belajar-SQL)

.

Leave a Reply

Your email address will not be published. Required fields are marked *