Ebook - Penduan Lengkap Query MySQL [PDF]

  • 0 0 0
  • Suka dengan makalah ini dan mengunduhnya? Anda bisa menerbitkan file PDF Anda sendiri secara online secara gratis dalam beberapa menit saja! Sign Up
File loading please wait...
Citation preview

EKSKLUSIF



PANDUAN QUERY MySQL Tutorial dan referensi lengkap SQL pada MySQL



INSERT



SELECT



TRANSACTION TRIGGERS



SQL



VIEWS DELETE



DDL



Agus Prawoto Hadi



UPDATE EVENTS



CROSSTAB



Panduan Lengkap Query MySQL i



Panduan Lengkap Query MySQL Penulis : Agus Prawoto Hadi Edisi : I (Pertama) Terbit : April 2017 Revisi 1: 17 Juni 2017 Dimensi : 15,7 cm x 23 cm Jumlah Halaman: xix + 519 Hak cipta ada dipenulis, dilarang menyalin dan mempublikasikan sebagian maupun keseluruhan isi dari buku ini tanpa ijin penulis



ii Panduan Lengkap Query MySQL



Kata Pengantar Alhamdulillah, penulis panjatkan kehadirat Allah S.W.T, karena dengan rahmat dan hidayah-Nya penulis dapat menyelesaikan buku “Panduan Lengkap Query MySQL”. Buku ini merupakan panduan bagi mereka yang baru belajar SQL maupun yang sudah mengerti MySQL namun ingin memperkaya referensi tentang SQL Dalam dunia pemrograman, kita tidak akan terlepas dari data, entah itu data statis maupun dinamis. Berbicara masalah data, maka di jaman modern ini, tidak akan terlepas dari database. Salah satu database yang paling populer digunakan di dunia ini adalah MySQL, karena sifatnya yang gratis dan handal untuk berbagai keperluan. Terdapat istilah yang digunakan untuk mengelola database yaitu SQL (Structured Query Language). Dunia SQL merupakan dunia tentang query yang tidak habisnya dibahas. Buku ini membahas secara lengkap berbagai statemen SQL yang sering digunakan dalam praktek. Meskipun ditujukan untuk MySQL, namun pembahasan pada buku ini dapat diterapkan pada database MariaDB. Dengan banyak contoh kasus diharapkan dapat mempermudah pembaca memahami syntax SQL yang dibahas. Penulis menyadari bahwa buku ini masih jauh dari sempurna, untuk itu penulis menerima segala kritik dan saran yang membangun untuk perbaikan di versi berikutnya. Kritik dan saran dapat dikirim ke alamat email penulis di [email protected] Akhir kata semoga buku ini dapat membawa manfaat bagi pembaca. Kudus, April 2017



Penulis



Panduan Lengkap Query MySQL iii



Source Code Buku ini disertai file dump database yaitu toko_buku.sql dan tutorial.sql, silakan load keduanya menggunakan aplikasi database manager seperti HeidiSQL atau phpMyAdmin. Setelah di load, akan terbentuk dua database yaitu toko_buku dan tutorial, di sepanjang buku ini, kita akan sering menggunakan kedua database tersebut secara bergantian. Buku ini menggunakan dua database karena contoh query yang ada kurang memadahi jika menggunakan satu database, sehingga untuk mempraktekkan contoh query pada buku ini, Anda perlu memperhatikan tabel yang digunakan apakah berada di database tutorial atau di database toko_buku. Selain file sql, juga disertakan file .php. File ini merupakan source code script PHP yang digunakan pada pembahasan BAB 29 MySQL dan PHP. Untuk menggunakannya, silakan letakkan file di dalam folder htdocs kemudian akses file tersebut melalui browser. File php tersebut menggunakan konfigurasi koneksi server: localhost, user: root, password: '', jika konfigurasi server MySQL yang Anda gunakan berbeda, edit file .php tersebut sebelum dijalankan



iv Source Code



Code Convention Di dalam buku ini, Anda akan menemukan statemen SQL dimana beberapa bagian dari SQL tersebut tidak wajib ditulis (opsional), atau mengharuskan Anda untuk memilih salah satu opsi. Untuk bagian yang bersifat opsional, ditulis menggunakan tanda kurung siku [], misal: ALTER TABLE nama_tabel RENAME [TO|AS] nama_tabel_baru



Pada contoh query diatas, karena klausa TO dan AS berada di dalam tanda kurung siku, maka keduanya tidak wajib ditulis, sehingga Anda cukup menuliskan: ALTER TABLE nama_tabel RENAME nama_tabel_baru



Anda juga dapat menggunakan salah satunya, misal: ALTER TABLE nama_tabel RENAME TO nama_tabel_baru



Untuk bagian yang harus ada dan kita diharuskan memilih salah satu klausa, tanda yang digunakan adalah kurung kurawal {}, misal: SHOW TRIGGERS {FROM | IN} nama_database



Untuk menggunakan query tersebut, kita harus menggunakan salah satu dari klausa FROM atau IN, misal: SHOW TRIGGERS FROM nama_database



Pada contoh diatas, penggunaan klausa FROM dan IN akan menghasilkan output yang sama, pada query lain, pilihan klausa dapat menghasilkan output yang berbeda.



Panduan Lengkap Query MySQL v



Daftar Isi Kata Pengantar .................................................................................................................... iii Source Code ........................................................................................................................... iv Code Convention ...................................................................................................................v Daftar Isi ................................................................................................................................. vi BAB 1 SQL dan Database .................................................................................................. 1 1.1.



SQL .........................................................................................................................1



1.2.



Database ..............................................................................................................3



1.3.



Database Relasional ........................................................................................3



1.4.



MySQL ...................................................................................................................4



BAB 2 Install MySQL ........................................................................................................... 7 2.1.



Download MySQL.............................................................................................7



2.2.



Install MySQL di Windows ...........................................................................9



2.3.



Menjalankan Query Dengan Command Prompt .............................. 19



BAB 3 Menginstall dan Menggunakan HeidiSQL .................................................. 21 3.1.



Download HeidiSQL ..................................................................................... 21



3.2.



Install HeidiSQL ............................................................................................. 22



3.3 Menjalankan HeidiSQL ........................................................................................ 29 BAB 4 SQL Untuk Database ........................................................................................... 33 4.1.



Membuat database ....................................................................................... 33



4.2.



Memilih Database ......................................................................................... 34



4.3.



Menghapus Database .................................................................................. 35



vi Daftar Isi



4.4.



Mengubah Database .................................................................................... 35



BAB 5 SQL Untuk Tabel ................................................................................................... 37 5.1.



Membuat Tabel .............................................................................................. 37



5.2.



Penamaan Tabel ............................................................................................ 39



5.3.



Opsi Tabel ........................................................................................................ 40



5.3.1.



Storage Engine...................................................................................... 40



5.3.2.



Character Set dan Collation ............................................................ 42



5.3.3.



Auto Increment .................................................................................... 47



5.4.



Mengcopy Tabel ............................................................................................ 48



5.5.



Mengubah Tabel ............................................................................................ 50



5.5.1.



Mengubah Nama Tabel ..................................................................... 50



5.5.2.



Mengubah Opsi Tabel ........................................................................ 51



5.5.2.1.



Mengubah Engine .......................................................................... 51



5.5.2.2.



Mengubah Character Set dan Collation ................................ 51



5.5.2.3.



Mengubah Auto Increment ........................................................ 54



5.5.3.



Mengubah Kolom ................................................................................ 55



5.5.3.1.



Menambah Kolom .......................................................................... 55



5.5.3.2.



Mengubah Nama Kolom dan/atau Kolom Definition ..... 58



5.5.3.3.



Menghapus Kolom ......................................................................... 60



5.6.



Menghapus Tabel .......................................................................................... 60



BAB 6 Tipe Data.................................................................................................................. 63 6.1. 6.1.1.



Numeric............................................................................................................. 63 Exact Value ............................................................................................. 65



Panduan Lengkap Query MySQL vii



6.1.2.



Desimal .................................................................................................... 65



6.1.2.1.



Fixed Point ........................................................................................ 65



6.1.2.2.



Floating Point................................................................................... 67



6.1.3.



BIT ............................................................................................................. 68



6.1.4.



Bool atau Boolean ............................................................................... 69



6.1.5.



Atribut Pada Numeric........................................................................ 70



6.2.



String .................................................................................................................. 72



6.2.1.



CHAR dan VARCHAR.......................................................................... 73



6.2.2.



TEXT vs BLOB ....................................................................................... 75



6.2.3.



ENUM dan SET...................................................................................... 75



6.3.



DATE dan TIME ............................................................................................. 78



6.3.1.



DATE ......................................................................................................... 79



6.3.2.



TIME.......................................................................................................... 80



6.3.3.



YEAR ......................................................................................................... 82



6.3.4.



TIMESTAMP........................................................................................... 82



6.3.5.



DATETIME vs TIMESTAMP............................................................. 84



BAB 7 Constrain ................................................................................................................. 87 7.1.



Constraint DEFAULT ................................................................................... 87



7.2.



NOT NULL ........................................................................................................ 89



7.3.



PRIMARY KEY................................................................................................. 89



7.4.



UNIQUE Key .................................................................................................... 92



7.5.



FOREIGN Key .................................................................................................. 94



7.6.



FOREIGN Key: Referensi Aksi .................................................................. 98



viii Daftar Isi



7.7.



Check Constraint ........................................................................................ 100



7.8.



Memberi Nama Constraint..................................................................... 101



7.9.



Menampilkan Detail Constraint........................................................... 103



7.10.



Mengubah Constraint............................................................................... 106



7.11.



Menghapus Constraint............................................................................. 107



BAB 8 Syntax Dasar Pengambilan Data................................................................. 109 8.1.



Satemen SELECT ........................................................................................ 109



8.2.



Aturan Penulisan Syntax......................................................................... 112



8.3.



Statemen SELECT DISTINCT ................................................................. 113



8.4.



WHERE ........................................................................................................... 114



8.5.



GROUP BY...................................................................................................... 114



8.6.



ORDER BY ..................................................................................................... 116



8.7.



HAVING .......................................................................................................... 117



8.8.



LIMIT ............................................................................................................... 120



8.9.



Mendefinisikan Nama Tabel.................................................................. 122



8.10.



Alias ................................................................................................................. 123



8.10.1.



Kolom Alias ......................................................................................... 124



8.10.2.



Tabel Alias ........................................................................................... 125



BAB 9 Operator................................................................................................................ 127 9.1.



Operator Aritmetika ................................................................................. 127



9.1.1.



Operator prioritas ............................................................................ 128



9.1.2.



Operator Penjumlahan................................................................... 128



9.1.3.



Operator Minus atau Operator Pengurangan ...................... 129



Panduan Lengkap Query MySQL ix



9.1.4.



Operator Perkalian .......................................................................... 130



9.1.5.



Operator Pembagian ....................................................................... 130



9.1.6.



Operator Modulo .............................................................................. 131



9.1.7.



Operator DIV ...................................................................................... 132



9.2.



Operator Pembanding ............................................................................. 133



9.3.



Operator Logika.......................................................................................... 134



9.4.



Operator IN................................................................................................... 137



9.5.



Operator BETWEEN ................................................................................. 138



9.6.



Operator NOT .............................................................................................. 139



9.7.



Operator LIKE ............................................................................................. 141



9.8.



Mengevaluasi NULL .................................................................................. 144



BAB 10 JOIN Pada MySQL ........................................................................................... 147 10.1.



Prinsip Dasar JOIN..................................................................................... 147



10.2.



Jenis JOIN ....................................................................................................... 148



10.2.1.



INNER JOIN Atau CROSS JOIN ..................................................... 148



10.2.2.



OUTER JOIN ........................................................................................ 149



10.2.2.1.



LEFT OUTER JOIN atau LEFT JOIN ................................. 149



10.2.2.2.



RIGHT OUTER JOIN atau RIGHT JOIN ........................... 153



10.2.2.3.



FULL OUTER JOIN .................................................................. 154



10.2.3.



Menghafal JOIN ................................................................................. 155



10.3.



Join Banyak Tabel ...................................................................................... 156



10.4.



Klausa USING dan NATURAL JOIN ..................................................... 157



10.4.1.



x Daftar Isi



Klausa USING ..................................................................................... 157



10.4.2.



Natural JOIN ....................................................................................... 158



10.5.



Pendefinisian Tabel dan Penggunaan Alias .................................... 160



10.6.



Self Join........................................................................................................... 161



10.7.



Join Dengan Kondisi Tertentu .............................................................. 162



10.8.



Implisit JOIN ................................................................................................. 166



BAB 11 Manipulasi Data: INSERT, UPDATE, dan DELETE ............................ 169 11.1.



Menambahkan Data .................................................................................. 169



11.1.1.



Mendefinisikan Nama Kolom ...................................................... 169



11.1.2.



Tanpa Mendefinisikan Nama Kolom ........................................ 170



11.1.3.



Kolom Dengan Nilai Default ........................................................ 172



11.1.4.



Memasukkan Data Turunan ........................................................ 173



11.1.5.



Memasukkan Banyak Data Dengan Satu Statemen ........... 176



11.1.6.



Alternatif Syntax ............................................................................... 177



11.1.7.



Pembatasan Panjang Data ............................................................ 178



11.2.



Statemen UPDATE ..................................................................................... 179



11.2.1.



UPDATE Semua Baris ..................................................................... 179



11.2.2.



UPDATE Baris Tertentu................................................................. 181



11.2.3.



UPDATE Baris Berdasarkan Nilai Pada Kolom Lain .......... 182



11.2.4.



UPDATE Baris Berdasarkan Query Tertentu ....................... 184



11.3.



Statemen DELETE...................................................................................... 186



11.3.1.



Menghapus Data Pada Tabel ....................................................... 186



11.3.2.



Menghapus Data Lebih Dari Satu Tabel.................................. 187



11.3.3.



Menghapus Semua Baris ............................................................... 188



Panduan Lengkap Query MySQL xi



BAB 12 Functions ........................................................................................................... 191 12.1.



Mengenal Fungsi ........................................................................................ 191



12.2.



Fungsi Karakter .......................................................................................... 192



12.2.1.



Fungsi LEFT ....................................................................................... 193



12.2.2.



Fungsi RIGHT .................................................................................... 193



12.2.3.



Fungsi SUBSTRING, SUBSTR, dan MID................................... 195



12.2.4.



Fungsi TRIM, LTRIM, dan RTRIM ............................................. 198



12.2.5.



Fungsi UPPER dan LOWER ......................................................... 199



12.2.6.



Fungsi CONCAT dan CONCAT_WS............................................. 200



12.3.



Fungsi Komposit ........................................................................................ 204



12.4.



Fungsi Date/Time ...................................................................................... 205



12.4.1.



Fungsi NOW() dan CURDATE() .................................................. 206



12.4.2.



Fungsi DATE_FORMAT() ............................................................... 207



12.4.3.



Fungsi STR_TO_DATE() ................................................................. 210



12.4.4.



Fungsi DAY(), MONTH(), dan YEAR() ..................................... 214



12.5.



Fungsi Perbedaan Waktu ....................................................................... 216



12.5.1.



Fungsi DATEDIFF() ......................................................................... 216



12.5.2.



Fungsi TIMEDIFF() .......................................................................... 217



12.5.3.



Fungsi TIMESTAMPDIFF() ........................................................... 219



12.6.



Fungsi Numeric (Angka) ......................................................................... 220



12.6.1.



Fungsi ROUND ................................................................................... 221



12.6.2.



Fungsi FLOOR()................................................................................. 222



12.6.3.



Fungsi CEIL ......................................................................................... 223



xii Daftar Isi



12.6.4.



Fungsi RAND ...................................................................................... 224



12.6.5.



Fungsi POW() dan POWER() ....................................................... 227



12.6.6.



Fungsi CAST() .................................................................................... 227



BAB 13 Agregate Functions........................................................................................ 235 13.1.



Jenis Fungsi Agregasi ............................................................................... 235



13.1.1.



Fungsi COUNT.................................................................................... 236



13.1.2.



Fungsi SUM ......................................................................................... 237



13.1.3.



Fungsi MIN .......................................................................................... 238



13.1.4.



Fungsi MAX ......................................................................................... 239



13.1.5.



Fungsi AVG .......................................................................................... 240



13.2.



Menggunakan klausa DISTINCT .......................................................... 240



13.3.



Fungsi Agregasi Dengan GROUP BY................................................... 240



13.4.



Fungsi Agregasi Dengan ORDER BY................................................... 242



13.5.



Fungsi Agregasi Dengan Having .......................................................... 243



13.6.



Fungsi Agregasi Dengan Limit.............................................................. 244



13.7.



Fungsi Agregasi Dengan Hasil NULL ................................................. 244



BAB 14 Ekspresi Logika ............................................................................................... 247 14.1.



Ekspresi Logika IF ..................................................................................... 247



14.1.1.



Fungsi IF............................................................................................... 247



14.1.2.



Nested IF .............................................................................................. 251



14.1.3.



Statemen IF ......................................................................................... 253



14.2.



Ekspresi CASE ............................................................................................. 254



14.3.



Ekspresi CASE Pada ORDER BY ........................................................... 259



Panduan Lengkap Query MySQL xiii



14.4.



Ekspresi CASE Pada WHERE................................................................. 261



BAB 15 Subquery ............................................................................................................ 263 15.1.



Pengelompokan Subquery ..................................................................... 264



15.2.



Subquery Sebagai Data ............................................................................ 265



15.3.



Subquery Sebagai Kriteria ..................................................................... 274



15.3.1.



Subquery Dengan Hasil Satu Row ............................................. 274



15.3.2.



Subquery Dengan Hasil Lebih Dari Satu Row ...................... 276



15.3.2.1.



Subquery Dengan Operator IN, = ANY, dan = SOME277



15.3.2.2.



Subquery Dengan Operator NOT .................................... 279



15.3.3.



Subquery Berkorelasi (Correlated Subquery) ...................... 280



15.3.3.1.



Subquery Dengan Operator EXISTS ............................... 282



15.3.3.2.



Subquery Dengan Operator NOT EXISTS .................... 284



15.4.



Subquery Sebagai Calculated Column ............................................... 285



15.5.



Peningkatan Performa ............................................................................. 288



BAB 16 UNION ................................................................................................................. 289 16.1.



Query UNION dan UNION ALL ............................................................. 291



16.2.



Precedence ................................................................................................... 294



16.3.



UNION Dengan Kolom Yang Berbeda................................................ 296



16.4.



Menggunakan ORDER BY Pada Statemen SELECT ...................... 297



16.5.



Menggunakan LIMIT pada Statemen SELECT ............................... 300



16.6.



Menggunakan JOIN Pada Statemen SELECT .................................. 302



BAB 17 Total dan Subtotal .......................................................................................... 305 17.1.



WITH ROLLUP ............................................................................................. 305



xiv Daftar Isi



17.2.



WITH ROLLUP - Mengganti Nilai NULL............................................ 311



17.3.



WITH ROLLUP dengan ORDER BY ..................................................... 314



17.4.



WITH ROLLUP dengan LIMIT ............................................................... 317



BAB 18 Crosstab - Pivot Table .................................................................................. 319 18.1.



Crosstab Sederhana .................................................................................. 319



18.2.



Menambahkan Baris Subtotal .............................................................. 322



18.3.



Mengubah Urutan Data Pivot Table ................................................... 323



18.4.



Menambah Baris Total Dengan Query Tersendiri ....................... 325



18.5.



Pivot Table Dinamis .................................................................................. 326



BAB 19 FULL TEXT Search ......................................................................................... 335 19.1.



Engine dan Tipe Data ............................................................................... 336



19.2.



Membuat Index ........................................................................................... 336



19.3.



Menjalankan Full-Text Search .............................................................. 338



19.4.



Natural Language Mode .......................................................................... 340



19.5.



Boolean Mode .............................................................................................. 343



19.6.



Query Expansion ........................................................................................ 347



BAB 20 Variable .............................................................................................................. 351 20.1.



Penulisan User-Defined Variable ........................................................ 351



20.2.



Karakteristik User-Defined Variable ................................................. 353



20.3.



Deklarasi Variable Dengan SET dan SELECT ................................. 354



20.4.



Berbagai Contoh Penggunaan Variable ............................................ 356



20.5.



Variable Sebagai Identifier .................................................................... 361



BAB 21 Views ................................................................................................................... 363



Panduan Lengkap Query MySQL xv



21.1.



Memahami View......................................................................................... 363



21.2.



Kelebihan dan Kekurangan View ........................................................ 364



21.3.



Membuat View ............................................................................................ 366



21.4.



Memanggil View ......................................................................................... 368



21.5.



Mengubah View Dengan Klausa OR REPLACE .............................. 370



21.6.



Membuat View Dengan Column List ................................................. 371



21.7.



Perubahan Pada Base Table .................................................................. 373



21.8.



Mengubah Nama View dan Statemen SELECT .............................. 373



21.9.



Menghapus View ........................................................................................ 375



21.10. Menampilkan Struktur View ................................................................. 376 21.11. Updatable dan Insertable View............................................................ 378 BAB 22 Stored Procedures ......................................................................................... 385 22.1.



Membuat Stored Procedure .................................................................. 387



22.2.



Membuat Stored Procedure Dengan Parameter .......................... 388



22.3.



Memanggil Stored Procedure ............................................................... 390



22.4.



Stored Procedure dengan Parameter IN, OUT, dan INOUT ..... 392



22.5.



Stored Procedure Dengan Variabel .................................................... 396



22.6.



Statemen IF dan CASE Pada Stored Procedure ............................. 398



22.7.



Parameter Tambahan (Optional) Pada Stored Procedure ....... 403



22.8.



Menampilkan Stored Procedure Yang Ada Pada Database...... 406



22.9.



Mengubah Stored Procedure ................................................................ 408



22.10. Menghapus Stored Procedure .............................................................. 409 BAB 23 Stored Function............................................................................................... 411



xvi Daftar Isi



23.1.



Membuat Stored Function ..................................................................... 411



23.2.



Stored Function Dengan Lebih Dari Satu Statemen Return .... 413



23.3.



Menampilkan Semua Stored Function .............................................. 415



23.4.



Mengubah Stored Function ................................................................... 417



23.5.



Menghapus Stored Function ................................................................. 417



23.6.



Stored Procedure atau Stored Function ? ....................................... 418



BAB 24 Transaction ....................................................................................................... 419 24.1.



Memahami Transaksi............................................................................... 419



24.2.



Membuat Transaksi .................................................................................. 420



24.3.



Membuat Transaksi Dengan Autocommit....................................... 423



24.4.



Menggunakan SAVEPOINT .................................................................... 426



24.5.



Otomasi ROLLBACK .................................................................................. 428



24.6.



Membuat Transaksi (Lanjutan) ........................................................... 431



24.7.



Store Engine Yang Digunakan .............................................................. 436



24.8.



Isolasi Transaksi......................................................................................... 437



BAB 25 Trigger ................................................................................................................ 441 25.1.



Membuat Trigger ....................................................................................... 441



25.2.



Multiple Trigger.......................................................................................... 449



25.3.



Error Pada Trigger .................................................................................... 450



25.4.



Integrity Constrain Dengan Trigger................................................... 451



25.5.



Menghentikan Eksekusi Statemen Pada Trigger.......................... 453



25.6.



Menampilkan Semua Trigger................................................................ 454



25.7.



Mengubah Trigger ..................................................................................... 456



Panduan Lengkap Query MySQL xvii



25.8.



Menghapus Trigger ................................................................................... 456



BAB 26 EVENT ................................................................................................................. 457 26.1.



Mengaktifkan Event Schedule .............................................................. 457



26.2.



Event Dengan Multi Statemen .............................................................. 464



26.3.



Auto Delete Event ...................................................................................... 467



26.4.



Status EVENT dan Comment ................................................................. 468



26.5.



Menampilkan Semua EVENT ................................................................ 469



26.6.



Mengubah EVENT ...................................................................................... 471



26.7.



Menghapus Event ...................................................................................... 472



26.8.



Log Event ....................................................................................................... 472



26.9.



Backup Event ............................................................................................... 474



BAB 27 DATA DICTIONARY ....................................................................................... 477 27.1.



Tabel Schemata ........................................................................................... 478



27.2.



Tabel Tables ................................................................................................. 479



27.3.



Tabel Columns............................................................................................. 480



27.4.



Tabel Routines ............................................................................................ 481



BAB 28 Identifikasi Error Pada Query ................................................................... 483 BAB 29 MySQL dan PHP .............................................................................................. 501 29.1.



Install PHP .................................................................................................... 501



29.2.



Menulis Script PHP.................................................................................... 502



29.3.



Koneksi Database MySQL ....................................................................... 503



29.4.



Memilih Database ...................................................................................... 504



29.5.



Statemen SELECT Dengan Hasil Satu Baris .................................... 506



xviii Daftar Isi



29.6.



Statemen SELECT Dengan Hasil Banyak Baris .............................. 508



29.7.



Tes Nilai NULL............................................................................................. 511



29.8.



Membuat Stored Procedure .................................................................. 513



29.9.



Membuat Transaksi .................................................................................. 516



29.10. Lintas Database .......................................................................................... 517 DAFTAR PUSTAKA ......................................................................................................... 519



Panduan Lengkap Query MySQL xix



BAB 1 SQL dan Database SQL dan database merupakan dua hal yang tidak dapat dipisahkan karena kita perlu SQL untuk mengeksplorasi database. Pada BAB ini, kita akan membahas secara singkat kedua istilah tersebut sehingga Anda memiliki gambaran umum mengenai hal-hal yang akan dibahas dalam buku ini.



1.1. SQL SQL (Structured Query Language) yang dibaca “sequel” adalah bahasa standar yang digunakan untuk berkomunikasi dengan database relasional, dengan kata lain, SQL merupakan bahasa yang digunakan user untuk berinteraksi dengan database. SQL pertaama kali dibuat oleh IBM sekitar tahun 1970. Bahasa tersebut awalnya dikembangkan untuk DB2 produk dari IBM (RDBMS yang saat ini masih eksis dan masih tersedian di pasaran). Tahun 1979, Relation Software (yang kemudian berubah nama menjadi ORACLE - saat ini menjadi salah satu leader teknologi database relational) merelease produk pertamanya yaitu ORACLE. Terdapat dua oraganisasi besar yang menangani tentang standard, yaitu American National Standards Organization (ANSI) dan International Standards Organization (ISO). Tahun 1986, ANSI mempublikasikan standar SQL yang pertama berdasarkan implementasi SQL yang dilakukan oleh IBM, standar ini sering disebut SQL1. Tahun 1987, SQL Standar ANSI diakui sebagai standar internasional. Oleh ISO, standar ini sering disebut SQL-86, sehingga SQL1 sama dengan SQL-86. Standar tersebut kemudian direvisi di tahun 1992 (SQL-92 atau SQL2) dan 1999 (SQL-99). Standar terbaru adalah SQL-2011 yang secara resmi ditetapkan pada Desember 2011. MySQL sendiri telah mengadopsi berbagai standar SQL (seperti umunya database lain), namun demikian, tidak ada database yang benar benar menerapkan standar SQL secara penuh, mereka menambah berbagai fitur pada SQL yang mereka gunakan. Meskipun berbagai vendor memiliki Panduan Lengkap Query MySQL 1



interpretasi sendiri sendiri terhadap standar SQL, mereka tetap menggunakan bahasa dasar yang sama. Secara umum, terdapat tiga komponen utama bahasa SQL. Yang pertama adalah DML atau Data Manipulation Language. Seperti arti “Data Manipulation” yaitu manipulasi data, modul ini memungkinkan kita untuk memanipulasi data, baik mengambil, menambah, mengubah, dan menghapus data pada database, seperti penggunaan statemen SELECT, UPDATE, INSERT, dan DELETE. Yang kedua adalah DDL atau Data Definition Language. Seperti arti “Data Definition” yaitu mendefinisikan data, modul ini memungkinkan kita membuat atau memodifikasi tabel dan database, misal statemen CREATE, DROP, atau ALTER. Yang ketiga adalah DCL, atau Data Control Language, yang berfungsi untuk memastikan (meng kontrol) data yang dimasukkan telah sesuai dengan tipe data yang disyaratkan. Terkadang, terdapat kerancuan antara SQL dengan software database. Software database ini sering disebut sql database, karena memang bahasa SQL terutama digunakan untuk memanage dan mengakses data pada database. Beberapa vendor malah menambahkan kata SQL pada produk mereka, seperti Microsoft SQL Server 2016, MySQL, PosgreSQL, dll. Faktanya, SQL hanyalah bahasa bukan database. Sebagai bahasa komputer, SQL berbeda dengan bahasa pemrograman yang umum kita kenal seperti Visual Basic, C++, PHP, dll, bahasa semacam ini secara default memiliki model struktural, yang artinya memungkinkan kita untuk menentukan prosedur untuk menyelesaikan suatu tugas, sedangkan SQL lebih ke model deklaratif, dimana deklarasi perintah ditujukan untuk mendapatkan output tertentu, contoh lain bahasa deklaratif adalah HTML dan CSS. Karena berbentuk deklaratif, maka kita tidak bisa berharap bisa melakukan pemrograman logika yang rumit pada SQL. Saat ini SQL tidak bisa lagi disebut sebagai bahasa deklaratif murni, karena, sejak 1990, berbagai vendor database, termasuk MySQL menambahkan ekstensi yang memungkinkan user untuk melakukan pemrograman prosedural dengan SQL, seperti pada objek database 2 BAB 1 SQL dan Database



berupa Trigger dan Stored Procdure, selain itu statemen logika dan perulangan seperti IF-ELSE dan DO-WHILE juga ditambahkan. Meskipun bahasa SQL yang umum dikenal dan digunakan bukan berbentuk prosedural, namun saat ini SQL bisa berbentuk “hybrid” yang artinya bisa berbentuk deklaratif atau prosedural.



1.2. Database Secara sederhana, database dapat diartikan sekumpulan catatan atau file yang terorganisir untuk tujuan tertentu. Mungkin kita tidak menyadari bahwa dalam keseharian, kita sering berinteraksi dengan database. Kita mungkin mencatat nama dan alamat semua teman, relasi, atau pelanggan, atau mungkin kita memiliki sekumpulan file dimana kita menyimpan semua data rekening, arus kas, hutang, dan piutang, semua ini adalah contoh bentuk database. Ketika kita bekerja dengan Microsoft Office, kita kelompokkan file office kita berdasarkan topik tertentu, hal tersebut juga merupakan salah satu bentuk lain dari database. Jika Anda sangat terorganisir, mungkin Anda dapat mengorganisir beberapa ratus file excel dan shortcut menggunakan folder dan subfolder. Ketika Anda melakukan ini, maka Anda sudah bisa disebut database manager. Tetapi, apa yang terjadi jika masalah yang Anda hadapi terlalu besar? Bagaimana Anda dapat memperoleh informasi semua pelanggan dan apa yang dipesannya dengan mudah jika data disimpan dalam beberapa file excel? Bagaimana Anda dapat menjaga hubungan antar data antar file excel jika ada informasi baru yang masuk? Bagaimana Anda memastikan bahwa data telah dimasukkan dengan benar? dan berbagai pertanyaan besar lainnya. Jika sudah demikian, maka Anda perlu sebuah Database Management System (DBMS).



1.3. Database Relasional Hampir semua modern Database Management System (DBMS) menyimpan dan mengelola informasi menggunakan model manajemen database relasional (Relational Database Management System – (RDBMS). Dalam RDBMS, sistem menyimpan dan mengelola semua data Panduan Lengkap Query MySQL 3



dalam bentuk tabel. Tabel menyimpan informasi tentang suatu subjek (seperti pelanggan atau produk) dan memiliki kolom (field) yang berisi berbagai jenis informasi tentang subjek tersebut seperti alamat pelanggan, email, dan nomor telepon. Selain kolom, tabel juga memiliki baris (records) yang berisi deskripsi semua atribut dari suatu subjek, seperti data tentang pelanggan dengan id pelanggan tertentu. Selain untuk menyimpan data, tabel juga digunakan untuk menampilkan hasil query. Istilah relational berarti bahwa tiap tabel dapat memiliki hubungan dengan tabel lain. Hubungan ini memungkinkan Anda untuk menampilkan record antar tabel berdasarkan data yang terkait pada tabel tersebut. Selain itu, Anda juga dapat memanipulasi data pada dua tabel (seperti pelanggan dan pesanan) dengan memperlakukannya sebagai satu kesatuan berdasarkan nilai-nilai data yang terkait. Sebagai contoh, akan berlebihan jika kita menyimpan data nama dan alamat pelanggan (yang kita simpan pada tabel pelanggan) pada setiap order yang dilakukan pelanggan (tabel order), dalam RDBMS, data tersebut dapat diwakili oleh field tertentu yang diletakkan pada tabel order, seperti field id pelanggan, yang dengannya, kita dapat menghubungkan tabel order dengan tabel pelanggan sehingga dapat diketahui data pelanggan yang melakukan order.



1.4. MySQL MySQL dikenal sebagai "the world most popular open-source database" yang artinya database open source paling populer di dunia. MySQL telah digunakan oleh jutaan pengguna khususnya pada aplikasi berbasis web. Pengguna database MySQL diantaranya adalah Facebook, Google, Youtube, Alcatel Lucent, dan NASA. Meskipun terkenal digunakan pada website, MySQL juga powerful ketiga digunakan secara offline (tidak terhubung dengan internet). MySQL yang dirilis pertama kali tahun 1995, pertama kali dikembangkan oleh MySQL AB, perusahaan asal Swedia (inilah mengapa default character set dan collation adalah latin_swedish_ci). Setelah rangkaian 4 BAB 1 SQL dan Database



akuisisi (MySQL AB diakuisisi oleh Sun Microsystem dan Sun Microsystem diakuisisi oleh Oracle), sekarang, raksasa database, yaitu ORACLE merupakan pemilik resmi dari MySQL. Oracle mendistribusikan MySQL dengan berbagai edisi yang masing masing memiliki lisensi tersendiri, salah satunya yang free adalah edisi komunitas (Community Edition) dengan lisensi GNU General Public License (GPL) yang dapat didownload di website resminya www.mysql.com. MySQL memiliki model client-server, dimana manajemen database dilakukan secara terpusat oleh sebuah komputer server yang di dalamnya terinstall server MySQL. Komputer server ini bertugas melayani permintaan/request dari client, lokasi client bisa berada dalam komputer server atau komputer lain. MySQL mendukung multithread processing, yang artinya memungkinkan lebih dari satu client terhubung dengan server yang sama dan menjalankan query secara bersamaan. Pada paket instalasi MySQL sudah disertakan database client sederhana berupa dump terminal (command prompt), dengan demikian ketika kita menginstall MySQL, selain menginstall database server, kita juga menginstall database (MySQL) client, sehingga setelah proses instalasi selesai, kita biasa langsung menggunakan database MySQL.



Panduan Lengkap Query MySQL 5



Halaman ini sengaja dikosongkan Jagowebdev.com



6 BAB 1 SQL dan Database



BAB 2 Install MySQL Untuk dapat menjalankan latihan pada buku ini, kita perlu mendownload dan menginstall MySQL. Kita dapat mendownload MySQL Community Edition secara gratis di website www.mysql.com. Paket instalasinya sudah mencakup command line client yang bernama mysql, yang dapat digunakan untuk menjalankan berbagai statemen SQL melalui command prompt. MySQL mendukung banyak platform, pada kesempatan ini , kita hanya membahas instalasi pada Sistem Operasi Windows. Jika komputer Anda sudah terinstall MySQL, Anda dapat melewati bagian ini.



2.1. Download MySQL Sebelum menginstall MySQL, kita perlu mendownload file Installernya. Untuk mendownloadnya, kunjungi halaman https://dev.mysql.com/downloads/installer/, selanjutnya, download file Windows (x86, 32-bit), MSI Installer, pilih mysql-installer-community5.7.17.0.msi dengan ukuran file sekitar 380 Mb, bukan yang mysql-installer-webcommunity-5.7.17.0.msi.



Panduan Lengkap Query MySQL 7



Gambar 2.1 Halaman Download MySQL Pada halaman berikutnya, jika tidak ingin login atau register, langsung saja klik link "No thanks, just start my download".



8 BAB 2 Install MySQL



Gambar 2.2 Halaman Download MySQL Tunggu hingga proses download selesai.



2.2. Install MySQL di Windows Setelah proses download selesai, dobel klik file tersebut untuk memulai proses instalasi. Berikut ini paduan langkah demi langkah menginstall MySQL versi 5.7.17 di Windows 10. Tahap instalasi sama pada versi windows yang lain. STEP 1. Dobel klik file installer .msi untuk memulai proses instalasi. Tunggu beberapa saat hingga muncul jendela MySQL Installer Pada pilihan MySQL Server yang ingin diinstall, pilih sesuai dengan arsitektur Windows yang sedang Anda gunakan, 32 atau 64 bit. Untuk mengetahui arsitektur Windows yang sedang digunakan, klik kanan pada Panduan Lengkap Query MySQL 9



My Computer, atau This PC, kemudian klik properties, selanjutnya akan ada informasi tentang arsitektur windows yang kita gunakan.



Gambar 2.3 Properties Windows Informasi jenis arsitektur ada pada pada bagian System Type. Pada contoh kali ini, penulis menggunakan arsitektur Windows 64-bit. Selanjutnya, klik bagian MySQL Server 5.7.17 – X64 kemudian klik tanda panah kanan, untuk memasukkan ke dalam daftar produk yang akan diinstall.



10 BAB 2 Install MySQL



Gambar 2.4 Memilih Produk Klik Next > Untuk melanjutkan. STEP 2. Klik Execute untuk menginstall MySQL Server



Panduan Lengkap Query MySQL 11



Gambar 2.5 Memulai Proses Instalasi Setelah selesai memilih, klik tombol Execute untuk memulai proses instalasi. Pada proses ini, MySQL akan menginstall file yang diperlukan ke direktori C:\Program Files Tunggu hingga proses instalasi selesai, setelah selesai, klik Next > untuk melanjutkan. Isi dari folder instalasi seperti tampak pada gambar 2.6



Gambar 2.6 Isi Folder Instalasi 12 BAB 2 Install MySQL



STEP 3. Pada jendela konfigurasi Type and Networking, isikan parameter yang ada, atau biarkan apa adanya. Klik Next > untuk melanjutkan. Pada bagian Config type, terdapat tiga pilhan mesin (komputer), yaitu: Developer Machine, Server Machine, atau Dedicated MySQL Server Machine. Pilihan ini akan mempengaruhi penggunaan porsi processor, hardisk, dan memory (RAM). Jika Anda menggunakan pada komputer yang digunakan untuk berbagai keperluan, pilih Development Machine. Jika MySQL dijalankan di komputer bersama dengan server lain dan masih tersedia cukup resource, pilih opsi Server Machine. Pilih Dedicated MySQL Server Machine jika Server MySQL merupakan server utama dan sebagian besar resource komputer dialokasikan untuk server tersebut. STEP 4. Selanjutnya masuk ke bagian Accounts and Roles. Pada bagian ini, kita harus mengisi MySQL Root Password dan Repeat Password. Password ini akan digunakan untuk login dengan user root. Setelah selesai, klik Next > untuk melanjutkan.



Gambar 2.7 Konfigurasi Type and Networking



Panduan Lengkap Query MySQL 13



Pada bagian Config type, terdapat tiga pilhan mesin (komputer), yaitu: Developer Machine, Server Machine, atau Dedicated MySQL Server Machine. Pilihan ini akan mempengaruhi penggunaan porsi processor, hardisk, dan memory (RAM). Jika Anda menginstall pada komputer yang digunakan untuk berbagai keperluan, pilih Development Machine. Jika MySQL dijalankan di komputer bersama dengan server lain dan masih tersedia cukup resource, pilih opsi Server Machine. Pilih Dedicated MySQL Server Machine jika Server MySQL merupakan server utama dan sebagian besar resource komputer dialokasikan untuk MySQL. STEP 4. Selanjutnya masuk ke bagian Accounts and Roles. Pada bagian ini, kita harus mengisi MySQL Root Password. Password ini akan digunakan untuk login dengan user root. Setelah selesai, klik Next > untuk melanjutkan.



Gambar 2.8 Accounts and Roles STEP 5. Selanjutnya masuk ke bagian Windows Service. Installer akan memberikan pilihan apakah ingin menjalankan MySQL Server sebagai service Windows. Jika pilihan ini dicentang, maka MySQL akan menginstal



14 BAB 2 Install MySQL



MySQL service ke Windows system service, selain itu, juga ada pilihan apakah service ini akan dijalankan ketika di Windows mulai di jalankan. Penggunaan service ini memudahkan kita ketika ingin menjalankan dan mematikan MySQL Server, karena berjalan bersamaan dengan Windows, kita tidak perlu menghidupkan dan mematikannya secara manual. Pada contoh kali ini, saya akan membiarkan pilihan apa adanya (Install service di Windows) Klik Next > untuk melanjutkan



Gambar 2.9 Windows Service STEP 6. Selanjutnya, masuk ke bagian Plugins and Extensions yang menawarkan pilihan apakah ingin menjadikan MySQL sebagai Document Store, untuk mudahnya, abaikan opsi ini. Klik Next > untuk melanjutkan.



Panduan Lengkap Query MySQL 15



Gambar 2.10 Plugins and Extensions STEP 7. Masuk kebagian terakhir yaitu Apply Server Configuration, klik Execute untuk menerapkan semua konfigurasi yang telah kita pilih.



16 BAB 2 Install MySQL



Gambar 2.11 Apply Style Configuration Proses ini akan membuat file konfigurasi bernama my.ini yang ada di dalam direktori C:\ProgramData\MySQL\MySQL Server 5.7. Selanjutnya Anda dapat memodifikasi file tersebut menggunakan notepad atau text editor lainnya. Setelah melakukan perubahan, Anda harus merestrart MySQL server untuk melihat perubahan. Selain membuat file konfigurasi, MySQL juga membuat direktori bernama data, yang akan digunakan untuk menyimpan semua file terkait database.



Gambar 2.12 Folder MySQL Pada Program Data Jika Anda mencentang opsi Configure MySQL Server as a Windows Service, maka pada Windows Service akan muncul service dengan nama MySQL 57. Panduan Lengkap Query MySQL 17



Untuk membuka jendela Windows Service, bisa dilakukan dengan mengetikkan kata service pada pencarian Start Menu atau dengan membuka Control Panel kemudian pada bagian pencarian isi kata Services.



Gambar 2.13 Service MySQL pada Windows Service STEP 8. Setelah selesai klik Finish.



Gambar 2.14 Pengaturan Selesai 18 BAB 2 Install MySQL



2.3. Menjalankan Query Dengan Command Prompt Pada saat proses instalasi, MySQL akan menginstall MySQL Command Line Client yang dapat diakses melalui menu Start Menu > Program Files. Ketika dibuka maka akan muncul jendela Command Prompt yang meminta kita untuk memasukkan password. Password ini merupakan password dari user root yang kita isikan pada proses instalasi. Setelah berhasil login, kita coba untuk menjalankan perintah SHOW databases perintah ini akan menampilkan semua database yang ada.



Gambar 2.15 Menampilkan Semua Database Selanjutnya, untuk memilih default database, gunakan perintah USE diikuti nama database, setelah itu, kita dapat menjalankan perintah SQL seperti biasa tanpa menuliskan nama database.



Panduan Lengkap Query MySQL 19



Gambar 2.16 Menjalankan SQL Dengan Command Prompt Setelah selesai, jalankan perintah exit dengan perintah tersebut, sesi (session) akan berakhir dan jendela command prompt akan tertutup. Terdapat banyak cara untuk mengelola database MySQL, yang paling sederhana menggunakan command line seperti contoh diatas. Selain itu terdapat cara lain yaitu menggunakan aplikasi database manager seperti MySQL Workbench, Toad For MySQL Free, dan HeidiSQL. Dari ketiga aplikasi tersebut, menurut penulis, yang paling user friendly dan ringan adalah HeidiSQL, petunjuk instalasi dan penggunaannya dapat diikuti pada BAB 3. Pada buku ini, penulis menggunakan kombinasi antara command line dan HeidiSQL. Sehingga, di beberapa bagian dari buku ini, Anda akan menemui output dari command line dan di bagian lain, output dari HeidiSQL.



20 BAB 2 Install MySQL



BAB 3 Menginstall dan Menggunakan HeidiSQL Selain menggunakan command prompt, kita dapat mengelola database dengan software Database Management. Penggunaan software jauh lebih mudah dibanding command prompt karena memiliki graphical user interface (GUI). Dengan GUI, kita tidak perlu menjalankan berbagai perintah SQL baik untuk mendefinisikan maupun memanipulasi data, seperti menampilkan data pada tabel, mengupdate data, membuat stored procedure, dll. Saat ini terdapat banyak software Database Management dengan berbagai fitur yang ditawarkan, diantaranya yang terkenal (lisensi gratis) adalah MySQL Workbench, Toad For MySQL Free, dan HeidiSQL, SQL Yog Community Edition, dll. Penulis telah mencoba software tersebut, dan menurut hemat penulis, HeidiSQL lebih mudah digunakan, karena memiliki GUI yang lebih user friendly dan ringan, selain itu, software ini juga memiliki banyak kelebihan dibanding software lainnya. Namun demikian, pilihan ini bersifat subjektif, Anda dapat menggunakan software Database Management lain yang menurut Anda lebih baik. HeidiSQL ditulis oleh Ansgar Becker tahun 1999 dan sampai sekarang masih terus dikembangkan. Meskipun ditulis oleh perorangan, software ini tidak kalah dengan software buatan perusahaan besar. Terdapat dua versi HeidiSQL, yaitu versi portable dan versi Installer. Pada BAB ini, kita akan membahas cara menginstall HeidiSQL menggunakan versi Installer.



3.1. Download HeidiSQL Untuk mendownload HeidiSQL, kunjungi halaman download resminya yang beralamat di http://www.heidisql.com/download.php Klik tombol "HeidiSQL Installer" untuk mendownload versi installer. Installer tersebut dapat digunakan baik pada Windows 64 bit maupun 32 bit. Tunggu hingga proses download selesai, Panduan Lengkap Query MySQL 21



Gambar 3.1 Halaman Download HeidiSQL



3.2. Install HeidiSQL Untuk menginstall HeidiSQL, langkah yang diperlukan adalah: STEP 1. Dobel klik file installer yang telah didownload, dan tunggu hingga muncul jendela Setup Wizard.



22 BAB 3 Menginstall dan Menggunakan HeidiSQL



Gambar 3.2 Jendela Selamat Datang di Setup Wizard Klik Next > untuk melanjutkan STEP 2. Selanjutnya, masuk ke halaman persetujuan lisensi (License Agreement), pilih I accept the agreement dan klik Next >.



Panduan Lengkap Query MySQL 23



Gambar 3.3 Gambar License Agreement STEP 3. Pilih lokasi instalasi, atau biarkan apa adanya. Secara default, software akan diinstall di C:\Program Files\HeidiSQL



24 BAB 3 Menginstall dan Menggunakan HeidiSQL



Gambar 3.4 Lokasi Folder Instalasi Klik Next > untuk melanjutkan ke proses berikutnya. STEP 4. Selanjutnya terdapat pilihan apakah ingin membuat shortcut di Start Menu. Jika tidak ingin membuat shortcut, centang pilihan Don’t create a Start Menu Folder. Pada contoh ini, saya centang pilihan Don’t create a Start Menu Folder. Klik Next > untuk melanjutkan.



Panduan Lengkap Query MySQL 25



Gambar 3.5 Opsi Membuat Shortcut STEP 5. Selanjutnya pilih beberapa opsi tambahan, atau biarkan apa adanya. Jika opsi Automatically check http://heidisql.com/ for updates dipilih, maka aplikasi akan memberi tahu jika ada versi terbaru dari HeidiSQL, sedangkan jika opsi Automatically report client and server versions on http://heidisql.com/ dicentang, maka aplikasi akan mengirimkan data versi MySQL server dan client yang kita gunakan. Data ini akan ditampilkan pada halaman depan website HeidiSQL berupa statistik pengguna HeidiSQL. Seperti tampak pada gambar berikut:



26 BAB 3 Menginstall dan Menggunakan HeidiSQL



Gambar 3.6 Statistik Pengguna HeidiSQL Pada Website HeidiSQL



Panduan Lengkap Query MySQL 27



Gambar 3.7 Opsi Tambahan Klik Next > untuk melanjutkan. STEP 6. Selanjutnya muncul resume opsi yang telah dipilih yang siap dieksekusi. Klik Install untuk menginstall HeidiSQL dengan semua opsi yang telah dipilih



28 BAB 3 Menginstall dan Menggunakan HeidiSQL



Gambar 3.8 HeidiSQL Siap Untuk Diinstall Setelah proses instalasi selesai, klik Finish untuk menutup jendela Setup Wizard, centang opsi Launch HeidiSQL untuk langsung mejalankan HeidiSQL



3.3 Menjalankan HeidiSQL Untuk menjalankan HeidiSQL, buka program tersebut melalui shortcut yang ada di start menu. Pertama kali dibuka, akan muncul jendela Session Manager. Selanjutnya isikan detail koneksi ke server database yang diinginkan, secara default, isian sudah terisi: Hostname / IP : 127.0.0.1, User: root, dan port: 3306, kita tinggal mengisi password saja.



Panduan Lengkap Query MySQL 29



Gambar 3.9 Jendela Session Manager Selanjutnya, klik Open. Jika berhasil, maka kita akan muncul tampilan seperti gambar 3.3.2



Gambar 3.10 Jendela Utama HeidiSQL



30 BAB 3 Menginstall dan Menggunakan HeidiSQL



Keterangan: 1. Nomor 1 merupakan Database Tree, dimana daftar semua database yang ada pada server ditampilkan, pada window tersebut, kita dapat menelusuri object yang ada pada suatu database, seperti tabel, procedure, trigger, dll. 2. Nomor 2 merupakan tab Object. Tab Object ini seperti breadcrumb pada website, yang menunjukkan posisi saat ini kita berada. Pada gambar diatas, karena kita baru saja login, maka kita berada di posisi server, ketika kita klik database, atau tabel dalam database, maka Tab tersebut akan bertambah. Misal ketika kita klik database mysql, maka akan muncul tab Database: mysql



Gambar 3.11 Ilustrasi Object Database 3. Nomor 3 merupakan detail dari object sesuai dengan tab object yang aktif. Pada contoh nomor 2, ketika tab Database: mysql aktif, maka tab detail object akan muncul daftar tabel beserta informasi terkait tabel tersebut, seperti Engine, jumlah baris, dll. Detail object juga dapat berisi opsi lain, misal ketika kita membuka tabel, terdapat tab untuk mengubah nama, index, key, dll.



Gambar 3.12 Ilustrasi Opsi Pada Tabel 4. Nomor 4 merupakan tab query yang merupakan tab dimana kita ingin menuliskan query SQL. Tab ini dapat ditambah dengan meng-klik icon plus yang ada di sebelah kanan nya. Tab ini tidak terpengaruh dengan Panduan Lengkap Query MySQL 31



Object tab, yang artinya akan selalu ada meskipun object tab berganti ganti. Untuk menjalankan query yang telah kita tulis, klik icon Execute Query yang ada di sebelah atas. Tabel hasil query akan muncul di sebelah bawah query SQL. Sebagai contoh, kita jalankan query untuk menampilkan daftar tabel dari database mysql. Proses eksekusi query seperti tampak seperti Gambar 3.3.5



Gambar 3.13 Jendela Query 5. Nomor 5 merupakan windows logging, window ini akan menampilkan semua query baik yang dijalankan oleh user, maupun query internal yang dijalankan oleh software. Semua software database manager, sejatinya hanya menjalankan berbagai query, seperti ketika kita mengklik nama database, kemudian melihat detail dari tabel yang ada.



32 BAB 3 Menginstall dan Menggunakan HeidiSQL



BAB 4 SQL Untuk Database Pada database relasional seperti MySQL, data disimpan dalam bentuk tabel yang terdiri dari baris (row) dan kolom (field). Sebuah database dapat terdiri dari beberapa tabel, misal database toko_buku terdiri dari tabel buku, pelanggan, dan penjualan. Pada MySQL, kita dapat membuat, mengubah dan menghapus database dengan perintah tertentu. Terkait database, terkadang kita menemui istilah SCHEMA, istilah ini sama saja dengan DATABASE.



4.1. Membuat database Untuk membuat database, kita gunakan perintah CREATE DATABASE diikuti nama database, misal untuk membuat database toko_buku, kita jalankan perintah: CREATE DATABASE toko_buku;



Jika nama database telah ada, maka akan muncul pesan error, untuk menghindarinya, kita dapat tambahkan klausa IF NOT EXISTS CREATE DATABASE IF NOT EXISTS toko_buku;



Untuk melihat semua database yang ada, kita dapat menggunakan perintah SHOW DATABASES mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | penjualan | | performance_schema | | sys | +--------------------+ 8 rows in set (0.00 sec)



Panduan Lengkap Query MySQL 33



4.2. Memilih Database Setelah database dibuat, kita dapat memilih database sebagai default database, untuk melakukannya, jalankan perintah USE diikuti nama database yang ingin digunakan, misal kita ingin menggunakan database toko_buku yang sebelumnya telah kita buat mysql> CREATE DATABASE penjualan; Query OK, 1 row affected (0.01 sec) mysql> USE penjualan; Database changed



Kita tidak wajib memilih database, kita dapat langsung menggunakan database dengan menambahkan nama database tersebut pada query yang kita jalankan, misal: SELECT * FROM tutorial.barang



Pada contoh tersebut kita dapat menampilkan data tabel barang yang ada pada database tutorial, meskipun saat ini kita sedang menggunakan database penjualan. Pemilihan default database dengan keyword USE dapat memudahkan kita untuk menjalankan berbagai query, karena kita tidak perlu menuliskan nama database pada setiap query, misal: SELECT * FROM pelanggan



Pada query diatas, MySQL akan menampilkan data tabel pelanggan pada database toko_buku. Karena kita telah membuat tabel toko_buku sebagai default database, maka secara implisit MySQL akan menambahkan nama database yaitu toko_buku di depan nama tabel pelanggan. Setelah memilih default database, kita tetap dapat menggunakan database lain dengan menuliskan nama database di depan nama tabel seperti pada contoh sebelumnya. Kita dapat mengubah default database ke database lain dengan menjalankan perintah USE kembali.



34 BAB 4 SQL Untuk Database



Ketika membuat database, MySQL akan membuat folder baru dengan nama sama dengan database tersebut, di dalamnya terdapat file db.opt yang menyimpan atribut database seperti character set dan collation. Pada folder tersebut nantinya akan disimpan file-file tabel.



Gambar 4.1 Folder dari Database toko_buku



4.3. Menghapus Database Untuk menghapus database, kita gunakan perintah DROP DATABASE diikuti nama database mysql> DROP DATABASE toko_buku; Query OK, 0 rows affected (0.11 sec)



Untuk menghindari error jika nama database tidak ditemukan, kita dapat menambahkan klausa IF NOT EXISTS mysql> DROP DATABASE IF NOT EXISTS toko_buku; Query OK, 0 rows affected (0.11 sec)



Ketika menghapus database, maka semua isi yang ada pada database tersebut juga akan ikut terhapus, seperti tabel, stored routines, dll, disamping itu folder fisik database tersebut juga ikut terhapus.



4.4. Mengubah Database Untuk mengubah database, kita dapat menggunakan statemen ALTER, Statemen ini hanya dapat digunakan untuk mengubah atribut database, yaitu CHARACTER SET dan COLLATION. Format penulisannya adalah sebagai berikut:



Panduan Lengkap Query MySQL 35



ALTER DATABASE [nama_database] [CHARACTER SET] [COLLATION]



Jika kita tidak menyertakan nama database, maka yang mengalami perubahan adalah default database, yang sebelumnya telah kita pilih dengan perintah USE Misal: mysql> ALTER DATABASE CHARACTER SET utf8; Query OK, 1 row affected (0.07 sec)



Catatan: Perubahan Character Set dan Collation pada database tidak akan mengubah character set dan collation pada tabel yang ada di dalam database tersebut, perubahan tersebut hanya berpengaruh pada tabel baru yang dibuat kemudian.



36 BAB 4 SQL Untuk Database



BAB 5 SQL Untuk Tabel MySQL menyediakan berbagai statement untuk membuat, mengubah maupun menghapus tabel. Pada BAB ini, kita akan membahas lebih jauh tentang statemen tersebut.



5.1. Membuat Tabel Sebelum kita dapat menyimpan data pada database, terlebih dahulu, kita harus membuat tabel. Untuk membuat tabel, kita gunakan perintah CREATE TABLE, dengan format sebagai berikut: CREATE TABLE nama_tabel ( nama_kolom definisi_kolom, nama_kolom definisi_kolom, nama_kolom definisi_kolom, dst.. )



Pada format diatas, bagian definisi_kolom harus memuat minimal tipe data kolom, kita juga dapat menambahkan atribut kolom seperti NULL, DEFAULT, dll, maupun constrain, seperti: UNIQUE atau PRIMARY KEY Misal, kita buat tabel pelanggan dengan perintah sebagai berikut: 1. CREATE TABLE `pelanggan_` ( 2. `id_pelanggan` INT(11) NOT NULL AUTO_INCREMENT PRIMARY 3. KEY, 4. `nama` VARCHAR(50) NOT NULL, 5. `email` VARCHAR(50) NOT NULL UNIQUE, 6. `no_telp` VARCHAR(12) NULL, )



Pada contoh diatas, kita buat tabel dengan nama pelanggan yang berisi 4 kolom yaitu id_pelanggan, nama, alamat, dan email. Pada tiap-tiap kolom tersebut, kita harus mendefinisikan tipe data yang ingin digunakan, seperti INT dan VARCHAR, sedangkan untuk panjang data tidak wajib diisi. Lebih jauh tentang tipe data dan panjang data dibahas pada BAB 6 Tipe Data Panduan Lengkap Query MySQL 37



Pada contoh diatas, kita juga menambahkan atribut untuk kolom seperti NOT NULL yang berarti kolom tidak boleh kosong, dan AUTO_INCREMENT yang berarti nilai kolom akan otomatis bertambah ketika suatu baris ditambahkan. Terakhir, kita tambahan constrain pada kolom yaitu UNIQUE dan PRIMARY KEY yang artinya dalam satu kolom tidak boleh ada nilai yang sama. Constrain primary key menandakan bahwa kolom menjadi kunci utama dari tabel. Lebih jauh tentang constrain dibahas pada BAB 7 Constrain. Ketika membuat tabel, sebisa mungkin untuk menjadikan salah satu kolom menjadi primary key, sehingga dapat dipastikan tidak ada baris yang nilai nya sama, hal ini untuk menjaga integritas dan konsistensi data, karena ketika melakukan proses update atau delete, baris yang sama tersebut akan sama sama terpengaruh. Sebagai tambahan, ketika membuat tabel, maka MySQL akan membuat file dengan nama sama seperti nama tabel. File tersebut disimpan di dalam folder yang bernama sama dengan nama database yang sedang digunakan. Jika engine yang digunakan MyISAM, MySQL akan membuat 3 file yang masing-masing ber ekstensi .frm, .MYD, dan .MYI, jika engine yang digunakan InnoDB, maka MySQL akan membuat 2 file, masing-masing berekstensi .frm dan .ibd misal pada contoh diatas, karena engine yang digunakan adalah InnoDB, maka file yang terbentuk adalah pelanggan.frm, pelanggan.ibd. File-file tersebut menyimpan baik data maupun informasi terkait tabel.



Gambar 5.1 File yang terbentuk ketika membuattabel 38 BAB 5 SQL Untuk Tabel



File .frm digunakan untuk menyimpan format dari tabel atau (table definition) seperti storage engine yang digunakan, partition, dll, file .MYD (MyISAM Data - red) untuk menyimpan data pada tabel, dan file .MYI (MyISAM INDEX - red) untuk menyimpan data index dari tabel, sedangkan file .ibd untuk menyimpan data sekaligus index.



5.2. Penamaan Tabel Ketika membuat tabel, kita bebas menentukan nama tabel beserta nama kolom nya, namun demikian nama tersebut harus memenuhi kriteria yang telah ditetapkan. Adapun kriterianya adalah sebagai berikut: 



Tidak boleh ada nama tabel yang sama dalam satu database.







Tidak boleh ada nama kolom yang sama dalam satu tabel, namun, nama kolom yang sama dapat digunakan pada tabel yang berbeda.







Nama kolom dan tabel hanya boleh menggunakan huruf, angka, _ dan $ dan maksimal 64 karakter. Selain itu, nama kolom dan tabel harus diawali degan huruf atau angka.







Nama tabel dan kolom tidak boleh sama dengan keyword yang telah digunakan oleh MySQL, seperti CASCADE, BEGIN, LEFT, dll







Sebagai pengecualian, kita dapat membuat nama tabel dengan karakter apa saja, tetapi harus menggunakan “identifier quote character” yang secara default berupa karakter grave accent atau lebih dikenal back tick (`). Misal CREATE TABLE `% JOIN tabel`. Meski lebih leluasa memilih nama tabel, hal ini tidak disarankan karena akan merepotkan, salah satunya setiap kali menjalankan query, kita harus selalu menggunakan back tick.



Lebih jauh, penentuan nama tabel dan kolom merupakan hal penting karena dapat memudahkan kita dalam mengelola tabel, terutama jika jumlah tabel banyak. Beberapa hal yang dapat dipertimbangkan ketika memilih nama tabel atau kolom:



Panduan Lengkap Query MySQL 39







Pilih nama tabel atau kolom yang mencerminkan isi tabel/kolom, sebisa mungkin tidak disingkat, misal tabel penjualan yang berisi data penjualan, tabel pelanggan yang berisi data pelanggan.







Kelompokkan tabel yang memiliki keterkaitan dengan menambahkan kata tertentu di belakangnya, misal tabel penjualan dan penjualan_detail.







Sekali tabel dibuat, maka ketika namanya diubah, akan berpengaruh pada semua SQL yang telah kita tulis terkait tabel tersebut, sehingga hindari penamaan tabel yang kurang informatif, misal: penjualan_2







Konsisten dalam penamaan kolom antar tabel. Contoh kolom yang berisi id pelanggan pada tabel pelanggan diberi nama id_pelanggan, pada tabel penjualan juga sebagiknya diberi nama id_pelanggan.







Beri nama tabel dan kolom dengan huruf kecil semua, meskipun SQL bersifat case insensitive (tidak membedakan huruf besar dan kecil) namun pemberian nama tabel dan kolom dengan huruf kecil akan memudahkan kita ketika menulis query SQL karena dapat dibedakan dengan mudah mana statemen SQL dan mana nama tabel atau kolom.



5.3. Opsi Tabel Ketika membuat tabel, terdapat banyak opsi yang dapat ditambahkan, diantaranya adalah STORAGE ENGINE, CHARACTER SET, COLLATION, dan COMMENT



5.3.1. Storage Engine Mungkin diantara sekian banyak opsi yang dapat ditambahkan, opsi yang paling penting adalah ENGINE. Opsi ini menentukan bagaimana data disimpan dan diakses, termasuk bagaimana transaksi diproses. Masingmasing storage engine memiliki kelebihan dan kekurangan. Ada yang fokus bagaimana perintah SELECT yang kompleks dapat dieksekusi dengan cepat, ada juga yang fokus bagaimana statemen UPDATE dapat dieksekusi dengan cepat.



40 BAB 5 SQL Untuk Tabel



MySQL memungkinkan kita mendefinisikan storage engine pada masing masing tabel. Jika tidak kita definisikan, maka tabel akan menggunakan storage engine default. Pada MySQL versi lama, storage engine default adalah MyISAM, namun saat ini defaultnya adalah InnoDB. Untuk mengecek storage engine yang tersedia, dapat menggunakan perintah berikut: mysql> SHOW ENGINES; +--------------------+---------+--------------------------+--------------+ | Engine | Support | Comment | Transactions | +--------------------+---------+--------------------------+--------------+ | InnoDB | DEFAULT | Supports transactions... | YES | | MRG_MYISAM | YES | Collection of identical..| NO | | MEMORY | YES | Hash based, stored in... | NO | | BLACKHOLE | YES | /dev/null storage engine | NO | | MyISAM | YES | MyISAM storage engine... | NO | | CSV | YES | CSV storage engine | NO | | ARCHIVE | YES | Archive storage engine | NO | | PERFORMANCE_SCHEMA | YES | Performance Schema | NO | | FEDERATED | NO | Federated MySQL storag | NULL | +--------------------+---------+--------------------------+--------------+



Dari tabel diatas terlihat bahwa storage engine default nya adalah InnoDB Terdapat dua storage engine yang populer, yaitu InnoDB da MyISAM. InnoDB merupakan storage engine yang powerful yang sering digunakan karena mendukung transaksi, constrain foreign key, dan row level locking (cocok digunakan ketika banyak terjadi manipulasi data – INSERT dan UPDATE). Sedangkan engine MyISAM lebih cepat daripada InnoDB terutama untuk membaca tabel (statemen SELECT) karena strukturnya yang lebih simpel, sehingga, untuk tabel yang simpel, yang lebih sering dibaca daripada dimanipulasi, maka disarankan untuk menggunakan MyISAM. Meski demikian, InnoDB terus berkembang dan banyak fitur yang sebelumnya hanya ada pada MyISAM mulai ada pada InnoDB seperti Full-text indexing yang ada setelah MySQL versi 5.6, adapun untuk engine MyISAM, perkembangannya lambat, tidak sepesat InnoDB. Sedikit gambaran bahwa ketika terjadi proses manipulasi seperti UPDATE, maka pada storage engine InnoDB, MySQL akan mengunci baris yang akan dimanipulasi sehingga tidak dapat digunakan oleh statemen lain hingga Panduan Lengkap Query MySQL 41



proses manipulasi selesai, proses ini disebut (row-level locking), sedangkan pada MyISAM, proses update akan mengunci tabel (table-level locking), itulah kenapa pada MyISAM lebih lambat ketika terjadi banyak manipulasi data. Contoh query untuk menambahkan engine pada saat pembuatan tabel: 1. CREATE TABLE `pelanggan` ( 2. `id_pelanggan` INT(11) NOT NULL AUTO_INCREMENT, 3. `nama` VARCHAR(50) NOT NULL, 4. `alamat` VARCHAR(50) NOT NULL, 5. `email` VARCHAR(50) NOT NULL, 6. PRIMARY KEY (`id_pelanggan`), 7. UNIQUE INDEX `email` (`email`) 8. ) 9. ENGINE=MyISAM;



Informasi mengenai storage engine pada tabel disimpan oleh MySQL di dalam database INFORMATION_SCHEMA tabel TABLES, misal untuk mengetahui storage engine pada tabel yang ada di database toko_buku, kita gunakan perintah berikut: mysql> SELECT TABLE_NAME, ENGINE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = "toko_buku"; +--------------+--------+ | TABLE_NAME | ENGINE | +--------------+--------+ | pelanggan | InnoDB | | pelanggan | InnoDB | +--------------+--------+ 2 rows in set (0.00 sec)



5.3.2. Character Set dan Collation Ketika membuat tabel, kita dapat mendefinisikan character set default yang digunakan oleh tabel, character set ini akan digunakan untuk mendefinisikan character set kolom, jika kolom tersebut tidak mendefinisikan character set. Untuk melihat character set yang dapat digunakan, beserta default collationnya, jalankan perintah berikut: SHOW CHARACTER SET



42 BAB 5 SQL Untuk Tabel



Hasil: +----------+---------------------------------+---------------------+--------+ | Charset | Description | Default collation | Maxlen | +----------+---------------------------------+---------------------+--------+ | big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 | | dec8 | DEC West European | dec8_swedish_ci | 1 | | cp850 | DOS West European | cp850_general_ci | 1 | | hp8 | HP West European | hp8_english_ci | 1 | | koi8r | KOI8-R Relcom Russian | koi8r_general_ci | 1 | | latin1 | cp1252 West European | latin1_swedish_ci | 1 | | latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 | | swe7 | 7bit Swedish | swe7_swedish_ci | 1 | | ascii | US ASCII | ascii_general_ci | 1 | | utf8 | UTF-8 Unicode | utf8_general_ci | 3 | | ucs2 | UCS-2 Unicode | ucs2_general_ci | 2 | | ... | ... | ... | ... | +----------+---------------------------------+---------------------+--------+



Character set digunakan untuk menentukan jenis karakter yang dapat disimpan pada suatu kolom, untuk huruf latin, seperti yang digunakan oleh bahasa indonesia dan bahasa ingris, maka cukup menggunakan character set latin1, sedangkan untuk khusus seperti huruf arab, maka kita perlu menggunakan utf8 Selain character set, kita juga dapat menentukan default collation pada tabel, collation ini juga digunakan untuk mendefinisikan collation kolom jika collation kolom tidak didefinisikan, untuk melihat semua collation yang dapat digunakan, jalankan perintah berikut: SHOW COLLATION



Hasil: +--------------------------+----------+-----+---------+----------+---------+ | Collation | Charset | Id | Default | Compiled | Sortlen | +--------------------------+----------+-----+---------+----------+---------+ | ... | ... | ... | ... | ... | ... | | latin1_swedish_ci | latin1 | 8 | Yes | Yes | 1 | | latin1_danish_ci | latin1 | 15 | | Yes | 1 | | utf8_general_ci | utf8 | 33 | Yes | Yes | 1 | | utf8_bin | utf8 | 83 | | Yes | 1 | | utf8_unicode_ci | utf8 | 192 | | Yes | 8 | | utf8_icelandic_ci | utf8 | 193 | | Yes | 8 | | utf8_latvian_ci | utf8 | 194 | | Yes | 8 | | ... | ... | ... | ... | ... | ... | +--------------------------+----------+-----+---------+----------+---------+



Panduan Lengkap Query MySQL 43



Untuk melihat collation tertentu kita dapat menggunakan klausa WHERE, misal melihat semua collation untuk character set utf8: SHOW COLLATION WHERE charset = "utf8"



Collation menentukan bagaimana data dibandingkan dan diurutkan. Yang terpenting dari collation ini adalah apakah kita akan membedakan huruf besar dan huruf kecil ketika melakukan perbandingan data. Misal, pada collation yang membedakan huruf besar dan kecil, maka klausa WHERE nama = "Andi" tidak sama dengan WHERE nama = "andi". Untuk collation yang membedakan huruf besar dan kecil, nama collation tersebut biasanya berakhiran _cs yang artinya case sensitive, misal: latin1_swedish_cs, sedangkan yang tidak membedakan huruf besar dan kecil, biasanya berakhiran _ci yang artinya case insensitive, misal: latin_swedish_ci. Contoh penerapan character set dan collation: Contoh 1: Character Set didefinisikan pada tabel namun tidak pada kolom CREATE TABLE tabel_tes ( kolom_tes VARCHAR(255) ) CHARACTER SET utf8 COLLATE utf8_unicode_ci;



Pada contoh diatas, kolom_tes akan memiliki character set utf8 dan collation utf8_unicode_ci. Hal ini dikarenakan kita tidak mendefinisikan character set dan collation pada kolom, sehingga kolom akan menggunakan collation dari tabel. mysql> SELECT CHARACTER_SET_NAME, COLLATION_NAME -> FROM information_schema.`COLUMNS` -> WHERE table_schema = 'toko_buku' -> AND table_name = 'tabel_tes'; +--------------------+-----------------+ | CHARACTER_SET_NAME | COLLATION_NAME | +--------------------+-----------------+ | utf8 | utf8_unicode_ci | +--------------------+-----------------+



44 BAB 5 SQL Untuk Tabel



Contoh 2: Character Set didefinisikan pada kolom CREATE TABLE IF NOT EXISTS tabel_coba ( kolom_coba VARCHAR(255) CHARACTER SET latin1 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci;



Pada contoh diatas, tabel kolom_coba memiliki character set latin1 dan collation latin1_swedish_ci, karena collation tidak di definisikan, maka otomatis mengambil default collation dari character set. Perhatikan bahwa meskipun kita mendefinisikan collation pada tabel, karena kita mendefinisikan character set untuk kolom, maka collation yang digunakan berdasarkan character set kolom, bukan tabel. Contoh 3: Collation didefinisikan pada kolom CREATE TABLE IF NOT EXISTS tabel_coba ( kolom_coba VARCHAR(255) COLLATE latin1_swedish_ci ) CHARACTER SET utf8 COLLATE utf8_unicode_ci;



Pada contoh diatas, tabel kolom_coba memiliki character set latin1 dan collation latin1_swedish_ci, karena character set kolom tidak di definisikan, maka otomatis mengambil character set yang terkait dengan collation kolom (biasanya kata depan dari collation). mysql> SELECT table_schema, table_name, CHARACTER_SET_NAME, COLLATION_NAME -> FROM information_schema.`COLUMNS` -> WHERE table_schema = 'tutorial_test' -> AND table_name = 'tabel_coba'; +---------------+------------+--------------------+-----------------+ | table_schema | table_name | CHARACTER_SET_NAME | COLLATION_NAME | +---------------+------------+--------------------+-----------------+ | tutorial_test | tabel_coba | utf8 | utf8_general_ci | +---------------+------------+--------------------+-----------------+ 1 row in set (0.00 sec)



Panduan Lengkap Query MySQL 45



Perhatikan bahwa meskipun kita mendefinisikan character set tabel, karena kita mendefinisikan collation untuk kolom, maka character set yang digunakan berdasarkan collation kolom, bukan character set tabel. Contoh 4: Character Set tidak didefinisikan pada kolom dan tabel CREATE TABLE tabel_tes ( kolom_tes VARCHAR(255) );



Pada contoh diatas, kolom akan mencari default character set dan collation pada tabel, karena pada tabel tidak didefinisikan, maka akan menggunakan character set dan collation pada database, yang dalam hal ini adalah latin1 mysql> SELECT schema_name, default_character_set_name , default_collation_name -> FROM information_schema.SCHEMATA -> WHERE schema_name = 'toko_buku'; +-------------+----------------------------+------------------------+ | schema_name | default_character_set_name | default_collation_name | +-------------+----------------------------+------------------------+ | toko_buku | latin1 | latin1_swedish_ci | +-------------+----------------------------+------------------------+ 1 row in set (0.00 sec)



Hal ini juga berlaku untuk tabel, karena kita tidak mendefinisikan character set dan collation tabel, maka akan digunakan character set dan collation dari database. Catatan: Character set dan collation sejatinya diperuntukkan untuk kolom, karena tidak mungkin kita membuat tabel tanpa kolom. Ketika kolom dibuat dan character set dan collation tidak didefinisikan, maka akan menggunakan character set dan collation tabel, jika pada tabel tidak didefinisikan, maka akan menggunakan character set dan collation database, terakhir, jika pada database tidak didefinisikan, maka akan menggunakan setting dari sistem



46 BAB 5 SQL Untuk Tabel



5.3.3. Auto Increment Auto increment adalah atribut pada suatu kolom dimana kolom tersebut akan otomatis berisi nilai numerik yang selalu bertambah (increment). Dalam suatu tabel hanya boleh ada 1 kolom yang ber atribut Auto Increment. Nilai awal auto increment tersebut dapat didefinisikan melalui atribut tabel. Misal kita buat tabel pelanggan sebagai berikut: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.



CREATE TABLE `pelanggan` ( `id_pelanggan` INT(11) NOT NULL AUTO_INCREMENT, `nama` VARCHAR(50) NOT NULL, `alamat` VARCHAR(50) NOT NULL, `email` VARCHAR(50) NOT NULL, PRIMARY KEY (`id_pelanggan`), UNIQUE INDEX `email` (`email`) ) ENGINE=MyISAM CHARACTER SET latin1 AUTO_INCREMENT=10;



Perhatikan bahwa titik koma ditulis di akhir statemen. Pada contoh diatas, kolom id_pelanggan kita beri AUTO_INCREMENT sedangkan pada tabel juga kita beri AUTO_INCREMENT dengan nilai 10.



atribut atribut



Selanjutnya, jika kita tambahkan data pada tabel, maka kolom id_pelanggan akan memiliki nilai 10, jika kita tambahkan lagi nilainya menjadi 11, demikian seterusnya mysql> INSERT INTO pelanggan (nama, alamat, email) VALUES ('alfa', 'Jakarta', '[email protected]'); Query OK, 1 row affected (0.00 sec) mysql> SELECT * FROM pelanggan; +--------------+------+---------+----------------+ | id_pelanggan | nama | alamat | email | +--------------+------+---------+----------------+ | 10 | alfa | Jakarta | [email protected] | +--------------+------+---------+----------------+



Panduan Lengkap Query MySQL 47



1 row in set (0.00 sec) mysql> INSERT INTO pelanggan (nama, alamat, email) VALUES ('beta', 'Jakarta', '[email protected]'); Query OK, 1 row affected (0.00 sec) mysql> SELECT * FROM pelanggan; +--------------+------+---------+----------------+ | id_pelanggan | nama | alamat | email | +--------------+------+---------+----------------+ | 10 | alfa | Jakarta | [email protected] | | 11 | beta | Jakarta | [email protected] | +--------------+------+---------+----------------+ 2 rows in set (0.00 sec)



5.4. Mengcopy Tabel Dengan perintah SQL, kita dapat membuat tabel sama persis dengan tabel lain termasuk indexnya, perintah SQL yang digunakan adalah: CREATE TABLE tabel_baru LIKE tabel_lama



Misal kita copy tabel buku ke tabel buku_backup, query yang kita jalankan: mysql> CREATE TABLE buku_backup LIKE buku; Query OK, 0 rows affected (7.22 sec)



Selanjutnya mari kita cek struktur dati tabel buku_backup: mysql> SET sql_mode = "ANSI"; Query OK, 0 rows affected (0.06 sec) mysql> SHOW CREATE TABLE buku_backup\G; *************************** 1. row *************************** Table: buku_backup Create Table: CREATE TABLE "buku_backup" ( "id_buku" int(11) NOT NULL AUTO_INCREMENT, "isbn" char(13) NOT NULL, "judul" varchar(255) NOT NULL,



48 BAB 5 SQL Untuk Tabel



"deskripsi" text NOT NULL, "id_pengarang" tinyint(4) NOT NULL, "id_penerbit" tinyint(4) NOT NULL, "tgl_terbit" date NOT NULL, "harga" int(11) NOT NULL, "status" tinyint(1) NOT NULL, "stok" tinyint(4) NOT NULL, "id_kategori" smallint(6) NOT NULL, "url" varchar(255) DEFAULT NULL, PRIMARY KEY ("id_buku"), KEY "FK_buku_pengarang" ("id_pengarang"), FULLTEXT KEY "judul" ("judul"), FULLTEXT KEY "deskripsi_fulltext" ("deskripsi"), FULLTEXT KEY "judul_deskripsi_fulltext" ("judul","deskripsi") )



Pada contoh diatas terlihat bahwa index pada tabel buku juga ikut tercopy termasuk kolom untuk foreign key, namun karena foreign key melibatkan tabel lain, foreign key constrain tidak ikut terbentuk. Statemen diatas hanya digunakan untuk mengcopy struktur tabel, tidak termasuk isinya, untuk menyalin isinya, kita harus menjalankan query tersendiri, tidak bisa digabung dengan query sebelumnya. Untuk mengcopy isi tabel buku ke dalam tabel buku_backup, kita gunakan perintah berikut: INSERT INTO buku_backup SELECT * FROM buku



Statemen insert ini dibahas lebih jauh pada BAB 11 Manipulasi Data. Untuk mengcopy tabel beserta isinya, selain menggunakan dua statemen seperti pada contoh sebelumnya, kita juga dapat menggunakan hanya satu statemen, yaitu: CREATE TABLE new_table [AS] SELECT * FROM old_table;



Keterangan: klausa AS bersifat opsional Misal, kita copy tabel buku ke tabel buku2, jalankan query berikut: Panduan Lengkap Query MySQL 49



CREATE TABLE buku2 SELECT * FROM buku;



Penting diperhatikan bahwa ketika menggunakan statemen diatas, index dari tabel lama tidak ikut tercopy, hal ini bertujuan agar statemen SELECT dapat fleksibel. Untuk mendefinisikan index pada tabel baru, kita dapat mendefinisikannya sebelum statemen SELECT, misal kita buat tabel buku2 dengan menambahkan index PRIMARY KEY pada kolom id_buku dan UNIQUE pada kolom isbn, query yang kita jalankan: mysql> DROP TABLE IF EXISTS buku2; Query OK, 0 rows affected (0.24 sec) mysql> CREATE TABLE buku2 (PRIMARY KEY(id_buku), UNIQUE(isbn)) SELECT * FROM buku; Query OK, 21 rows affected (0.59 sec) Records: 21 Duplicates: 0 Warnings: 0



5.5. Mengubah Tabel Untuk mengubah definisi tabel, kita gunakan statemen ALTER. Statemen ini dapat digunakan untuk mengubah baik nama tabel, opsi tabel, maupun struktur tabel, seperti mengubah engine dan index, menambah dan menghapus kolom, mengubah nama kolom dan tipe data kolom, mengubah urutan kolom, dll. Format umum penulisan ALTER untuk mengubah tabel adalah: ALTER TABLE nama_tabel [spesifikasi_alter]



5.5.1. Mengubah Nama Tabel Untuk mengubah nama tabel, gunakan perintah: ALTER TABLE nama_tabel RENAME [TO|AS] nama_tabel_baru



Catatan: kita dapat memilih menggunakan klausa TO atau AS atau tanpa keduanya 50 BAB 5 SQL Untuk Tabel



Misal kita ingin mengubah nama tabel buku menjadi barang, maka perintah yang kita jalankan: ALTER TABLE buku RENAME TO barang



Jika tabel barang telah ada, maka akan muncul pesan error: SQL Error (1050): Table 'barang' already exists



5.5.2. Mengubah Opsi Tabel Perintah ALTER juga dapat digunakan untuk mengubah opsi tabel, seperti Engine, Character Set, Collation, dan Auto Increment



5.5.2.1. Mengubah Engine Query berikut akan mengubah engine tabel buku menjadi InnoDB: ALTER TABLE buku ENGINE = InnoDB;



Perlu diperhatikan jika kita mengubah engine dari MyISAM ke InnoDB, pastikan memahami fitur kedua engine tersebut, karena MyISAM dan InnoDB memiliki karakteristik berbeda di setiap versi MySQL, perbedaan ini bisa jadi akan berpengaruh pada data yang berada pada tabel. Beberapa keterbatasan engine InnoDB: (1) InnodDB tidak mendukung Full-text Search (sebelum versi 5.6) (2) row length/pajang baris yang dapat diterima berbeda beda tergantung besarnya page size, misal pada default page size 16KB, maksimum row-length nya adalah 8000byte. Perbedaan selengkapnya dapat di pelajari di: https://dev.mysql.com/doc/refman/5.7/en/innodb-restrictions.html



5.5.2.2. Mengubah Character Set dan Collation Untuk mengubah Character Set suatu tabel pada kolom dengan tipe data karakter (CHAR, VARCHAR, TEXT) gunakan format query berikut: ALTER TABLE nama_tabel CONVERT TO CHARACTER SET nama_character_set



Panduan Lengkap Query MySQL 51



Catatan: perintah diatas akan mengubah character set dan collation semua kolom pada tabel menjadi character set dan collation baru yang didefinisikan. Misal kita memiliki tabel pengarang dengan struktur sebagai berikut: mysql> SHOW CREATE TABLE pengarang \G; *************************** 1. row *************************** Table: pengarang Create Table: CREATE TABLE `pengarang` ( `id_pengarang` tinyint(4) NOT NULL AUTO_INCREMENT, `nama` varchar(50) NOT NULL, PRIMARY KEY (`id_pengarang`) ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC 1 row in set (0.02 sec)



Collation tabel: mysql> SHOW TABLE STATUS WHERE name = "pengarang"\G; *************************** 1. row *************************** Name: pengarang Engine: InnoDB ... Collation: latin1_swedish_ci Checksum: NULL Create_options: Comment: 1 row in set (0.12 sec)



Character set dan collation kolom adalah: mysql> SELECT column_name, character_set_name, collation_name -> FROM information_schema.`COLUMNS` -> WHERE table_schema = 'toko_buku' -> AND table_name = 'pengarang'; +--------------+--------------------+-------------------+ | column_name | character_set_name | collation_name | +--------------+--------------------+-------------------+ | id_pengarang | NULL | NULL |



52 BAB 5 SQL Untuk Tabel



| nama | latin1 | latin1_swedish_ci | +--------------+--------------------+-------------------+ 2 rows in set (0.00 sec)



Selanjutnya mari kita ubah character set tabel pengarang menjadi utf8 mysql> ALTER TABLE pengarang CONVERT TO CHARACTER SET utf8; Query OK, 0 rows affected (0.11 sec) Records: 0 Duplicates: 0 Warnings: 0



Perintah diatas akan mengubah character set tabel menjadi utf8 dan collation tabel menjadi utf8_general_ci, karena collation tidak didefinisikan maka diambil collation default dari character set utf8, hal ini juga berlaku untuk kolom: mysql> SELECT column_name, character_set_name, collation_name -> FROM information_schema.`COLUMNS` -> WHERE table_schema = 'toko_bukua' -> AND table_name = 'pengarang'; +------------------+--------------------+-----------------+ | column_name | character_set_name | collation_name | +------------------+--------------------+-----------------+ | id_pengarang | NULL | NULL | | nama | utf8 | utf8_general_ci | +------------------+--------------------+-----------------+ 2 rows in set (0.00 sec)



Untuk mengubah collation tabel, kita tambahkan klausa COLLATE pada perintah ALTER TABLE, format penulisannya: ALTER TABLE nama_tabel CONVERT TO CHARACTER SET character_set COLLATE collation



Misal kita ubah character set tabel pengarang menjadi utf8 dan collation utf8_unicode_ci: mysql> ALTER TABLE pengarang CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;



Panduan Lengkap Query MySQL 53



Query OK, 0 rows affected (0.11 sec) Records: 0 Duplicates: 0 Warnings: 0



Pada tipe data VARCHAR dan TEXT, perintah CONVERT TO CHARACTER SET akan melakukan penyesuaian tipe data kolom untuk menyesuaikan panjang data maksimal yang dapat diterima character set, misal pada kolom dengan tipe data TEXT yang memiliki character set latin1, ketika diubah menjadi utf8 tipe data akan berubah menjadi MEDIUMTEXT. Perubahan tipe data tersebut dikarenakan pada character set latin1, setiap karakter memiliki panjang data 1 byte, sedangkan pada utf8 panjang data maksimal karakter adalah 3 byte, sehingga pada tipe data TEXT dengan character set latin1 yang dapat menampung 65,535 karakter, ketika berubah menjadi utf8, panjang data maksimal adalah 3 byte x 65,535 = 196,605 bytes, demikian juga dengan VARCHAR yang mungkin juga akan diubah menjadi MEDIUMTEXT. Untuk menghindari perubahan tipe data gunakan MODIFY untuk mengubah tipe data kolom tertentu, misal: ALTER TABLE pelanggan MODIFY alamat TEXT CHARACTER SET utf8 ALTER TABLE nama MODIFY VARCHAR(50) CHARACTER SET utf8



5.5.2.3. Mengubah Auto Increment Pada tabel yang memiliki kolom dengan atribut auto_increment, maka nilai auto_increment tersebut akan terus bertambah ketika baris ditambahkan, untuk mereset atau mengubah nilai auto_increment tersebut, gunakan statemen ALTER ALTER TABLE nama_tabel AUTO_INCREMENT = nilai;



Perlu diperhatikan bahwa nilai auto_increment tidak boleh lebih kecil dari data maksimal yang ada pada kolom, misal pada tabel pengarang, data maksimal kolom id_pengarang adalah 13, sehingga kita hanya dapat memberi nilai auto_increment 14 keatas, jika kita beri nilai kurang dari 14, maka nilai auto_increment akan menjadi 14. 54 BAB 5 SQL Untuk Tabel



Misal kita ubah nilai auto_increment menjadi 17: mysql> ALTER TABLE pengarang AUTO_INCREMENT = 17; Query OK, 0 rows affected (0.06 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> SHOW CREATE TABLE pengarang\G; *************************** 1. row *************************** Table: pengarang Create Table: CREATE TABLE `pengarang` ( `id_pengarang` tinyint(4) NOT NULL AUTO_INCREMENT, `nama` varchar(50) NOT NULL, PRIMARY KEY (`id_pengarang`) ) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC 1 row in set (0.00 sec)



5.5.3. Mengubah Kolom Perintah ALTER TABLE juga dapat digunakan untuk mengubah struktur kolom seperti mengubah nama kolom, menambah kolom, menghapus kolom, dll.



5.5.3.1. Menambah Kolom Untuk menambah kolom tabel, gunakan perintah berikut: ALTER TABLE nama_tabel ADD [COLUMN] nama_kolom kolom_definition [FIRST | AFTER nama_kolom ]



Penjelasan:  Klausa COLUMN bersifat opsional.  Klausa FIRST dan AFTER bersifat opsional. Klausa FIRST akan menempatkan kolom baru pada urutan paling depan, klausa AFTER akan menempatkan kolom baru setelah kolom tertentu, sedangkan jika keduanya tidak didefinisikan, maka kolom baru akan diletakkan di urutan paling belakang.



Panduan Lengkap Query MySQL 55



Contoh 1: pada tabel pengarang kita tambahkan kolom alamat: ALTER TABLE pengarang ADD COLUMN alamat TEXT



Pada contoh diatas, kolom alamat memiliki tipe data TEXT, posisinya berada di bagian akhir dari daftar kolom mysql> SELECT * FROM pengarang LIMIT 3; +--------------+--------------------+--------+ | id_pengarang | nama | alamat | +--------------+--------------------+--------+ | 1 | R. H. Sianipar | NULL | | 2 | Abdul Kadir | NULL | | 3 | Jubilee Enterprise | NULL | +--------------+--------------------+--------+ 3 rows in set (0.00 sec)



Contoh 2: Selanjutnya kita tambahkan kolom email setelah kolom nama. Query yang kita jalankan: ALTER TABLE pengarang ADD email VARCHAR(50) NOT NULL AFTER nama



Pada contoh diatas, kolom email memiliki tipe data VARCHAR dengan panjang data 50, serta tidak boleh berisi nilai NULL mysql> SHOW CREATE TABLE pengarang\G; *************************** 1. row *************************** Table: pengarang Create Table: CREATE TABLE `pengarang` ( `id_pengarang` tinyint(4) NOT NULL AUTO_INCREMENT, `nama` varchar(50) NOT NULL, `email` varchar(50) NOT NULL, `alamat` text, PRIMARY KEY (`id_pengarang`) ) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC 1 row in set (0.00 sec)



56 BAB 5 SQL Untuk Tabel



Dengan statemen ALTER TABLE, kita juga dapat menambah banyak kolom sekaligus dalam satu statemen. Contoh3: misal kita tambahkan kolom website setelah kolom email, kolom telp setelah kolom website, dan kolom kota pada bagian akhir tabel. ALTER TABLE pengarang ADD website VARCHAR(50) NULL AFTER email, ADD telp VARCHAR(15) NULL AFTER website, ADD kota VARCHAR(50) NOT NULL



Jika kita ingin menambahkan banyak kolom di akhir tabel, kita dapat menggunakan cara lain, yaitu hanya satu kali menulis klausa ADD, format penulisannya adalah: ALTER TABLE pengarang ADD (nama_kolom kolom_definition, nama_kolom kolom_definition, ...)



Contoh 4: Misal pada tabel pengarang, pada bagian akhir tabel kita tambahkan kolom kota, kode_popinsi, kode_kabupaten. query yang kita jalankan: ALTER TABLE pengarang ADD (status ENUM("AKTIF", "TIDAK AKTIF") DEFAULT "AKTIF", kode_propinsi VARCHAR(50) NULL, kode_kabupaten VARCHAR(15) NULL )



Hasil akhir struktur tabel pengarang adalah sebagai berikut: mysql> SHOW CREATE TABLE pengarang\G; *************************** 1. row *************************** Table: pengarang Create Table: CREATE TABLE `pengarang` ( `id_pengarang` tinyint(4) NOT NULL AUTO_INCREMENT, `nama` varchar(50) NOT NULL, `email` varchar(50) NOT NULL, `alamat` text,



Panduan Lengkap Query MySQL 57



`website` varchar(50) DEFAULT NULL, `telp` varchar(15) DEFAULT NULL, `kota` varchar(50) NOT NULL, `status` enum('AKTIF','TIDAK AKTIF') DEFAULT 'AKTIF', `kode_propinsi` varchar(50) DEFAULT NULL, `kode_kabupaten` varchar(15) DEFAULT NULL, PRIMARY KEY (`id_pengarang`) ) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC 1 row in set (0.00 sec)



5.5.3.2. Mengubah Nama Kolom dan/atau Kolom Definition Dengan perintah ALTER TABLE kita dapat mengubah nama kolom sekaligus kolom definition. Format penulisannya adalah: ALTER TABLE nama_tabel CHANGE [COLUMN] nama_kolom_lama nama_kolom_baru kolom_definition [FIRST | AFTER nama_kolom]



Penjelasan: penggunaan klausa COLUMN, FIRST, dan AFTER sama seperti pada pembahasan sebelumnya, sub bab 5.5.3.1 Catatan: ketika mengubah nama kolom, selain mendefinisikan nama kolom baru, kita juga harus mendefinisikan tipe data kolom tersebut Contoh 1: pada tabel pengarang, kita ubah nama kolom nama menjadi nama_pengarang. Jalankan Query berikut ALTER TABLE pengarang CHANGE nama nama_pengarang VARCHAR(50)



Contoh 2: pada tabel pengarang, kita ubah nama kolom alamat menjadi alamat_pengarang dan kita ubah tipe datanya menjadi VARCHAR(255), selain itu kita pindah posisi kolom tersebut menjadi setelah kolom kota. Query yang kita jalankan adalah:



58 BAB 5 SQL Untuk Tabel



ALTER TABLE pengarang CHANGE alamat alamat_pengarang VARCHAR(255) AFTER kota



Catatan: Ketika memindah posisi kolom suatu tabel, data kolom tersebut otomatis akan berpindah Jika kita hanya ingin mengubah atribut kolom (kolom definition) tanpa mengubah nama kolom, maka kita dapat menggunakan klausa MODIFY. Adapun format penulisannya adalah: ALTER TABLE nama_tabel MODIFY [COLUMN] nama_kolom kolom_definition [FIRST | AFTER nama_kolom]



Contoh 3: pada tabel pengarang, kita ubah tipe data kolom email menjadi VARCHAR(255) dan kita ubah nilai defaultnya menjadi [email protected] ALTER TABLE pengarang MODIFY email VARCHAR(255) DEFAULT "[email protected]"



Untuk mengubah hanya atribut default dari suatu kolom kita dapat menggunakan klausa SET DEFAULT dan DROP DEFAULT, format penulisannya adalah: ALTER TABLE nama_tabel ALTER nama_kolom {SET DEFAULT literal | DROP DEFAULT}



Contoh 4: Misal kita ubah nilai default kolom email pada tabel pengarang menjadi noemail. Query yang kita jalankan: ALTER TABLE pengarang ALTER email SET DEFAULT "noemail"



Contoh 5: Misal, kita hapus nilai default pada kolom email, query yang kita jalankan



Panduan Lengkap Query MySQL 59



ALTER TABLE pengarang ALTER email DROP DEFAULT



5.5.3.3. Menghapus Kolom Untuk menghapus kolom suatu tabel, kita gunakan perintah: ALTER TABLE pengarang DROP COLUMN nama_kolom



Contoh 1: Misal kita ingin menghapus kolom kota pada tabel pengarang. Query yang kita jalankan ALTER TABLE pengarang DROP COLUMN kota



Selain menghapus kolom satu per satu, kita dapat menghapus beberapa kolom sekaligus dalam satu statemen. Contoh 2: pada tabel pengarang, kita hapus kolom email dan website. Query yang kita jalankan: ALTER TABLE pengarang DROP COLUMN email, DROP COLUMN website



Catatan: Kita tidak dapat menghapus kolom yang sedang digunakan sebagai foreign key, baik sebagai kolom referensi maupun kolom foreign key, jika kita hapus kolom tersebut, maka akan muncul pesan error, misal: SQL Error (1828): Cannot drop column 'id_pengarang': needed in a foreign key constraint 'FK_buku_pengarang'



5.6. Menghapus Tabel Untuk menghapus tabel, kita gunakan perintah DROP TABLE diikuti nama tabel, untuk menghindari error karena tabel tidak ditemukan, kita tambahkan klausa IF EXISTS, misal kita hapus tabel pengarang, perintah yang kita jalankan: 60 BAB 5 SQL Untuk Tabel



DROP TABLE IF EXISTS pengarang



Catatan: sama seperti menghapus kolom, kita juga tidak dapat menghapus tabel yang kolomnya sedang digunakan sebagai foreign key, baik sebagai kolom foreign key maupun kolom referensi, jika tidak maka akan muncul pesan error, misal: SQL Error (1217): Cannot delete or update a parent row: a foreign key constraint fail



Panduan Lengkap Query MySQL 61



Halaman ini sengaja dikosongkan Jagowebdev.com



62 BAB 5 SQL Untuk Tabel



BAB 6 Tipe Data Pada MySQL, tipe data atau data type menunjukkan jenis data suatu kolom. Ketika mendesain tabel pada database, mau tidak mau kita harus menentukan tipe data apa yang akan kita gunakan pada kolom tersebut, apakah karakter (string), angka (numerik), Boolean, Datetime, atau yang lain, selain itu, kita juga harus mendefinisikan panjang datanya, misal VARCHAR(50) yang artinya tipe data VARCHAR dengan panjang data 50 karakter. Pemilihan tipe data merupakan hal yang penting untuk diperhatikan karena dengan pemilihan tipe data yang tidak tepat akan mengakibatkan kinerja (performance) database menurun, misal membandingkan data numerik akan jauh lebih cepat dari pada string (seperti pada klausa WHERE) karena pada string, MySQL akan mempertimbangkan character set dan collation yang digunakan. Selain itu, memproses data yang kecil (data dengan panjang data kecil), akan lebih cepat daripada data yang besar, terlebih jika data tersebut dapat disimpan pada memory (RAM), misal seperti penentuan panjang data untuk tipe data integer, pemrosesan tipe data INT(4) akan lebih cepat daripada INT(11) MySQL sendiri telah mensupport banyak tipe data, BAB ini akan membahas lebih dalam tipe data yang didukung MySQL, seperti: Numeric, String, Boolean, dan Datetime



6.1. Numeric Tipe data numeric digunakan untuk menyimpan data berupa angka, tipe data ini terbagi menjadi dua, yaitu yang hanya mendukung bilangan bulat (exact value) dan dan yang mendukung bilangan pecahan (floating point). Untuk bilangan bulat kita gunakan tipe data TINYINT, SMALLINT,



Panduan Lengkap Query MySQL 63



MEDIUMINT, INT, dan BIGINT, sedangkan untuk bilangan pecahan gunakan DECIMAL, FLOAT, dan DOUBLE.



Jangkauan data dan ruang penyimpanan yang diperlukan oleh masing masing tipe data seperti tampak pada tabel 6.1: Value



Storage (byte)



TINYINT ([M])



Signed: -128 s.d 127, Unsigned: 0 s.d 255



1



SMALLINT ([M])



Signed: -32768 s.d 32767, Unsigned: 0 s.d 65535



2



MEDIUMINT ([M])



Signed: -32768 s.d 32767, Unsigned: 0 s.d 16777215



3



INT ([M])



Signed: -2147483648 s.d 2147483648, Unsigned: 0 s.d 4294967295



4



BIGINT ([M])



Signed: -9223372036854775808 s.d 9223372036854775807, Unsigned: 0 s.d 18446744073709551615



8



DECIMAL([M,D])



Tergantung nilai M dan D



Tergantung M dan D



FLOAT[(M,D)]



Minimum Nonzero Value: ±1.175494351E-38 s.d ± 3.402823466E+38



4



DOUBLE [(M,D)]



Minimum Nonzero Value: ± 2.2250738585072014E-308 s.d ± 1.7976931348623157E+308



8



BIT



0 s.d 2M-1, dimana 1 ≤ M ≤ 64



Tipe Data



Tergantung M



Tabel 6.1 Jangkauan dan ruang penyimpanan tipe data numeric



64 BAB 6 Tipe Data



6.1.1. Exact Value Exact value (integer) dapat terdiri dari nilai positif maupun negatif, untuk dapat menampung kedua nilai tersebut gunakan atribut SIGNED sedangkan untuk nilai positif saja, gunakan UNSIGNED, nilai defaultnya adalah SIGNED.. Dengan UNSIGNED, nilai yang dapat ditampung 2 kali lipat dari signed. Keduanya membutuhkan ruang penyimpanan yang sama dan memiliki performance yang sama. Misal untuk tipe data INT, signed dapat menampung -128 s.d 127, sedangkan unsigned 0 s.d 255 Masing masing tipe data Integer dapat kita definisikan panjang data nya, namun panjang data ini tidak berpengaruh apa apa, baik pada besarnya ruang penyimpanan maupun banyaknya data yang ditampung. Misal meskipun kita mendefinisikan integer dengan TINYINT(2), kita tetap dapat memasukkan nilai 126, disamping itu, ruang penyimpanan yang digunakan tetap 1 byte (4 bits), sehingga, untuk praktisnya, kita tidak perlu menentukan panjang data, biarkan MySQL yang mendefinisikannya. Contoh penggunaan tipe data numeric adalah ketika kita membuat tabel nilai ujian dengan rentang nilai 0 s.d 100, karena nilai dibawah 127, maka maka tipe data yang pas adalah TINYINT. Contoh lain adalah ketika kita ingin menyimpan data pembayaran nasabah bank, karena nilainya besar dan nilainya selalu positif, maka kita gunakan tipe data INT UNSIGNED, namun, ketika suatu saat nilai data yang disimpan melebih batas, misal Rp. 5 milyar, maka data tersebut akan terpotong menjadi 4.294.967.295 (batas maksimal tipe data INT UNSIGNED), sehingga perlu diubah menjadi BIGINT.



6.1.2. Desimal Bentuk kedua setelah fixed point adalah decimal. Pada jenis ini, terdapat tiga tipe data yang dapat digunakan, DECIMAL (fixed point), FLOAT dan DOUBLE (floating point).



6.1.2.1. Fixed Point DECIMAL merupakan fixed-point data type, yang artinya banyaknya digit desimal tetap (fixed), misal jika sudah ditetapkan banyaknya desimal di



Panduan Lengkap Query MySQL 65



belakang koma sebanyak 2 digit, maka ketika kita isikan 0.2, data akan berubah menjadi 0.20, jika 0, maka 0.00, namun jika kita isikan 0.255, akan muncul error karena jumlah digit melebih batas maksimal. Dengan karakteristik tersebut, seringnya tipe data ini digunakan untuk menyimpan data keuangan. Untuk mendefinisikan tipe data DECIMAL, kita perlu memberikan parameter jumlah maksimum keseluruhan digit (termasuk digit desimal) dan jumlah digit desimal dengan format: DECIMAL(M, D)



Misal DECIMAL(3,2) berarti jumlah keseluruhan digit adalah 3 dan jumlah digit desimal adalah 2, contoh: 0.25, 5.15, dan 7.33. Jumlah maksimal nilai M adalah 65, sedangkan D 30 digit, dimana nilai D tidak boleh lebih besar dari M. M dan D sifatnya opsional, jika D tidak didefinisikan, maka akan otomatis diberi nilai 0, jika M tidak didefinisikan, maka akan diberi nilai 10. Sehingga jika kita mendefinisikan DECIMAL saja tanpa D dan M, maka akan sama dengan DECIMAL(10,0) Tipe data DECIMAL juga dapat diberi atribut UNSIGNED, namun tidak seperti pada INTEGER, unsigned pada DECIMAL hanya membatasi nilai negatif, tidak memperbesar jangkauan data yang dapat ditampung. Contoh jangkauan data DECIMAL Definisi



Range (SIGNED)



Range (UNSIGNED)



DECIMAL(4,1)



-999.9 s.d 999.9



0.0 s.d 999.9



DECIMAL(4, 2)



-99.99 s.d 99.99



0.00 s.d 9.99



DECIMAL(5, 1)



-99999.9 s.d 99999.9



0.00 s.d 99999.9



DECIMAL(5, 2)



-99999.99 99999.99



0.00 s.d 99999.9



s.d



Tabel 6.2 Jangkauan data tipe data DECIMAL



66 BAB 6 Tipe Data



6.1.2.2. Floating Point Selain DECIMAL, terdapat dua tipe data lain yang dapat digunakan untuk menyimpan desimal yaitu FLOAT dan DOUBLE, keduanya memiliki sifat floating-point (nilai desimal yang tidak tetap), kebalikan dari DECIMAL yang memiliki sifat fixed-point. Perbedaan keduanya ada pada penggunaan ruang penyimpanan, selain itu, jumlah digit desimal yang dapat ditampung juga tidak sama. FLOAT merupakan 4 byte single-precision yang biasanya akurasinya mencapai 7 digit desimal, sedangkan DOUBLE merupakan 8 byte double-precision yang biasanya akurasinya mencapai 15 digit desimal. Sama seperti DECIMAL, FLOAT dan DOUBLE juga dapat menerima atribut UNSIGNED yang artinya hanya dapat menerima nilai positif, selain itu, FLOAT dan DOUBLE juga dapat menerima argumen M dan D. Nilai dari M antara 1 s.d 255, sedangkan untuk D antara 0 s.d 30, dan tidak boleh lebih besar dari M. M dan D bersifat opsional, jika keduanya tidak didefinisikan, maka desimal akan disimpan dengan presisi penuh (full precision) yang dapat dilakukan oleh hardware komputer. Tidak seperti DECIMAL, FLOAT dan DOUBLE akan melakukan pembulatan jika jumlah digit melebihi jumlah yang telah ditentukan, misal pada kolom dengan tipe data FLOAT (4,2), jika kita masukkan nilai 10.155, maka akan diubah menjadi 10.16. Disamping itu, keduanya menyimpan nilai yang sifatnya perkiraan (approximate-value) artinya data yang tersimpan tidak benar sama dengan apa yang terlihat. Misal kita memiliki tabel tes_float sebagai berikut: mysql> SELECT * FROM tes_float; +------+-----------+-------------+ | id | float_col | decimal_col | +------+-----------+-------------+ | 1 | 10.15 | 10.15 | | 2 | 20.25 | 20.25 | +------+-----------+-------------+ 2 rows in set (0.00 sec)



Panduan Lengkap Query MySQL 67



Selanjutnya jika kita ambil data dengan nilai 10.15 pada kolom float_col, maka kita tidak akan memperoleh hasil apa-apa mysql> SELECT * FROM tes_float WHERE float_col = 10.15; Empty set (0.00 sec)



Sebaliknya, jika kita ambil data berdasarkan kolom decimal_col maka akan memperoleh hasil sesuai yang kita harapkan mysql> SELECT * FROM tes_float WHERE decimal_col = 10.15; +------+-----------+-------------+ | id | float_col | decimal_col | +------+-----------+-------------+ | 1 | 10.15 | 10.15 | +------+-----------+-------------+ 1 row in set (0.00 sec)



Hal ini terjadi karena pada tipe data decimal, nilai yang disimpan benar benar 10.15, sedangkan pada float, nilai yang disimpan bukan 10.15, mari kita tes: mysql> SELECT 1 * float_col, 1 * decimal_col FROM tes_float; +--------------------+-----------------+ | 1 * float_col | 1 * decimal_col | +--------------------+-----------------+ | 10.149999618530273 | 10.15 | | 20.25 | 20.25 | +--------------------+-----------------+ 2 rows in set (0.00 sec)



Dari berbagai contoh diatas, dapat diketahui bahwa tipe data floating-point memiliki nilai yang tidak pasti, sehingga agak merepotkan, untuk itu, utamakan menggunakan tipe data decimal.



6.1.3. BIT Tipe data BIT digunakan untuk menyimpan data binary digit (BIT), binary merupakan kombinasi angka yang terdiri dari 0 dan 1. BIT memiliki kapasitas 1 hingga 64 digit, jika panjang digit tidak didefinisikan, maka secara default panjangnya adalah 1 digit. BIT(1) hanya dapat menyimpan sebuah nilai 0 atau 1, BIT(2) dapat menyimpan 2 digit kombinasi 0 dan 1, 68 BAB 6 Tipe Data



yaitu 00, 01, 10, dan 11. BIT(3) dapat menyimpan 3 digit kombinasi, yaitu: 000, 001, 011, 111, 101, dst. MySQL menggunakan notasi b'value' untuk mengubah digit ke string, misal: b'101010'. Notasi tersebut digunakan ketika kita memasukkan data ke kolom dengan tipe data bit, contoh: INSERT INTO `tes_bit` (`id`, `bit_digit`) VALUES ('2', b'101');



Untuk menampilkan data BIT, kita gunakan fungsi BIN() mysql> SELECT BIN(bit_digit) FROM tes_bit; +----------------+ | BIN(bit_digit) | +----------------+ | 1 | | 101 | +----------------+ 2 rows in set (0.00 sec)



6.1.4. Bool atau Boolean Tipe data BOOL atau BOOLEAN digunakan untuk menyimpan nilai true dan false yang diwakili dengan nilai 1 untuk true dan 0 untuk false. Tipe data ini sering digunakan untuk memberi tanda suatu record, misal pada tabel user, untuk memberi tanda bahwa user tersebut aktif, pada kolom status diberi nilai 1 sedangkan untuk yang non aktif diberi nilai 0 Contoh penggunaan tipe data Boolean saat membuat tabel: CREATE TABLE `test`.`user` ( `username` VARCHAR(50) NOT NULL , `status`BOOLEAN NOT NULL ) ENGINE = InnoDB;



Pada contoh diatas, BOOLEAN dapat diganti BOOL. Contoh data untuk tabel user: mysql> SELECT * FROM user; +----------+--------+ | username | status |



Panduan Lengkap Query MySQL 69



+----------+--------+ | ANDI | 0 | | ANTONY | 1 | +----------+--------+ 2 rows in set (0.00 sec) BOOLEAN ini merupakan alias dari TINYINT(1), pada contoh diatas,



meskipun kita membuat tabel user dengan tipe data BOOLEAN, jika kita lihat struktur tabel tersebut maka terlihat bahwa tipe data kolom status adalah TINYINT(1) mysql> SHOW CREATE TABLE user\G; *************************** 1. row *************************** Table: user Create Table: CREATE TABLE `user` ( `username` varchar(50) NOT NULL, `status` tinyint(1) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 1 row in set (0.00 sec)



Karena panjang data maksimal TINYINT adalah 127, maka kolom status tersebut dapat kita isi nilai 0 s.d 127, tidak hanya 1 atau 0, meski demikian tipe data tersebut hanya membutuhkan ruang 1 byte



6.1.5. Atribut Pada Numeric Ketika membuat tabel, kita harus mendefinisikan tipe data dan panjang data pada kolom, untuk tipe data numeric, panjang data sifatnya opsional, tidak harus ada, selain itu, ada beberapa atribut yang dapat kita tambahkan, yaitu UNSIGNED, ZEROFILL, dan AUTO_INCREMENT. Misal: 1. CREATE TABLE `tes_numeric_attribute` ( 2. `int_ai` INT(11) UNSIGNED NOT NULL 3. AUTO_INCREMENT, 4. `tinyint_uz` TINYINT(3) ZEROFILL NOT NULL, 5. PRIMARY KEY (`int_ai`) )



70 BAB 6 Tipe Data



Atribut UNSIGNED dapat diterapkan ke semua tipe data numeric kecuali BIT. Seperti yang telah kita bahas sebelumnya, pada tipe data INTEGER, UNSIGNED dapat meningkatkan jangkauan data, misal untuk TINYINT bisa mencapai 256, dibanding SIGNED yang hanya 127, UNSIGNED cocok digunakan untuk menyimpan data yang tidak memiliki nilai negatif (jenis data ini yang paling sering kita gunakan), misal data pembayaran, jumlah stok, nilai ujian, dll. Selain itu, terdapat juga atribut ZEROFILL. Seperti terjemahannya, yaitu isi dengan nol, dengan atribut ini, maka jika data yang akan dimasukkan memiliki panjang data lebih kecil dari yang telah ditetapkan, maka di depannya akan ditambahkan angka 0 sebanyak sisa digit yang kurang. Misal: mysql> INSERT INTO `tes_numeric_attribute` (`tinyint_uz`) VALUES ('1'); Query OK, 1 row affected (0.09 sec) mysql> SELECT * FROM tes_numeric_attribute; +--------+------------+ | int_ai | tinyint_uz | +--------+------------+ | 1 | 001 | +--------+------------+ 1 row in set (0.00 sec)



Sebagai tambahan, jika kita gunakan atribut ZEROFILL, maka otomatis, kolom tersebut beratribut UNSIGNED. Atribut AUTO INCREMENT dapat diterapkan baik pada tipe data integer maupun floating point. Gunakan atribut ini jika kita ingin memiliki kolom dengan angka unik yang berurutan (series) seperti (1, 2, 3, dst…). Agar MySQL memberikan angka series maka ketika memasukkan data, kolom tersebut tidak perlu diisi, atau diisi dengan nilai NULL, seperti pada contoh diatas ( INSERT pada tabel tes_numeric_attribute). Urutan digit tersebut akan terus berlanjut meski ada baris yang dihapus, contoh mysql> DELETE FROM tes_numeric_attribute WHERE int_ai = 1; Query OK, 1 row affected (0.04 sec)



Panduan Lengkap Query MySQL 71



mysql> INSERT INTO `tes_numeric_attribute` (`tinyint_uz`) VALUES ('1'); Query OK, 1 row affected (0.14 sec) mysql> SELECT * FROM tes_numeric_attribute; +--------+------------+ | int_ai | tinyint_uz | +--------+------------+ | 2 | 001 | +--------+------------+ 1 row in set (0.00 sec)



Pada contoh diatas, terlihat bahwa setelah data dihapus, nilai kolom int_ai melanjutkan nilai series digit berikutnya yaitu 2. Nilai series digit akan direset jika kita kosongkan tabel menggunakan statemen TRUNCATE TABLE. Dalam satu tabel, hanya boleh ada satu kolom dengan atribut AUTO INCREMENT dan kolom tersebut harus memiliki constraint NOT NULL, jika kita tidak mendefinisikan constraint tersebut, maka MySQL otomatis akan menambahkannya, selain itu, kolom tersebut juga harus menjadi index, umumnya index yang digunakan adalah PRIMARY KEY atau UNIQUE KEY. Karena urutan digit selalu positif (dimulai dari 1), maka agar jangkauan data lebih lebar, kolom tersebut dapat kita beri atribut UNSIGNED



6.2. String String yang kita kenal umumnya berupa teks, namun demikian, string juga dapat berupa data biner (binary) seperti file gambar, suara, dll. MySQL menyediakan berbagai tipe data untuk menyimpan string, tabel 15.1 berisi daftar tipe data string yang didukung oleh MySQL Tipe Data



Maksimal



Ruang penyimpanan



CHAR [(M)]



M Karakter



M x W bytes



VARCHAR (M)



M Karakter



L + 1 atau 2 bytes



TINYTEXT



28 – 1 bytes



L + 1 bytes



TEXT, BLOB



216 – 1 bytes



L + 2 bytes



72 BAB 6 Tipe Data



MEDIUMTEXT, MEDIUMBLOB



224 – 1 bytes



L + 3 bytes



LONGTEXT, LONGBLOB



232 – 1 bytes



L + 4 bytes



BINARY [(M)]



M bytes



M bytes



VARBINARY (M)



M bytes



L + 1 atau 2 bytes



ENUM



65.535 data



1 atau 2 bytes



SET



64 data



1, 2, 3, 4, atau 8 bytes



Tabel 6.3 Jangkauan dan ruang penyimpanan tipe data character Keterangan: 



M atau Maksimum merupakan panjang data maksimal dalam (1) byte untuk tipe data BYNARY atau VARBINARY dan (2) karakter untuk CHAR atau VARCHAR. Misal CHAR(10) hanya dapat menampung karakter maksimal sebanyak 10 karakter.







W atau width merupakan besarnya byte tiap satu karakter. Hal ini tergantung dari jenis karakter set. Untuk karakter ASCII (yang sering kita gunakan - bahasa Indonesia atau Inggris) nilai w adalah 1 byte, sedangkan untuk karakter khusus seperti arab, nilai w bisa 2-3 byte.







L atau length merupakan panjang data aktual dalam byte, misal untuk CHAR, L diperoleh dari M x W, sedangkan untuk Binary L = M.



Berdasarkan keterangan diatas, maka untuk tipe data BINARY(20) dapat menampung data sebesar 20 byte, CHAR(20) dapat menampung 20 karakter (20 byte untuk karakter ASCII), dan TEXT dapat menampung 216 – 1 bytes atau 65.535 byte, jika ukuran 1 karakter adalah 1 byte (seperti pada ASCII) maka tipe data TEXT dapat menampung 65.535 karakter.



6.2.1. CHAR dan VARCHAR Tipe data CHAR digunakan untuk menyimpan karakter dengan panjang data tetap, dan VARCHAR untuk panjang data yang tidak tetap, ruang penyimpanan yang digunakan juga berbeda, pada CHAR, ruang penyimpanan yang digunakan tetap, berapapun jumlah data yang ada, misal CHAR(10) akan selalu menggunakan ruang 10 byte, meskipun data Panduan Lengkap Query MySQL 73



tersebut hanya terdiri dari tiga karakter. Sebaliknya, pada VARCHAR, ruang penyimpanan berbeda beda tergantung banyaknya karakter, misal pada VARCHAR(10), jika data yang disimpan hanya 3 karakter, maka ruang penyimpanan yang digunakan hanya 4 byte (3 bute + 1 Byte). Mungkin Anda bertanya tanya kalau begitu bukankah lebih efisien untuk selalu menggunakan tipe data VARCHAR? Jawabnya tidak selalu, tergantung kondisi yang ada. Berikut ini beberapa hal yang dapat dipertimbangkan ketika menggunakan CHAR atau VARCHAR 



Untuk data yang panjang datanya berubah ubah seperti data nama, maka lebih efisien menggunakan VARCHAR, misal VARCHAR(50), sehingga nama yang terdiri dari 7 karakter akan membutuhkan space 8-9 byte, namun jika kita gunakan CHAR(50) nama dengan jumlah karakter berapapun akan membutuhkan tempat penyimpanan 50 byte.







Untuk data yang panjangnya tetap gunakan tipe data CHAR, misal pada NIK pegawai yang panjangnya selalu 9 digit, kita gunakan tipe data CHAR(9), jika menggunakan tipe data VARCHAR(9) maka akan memerlukan tambahan ruang 1 atau 2 byte.







Pada VARCHAR, selalu gunakan panjang data sesuai kebutuhan. Misal, tidak ada nama yang jumlah karakternya melebihi 50 karakter, sehingga tidak efisien jika kita menggunakan VARCHAR(255), kenapa demikian? Bukankah jika panjang nama 50 karakter tetap hanya memerlukan tempat 51 – 52 byte? Jawabnya iya, namun, ketika kita melakukan JOIN atau statemen lain yang menyebabkan MySQL membuat temporary tabel di memory (RAM) maka akan memakan tempat sebanyak panjang maksimal data yang ditampung tipe data tersebut yaitu 255 byte.







Pada tipe data CHAR, tambahan spasi di depan maupun di belakang string akan dihilangkan, misal 'Nama ' atau ' Nama ' akan disimpan menjadi 'Nama', hal ini tidak terjadi pada VARCHAR.







Sebagai tambahan, jika storage engine yang kita gunakan adalah MyISAM dan perbedaan jumlah karakter yang akan disimpan tidak



74 BAB 6 Tipe Data



terlalu besar, maka kita dapat menggunakan CHAR, karena MyISAM lebih efisien dalam memproses fixed-length character dalam hal ini CHAR dibanding VARCHAR.



6.2.2. TEXT vs BLOB TEXT dan BLOB sama sama digunakan untuk menyimpan string, namun demikian keduanya memiliki karakteristik berbeda. BLOB merupakan kependekan dari Binary Large Object. Tipe data BLOB dapat digunakan untuk menyimpan data apa saja. Varian BLOB, yaitu TINYBLOB, BLOB, MEDIUMBLOB, LONGBLOB memiliki fungsi yang sama hanya berbada pada kapasitas penyimpanannya saja.



Tipe data TEXT umumnya text digunakan untuk menyimpan string yang panjang, misal untuk artikel pada suatu website, deskripsi produk, dll, sedangkan BLOB digunakan untuk menyimpan binary string dari file seperti binary string file gambar. Contoh pada PHP: 1. $id = 1; 2. $binary = file_get_contents(gambar.jpg); 3. $query = 'INSERT INTO gallery (id, file) VALUES ($id, $binary)';



Lebih lanjut, perbedaan keduanya adalah pada TEXT, terdapat beberapa konfigurasi yang diterapkan ketika melakukan perbandingan string seperti penggunaan character set, collation, case sensitify, dan index (jika ada), sehingga diperlukan pekerjaan ekstra bagi MySQL, sedangkan string pada BLOB disimpan apa adanya, tidak ada tambahan konfigurasi. Berdasarkan hal tersebut, jika data yang kita simpan berupa plain teks seperti binary string, maka selalu gunakan tipe data BLOB.



6.2.3. ENUM dan SET ENUM dan SET merupakan tipe data yang hanya menerima nilai dari daftar yang sudah ditetapkan. Misal kolom yang didefinisikan dengan ENUM('Alpha', 'Beta', 'Charlie') hanya dapat diisi oleh salah satu dari ketiga nilai tersebut, yaitu 'Alpha’ saja, 'Beta' saja, atau 'Charlie'.



Panduan Lengkap Query MySQL 75



Sedangkan untuk SET dapat menerima kombinasi dari nilai yang ada, sehingga jika suatu kolom didefinisikan dengan SET('Alpha', 'Beta', 'Charlie'), maka kolom tersebut dapat menerima nilai: 'Alpha', 'Alpha,Beta', 'Alpha,Beta,Charlie', dsb… Tipe data ENUM umumnya digunakan untuk menyimpan data opsi yang bernilai tunggal. Misal untuk opsi jenis kelamin ENUM('L', 'P') atau opsi yang hanya memberikan nilai Yes atau No ENUM('Y', 'N'). Contoh lain: opsi ukuran produk ENUM('S','M','L','XL'), opsi warna ENUM('Hitam','Merah','Biru'), atau survey dengan jawaban yang telah ditentukan. Tipe data SET umumnya digunakan untuk menyimpan data opsi bernilai jamak. Karakteristik opsi yang bernilai jamak adalah opsi satu dengan yang lain dapat saling menggantikan, tidak berdiri sendiri, misal data pilihan universitas pada pendaftaran beasiswa, gunakan tipe data ENUM('UI', 'UGM','UNS'), sehingga pilihan dapat berupa UGM saja, UI,UGM, UGM,UNS, dst.. Secara internal, daftar pada ENUM dan SET disimpan berdasarkan urutan index, dimana nilai awal index adalah 1, sehingga jika kita melakukan pengurutan data, maka akan diurutkan berdasarkan index, bukan string. Misal kita memiliki tabel tes_enum sebagai berikut: 1. CREATE TABLE `tes_enum` ( 2. `col_enum` ENUM('Charlie','Alfa','Beta') NULL DEFAULT NULL 3. )



Selanjutnya kita isi dengan data sebagai berikut: 1. 2. 3. 4.



INSERT INSERT INSERT INSERT



INTO INTO INTO INTO



`tes_enum` `tes_enum` `tes_enum` `tes_enum`



(`col_enum`) (`col_enum`) (`col_enum`) (`col_enum`)



VALUES VALUES VALUES VALUES



('Alfa'); ('Beta'); ('Charlie'); ('Charlie');



Jika data kita urutkan berdasarkan abjad (col_enum), maka hasil yang kita peroleh adalah:



76 BAB 6 Tipe Data



mysql> SELECT * FROM tes_enum ORDER BY col_enum ASC; +----------+ | col_enum | +----------+ | Charlie | | Charlie | | Alfa | | Beta | +----------+ 4 rows in set (0.00 sec)



Pada contoh diatas, terlihat bahwa data tidak diurutkan berdasarkan abjad. Hal ini dikarenakan data yang disimpan pada kolom col_enum bukanlah string melainkan angka index, perhatikan contoh berikut: mysql> SELECT col_enum, col_enum * 1 AS col_index FROM tes_enum ORDER BY col_enum DESC; +----------+-----------+ | col_enum | col_index | +----------+-----------+ | Alfa | 3 | | Beta | 2 | | Charlie | 1 | | Charlie | 1 | +----------+-----------+ 4 rows in set (0.03 sec)



pada contoh diatas terlihat bahwa data diurutkan berdasarkan index terbesar yaitu 3. Khusus pada ENUM dan SET, jika kita ingin mengurutkan data berdasarkan abjad kita gunakan fungsi CAST(), misal: mysql> SELECT col_enum FROM tes_enum ORDER BY CAST(col_enum AS CHAR) ASC; +----------+ | col_enum | +----------+ | Alfa | | Beta | | Charlie | | Charlie | +----------+ 4 rows in set (0.00 sec)



Panduan Lengkap Query MySQL 77



Pada ENUM dan SET, kita juga dapat memfilter data berdasarkan index nya, misal: mysql> SELECT col_enum FROM tes_enum WHERE col_enum = 3; +----------+ | col_enum | +----------+ | Alfa | +----------+ 1 row in set (0.05 sec)



Selain itu, kita juga dapat memfilter data berdasarkan nilainya, misal: mysql> SELECT col_enum FROM tes_enum WHERE col_enum = 'alfa'; +----------+ | col_enum | +----------+ | Alfa | +----------+ 1 row in set (0.00 sec)



6.3. DATE dan TIME MySQL menyediakan berbagai tipe data terkait dengan waktu yaitu: DATE, TIME, DATETIME, YEAR, dan TIMESTAMP, fomat tanggal dan waktu yang digunakan adalah: Tipe Data



Format



DATE



YYYY-MM-DD



TIME



HH:MM:SS[.microsecond]



DATETIME



YYYY-MM-DD HH:MM:SS[.microsecond]



TIMESTAMP



YYYY-MM-DD HH:MM:SS[.microsecond]



YEAR



YYYY



Tabel 6.4 Format tanggal dan waktu tipe data datetime Masing masing tipe data tersebut membutuhkan ruang penyimpanan tertentu serta memiliki nilai minimum dan maksimum, detailnya seperti tampak pada tabel 6.5: 78 BAB 6 Tipe Data



Tipe Data



Storage (byte)



Minimum



Maksimum



DATE



3



1000-01-01



9999-12-31



TIME



3+(fp)



-838:59:59[.000000]



838:59:59[.000000]



DATETIME



8+(fp)



1000-01-01 00:00:00[.000000]



9999-12-31 23:59:59[.999999]



TIMESTAMP



4+(fp)



1970-01-01 00:00:00[.000000]



2038-01-19 03:14:07[.999999]



YEAR



1



1901



2155



Tabel 6.5 Jangkauan dan ruang penyimpanan tipe data datetime Pada tabel diatas, fsp merupakan kependekan dari Fractional Seconds Precision. Fsp menunjukkan banyaknya microsecond yang dapat ditambahkan, maksimal 6 digit. Jumlah ruang yang dibutuhkan oleh fsp adalah: Jumlah digit



Storage



0



0 byte



1,2



1 byte



3,4



2 byte



5,6



3 byte Tabel 6.6 Ruang penyimpanan microsecond



6.3.1. DATE Pada MySQL, tanggal (date) harus ditulis menggunakan format tertentu, format tanggal yang digunakan adalah 4 digit tahun, 2 digit bulan, dan 2 digit tanggal, dengan separator dash (-), misal 2017-03-10. Format ini merupakan format baku sesuai spesifikasi standar SQL dalam ISO 8601. Jika kita memasukkan data dengan format yang tidak baku, maka kita perlu mengubahnya ke bentuk baku menggunakan fungsi STR_TO_DATE, misal: mysql> INSERT INTO tes_date (col_date) VALUES (STR_TO_DATE('3-52017', '%d-%m-%Y'));



Panduan Lengkap Query MySQL 79



Query OK, 1 row affected (0.09 sec) mysql> SELECT * FROM tes_date; +------------+ | col_date | +------------+ | 2017-05-03 | +------------+ 1 row in set (0.04 sec)



Selanjutnya jika ingin mengubah format ketika melakukan pengambilan data, maka dapat menggunakan fungsi DATE_FORMAT(), misal: mysql> SELECT DATE_FORMAT(col_date, '%d/%m/%Y') AS tanggal FROM tes_date; +------------+ | tanggal | +------------+ | 03/05/2017 | +------------+ 1 row in set (0.00 sec)



Fungsi STR_TO_DATE() dan DATE_FORMAT() dibahas lebih lanjut di BAB 12 Functions



6.3.2. TIME Pada MySQL, waktu (time) juga harus ditulis menggunakan format tertentu. Standard format waktu yang digunakan adalah jam:menit:detik yang masing masing terdiri dari dua digit, misal 10:08:17. Sebagai tambahan, kita dapat menambahkan microsecond hingga 6 digit, misal 15:08:10.436574. Pendefinisian jumlah digit microsecond (Fractional Seconds - fs) kita lakukan saat mendefinisikan kolom, yaitu dengan format tipedata_waktu(fs). tipedata_waktu dapat berupa DATETIME, TIME, atau TIMESTAMP. Jika data yang dimasukkan melebihi batas digit fs yang yang telah ditentukan, maka akan dilakukan pembulatan. Untuk digit dengan nilai lebih besar atau sama dengan 5, akan dibulatkan ke atas, sedangkan dibawah 5 akan dihilangkan. Perhatikan contoh berikut:



80 BAB 6 Tipe Data



mysql> CREATE TABLE tes_time(col_datetime DATETIME(3), col_time TIME(3)); Query OK, 0 rows affected (0.49 sec) mysql> INSERT INTO tes_time (col_datetime, col_time) VALUES ('2017-03-04 10:05:55.5465', '10:05:55.5464'); Query OK, 1 row affected (0.05 sec) mysql> SELECT * FROM tes_time; +-------------------------+--------------+ | col_datetime | col_time | +-------------------------+--------------+ | 2017-03-04 10:05:55.547 | 10:05:55.546 | +-------------------------+--------------+ 1 row in set (0.00 sec)



Pada contoh diatas, digit ke 4 microsecond pada data pertama dibulatkan keatas, sedangkan pada data ke 2 dihilangkan. Perlu diperhatikan bahwa untuk memasukkan data waktu, kita harus menuliskannya secara penuh, misal ingin memasukkan 30 menit 12 detik, maka kita perlu menuliskannya 00:30:12, atau jika detik saja, maka kita gunakan format 00:00:12. Ketika memasukkan data tanggal dan waktu pada kolom dengan tipe data tanggal atau waktu saja, maka otomatis data tersebut disesuaikan dengan tipe data kolom, misal: mysql> TRUNCATE TABLE tes_date; Query OK, 0 rows affected (0.26 sec) mysql> INSERT INTO tes_date (col_date, col_datetime, col_time) VALUES (NOW(), NOW(), NOW()); Query OK, 1 row affected, 1 warning (0.04 sec) mysql> SELECT * FROM tes_date; +------------+---------------------+----------+ | col_date | col_datetime | col_time | +------------+---------------------+----------+ | 2017-03-04 | 2017-03-04 10:15:28 | 10:15:28 | +------------+---------------------+----------+ 1 row in set (0.00 sec)



Panduan Lengkap Query MySQL 81



Pada contoh diatas, fungsi NOW() akan menghasilkan 2017-03-04 10:15:28, ketika dimasukkan ke kolom dengan tipe data DATE maka akan masuk data tanggal saja, DATETIME akan masuk data tanggal dan waktu, dan TIME akan masuk data waktu saja.



6.3.3. YEAR Tipe data YEAR digunakan untuk menyimpan data tahun. Jumlah digit tahun bisa 2 atau 4, defaultnya 4 digit tahun. Digit tersebut didefinisikan ketika mendefinisikan kolom, yaitu YEAR(4) untuk 4 digit tahun dan YEAR(2) untuk 2 digit tahun. YEAR dengan panjang 4 digit dapat menampung tahun mulai dari tahun 1901 2155 Dua digit tahun akan mengambil tahun dari belakang sebanyak dua digit, misal 17 untuk tahun 2017. Rentang tahun yang dapat disimpan adalah 1970 s.d 2069. Jika diluar itu, maka data menjadi ambigu misal 70 dapat berarti 1970 dan 2070, karena kekurangan ini, maka mulai MySQL versi 5.6.6, penggunaan dua digit tahun sudah tidak disarankan lagi (deprecated).



6.3.4. TIMESTAMP TIMESTAMP merupakan gabungan dari DATE dan TIME dalam format UNIX



timestamp, disebut timestamp karena tipe data ini merujuk ke waktu tertentu, lebih tepatnya detik tertentu dari waktu tertentu. Acuan waktu untuk TIMESTAMP adalah 1970-01-01 00:00:00, sehingga timestamp 1 berarti 1970-01-01 00:00:01 TIMESTAMP sendiri memiliki rentang mulai dari 1970-01-01 00:00:01.000000 s.d 2038-01-19 03:14:07.999999, range tersebut mengikuti aturan Unix time, dimana hari pertama dari tahun 1970 (197001-01) merupakan “day zero” atau lebih dikenal the epoch. TIMESTAMP menyimpan data dalam bentuk Universal Coordinated Time (UTC). Ketika kita menyimpan waktu ke dalam TIMESTAMP, maka waktu



tersebut akan diubah ke dalam bentuk UTC (atau GMT + 0) kemudian disimpan ke dalam database. Untuk mengetahui waktu UTC, dapat menggunakan perintah berikut: 82 BAB 6 Tipe Data



mysql> SELECT UTC_TIMESTAMP; +---------------------+ | UTC_TIMESTAMP | +---------------------+ | 2017-03-04 03:34:56 | +---------------------+ 1 row in set (0.00 sec)



Query tersebut dijalankan pukul 10:34:56, sehingga waktu UTC atau GMT + 0 adalah pukul 03:34:56 atau selisih 7 jam, hal tersebut karena kita menggunakan zona waktu GMT + 7. Untuk mengetahui time zone yang sedang digunakan, buka variabel @@session.time_zone mysql> SELECT @@session.time_zone; +---------------------+ | @@session.time_zone | +---------------------+ | +07:00 | +---------------------+ 1 row in set (0.00 sec)



Selanjutnya, jika data tersebut dipanggil maka akan diubah menjadi GMT sesuai dengan zona waktu user yang memanggilnya (hal ini tidak terjadi pada tipe data lain seperti DATETIME). Misal: mysql> CREATE TABLE tes_timestamp (col_timestamp TIMESTAMP); Query OK, 0 rows affected (0.43 sec) mysql> INSERT INTO tes_timestamp (col_timestamp) VALUES ( NOW() ); Query OK, 1 row affected (0.06 sec) mysql> SELECT * FROM tes_timestamp; +---------------------+ | col_timestamp | +---------------------+ | 2017-03-04 10:40:15 | +---------------------+ 1 row in set (0.00 sec)



Panduan Lengkap Query MySQL 83



Pada contoh diatas, dengan fungsi NOW(), kita memasukkan data waktu sekarang, namun secara internal, MySQL menyimpannya dalam waktu UTC, ketika kita panggil data tersebut, maka akan ditampilkan data waktu saat data dimasukkan, yaitu: 2017-03-04 10:40:15. Jika kita ubah zona waktunya, maka tanggal juga akan ikut menyesuaikan, misal: mysql> SET time_zone = '+03:00'; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM tes_timestamp; +---------------------+ | col_timestamp | +---------------------+ | 2017-03-04 02:05:07 | +---------------------+ 1 row in set (0.00 sec)



6.3.5. DATETIME vs TIMESTAMP Baik DATETIME maupun TIMESTAMP, kedua memiliki persamaan dan perbedaan. Adapun persamaannya adalah: 



Keduanya memiliki format yang sama yaitu YYYY-MM-DD HH:II:SS







Pada pendefinisian kolom, keduanya dapat diberikan nilai default baik untuk INSERT maupun UPDATE berupa CURRENT_TIMESTAMP atau NOW. Pada DATETIME fitur ini mulai ada pada MySQL versi 5.6.5 Misal: CREATE TABLE `tes_default_timestamp` ( `id` INT(11), `insert_data` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, `update_data` DATETIME ON UPDATE CURRENT_TIMESTAMP )



Pada contoh diatas, CURRENT_TIMESTAMP dapat diganti dengan fungsi NOW(), keduanya memiliki fungsi yang sama. Selanjutnya mari kita isikan data: mysql> INSERT INTO tes_default_timestamp (id) VALUES (1);



84 BAB 6 Tipe Data



Query OK, 1 row affected (0.22 sec) mysql> SELECT * FROM tes_default_timestamp; +------+---------------------+---------------------+ | id | insert_data | update_data | +------+---------------------+---------------------+ | 1 | 2017-03-05 08:52:46 | NULL | +------+---------------------+---------------------+ 1 row in set (0.00 sec)



Ketika kita isi kolom id dengan nilai 1 maka kolom insert_data otomatis terisi waktu ketika data ditambahkan. Selanjutnya mari kita lakukan update data: mysql> UPDATE tes_default_timestamp SET id = 2; Query OK, 1 row affected (0.08 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> SELECT * FROM tes_default_timestamp; +------+---------------------+---------------------+ | id | insert_data | update_data | +------+---------------------+---------------------+ | 2 | 2017-01-02 08:56:23 | 2017-03-05 09:02:47 | +------+---------------------+---------------------+ 1 row in set (0.00 sec)



Dari data diatas terlihat bahwa kolom update_data berisi waktu ketika proses update dilakukan. Meskipun memiliki persamaan, keduanya memiliki perbedaan yang cukup mendasar, diantaranya adalah: 



DATETIME memiliki jangkauan waktu yang sangat lebar mulai 1000-0101 00:00:00 hingga 9999-12-31 23:59:59 dengan demikian kita tidak perlu khawatir dengan keterbatasan waktu seperti pada TIMESTAMP yang hanya dapat menyimpan tanggal antara tahun 1970 s.d 2038.







DATETIME dapat menyimpan data secara parsial, misal pada data waktu yang bervariasi kita dapat menyimpan hanya data tahun dan bulan, dengan format YYYY-MM-00 00:00:00 misal 2017-03-00 00:00:00, hal ini tidak dapat dilakukan pada TIMESTAMP



Panduan Lengkap Query MySQL 85







TIMESTAMP membutuhkan ruang penyimpanan sebesar 4 byte sedangkan DATETIME 8 byte.



Berdasarkan persamaan dan perbedaan tersebut maka dapat kita identifikasi kapan kita menggunakan TIMESTAMP dan kapan menggunakan DATETIME. Beberapa kondisi dimana kita perlu untuk mempertimbangkan menggunakan TIMESTAMP: 



Misal kita ingin menampilkan data waktu kunjungan website dari berbagai negara, hal ini dapat dilakukan dengan mengubah masing masing time zone untuk masing masing negara. Misal visitor A dari USA mengunjungi website kita pukul 02:00, untuk mengetahui kapan kunjungan visitor A berdasarkan waktu USA, kita dapat sesuaikan zona waktunya.







Contoh lainnya adalah Website multi user dengan user dari berbagai negara, sehingga event yang terjadi seperti INSERT, UPDATE atau DELETE data dapat diketahui sesuai zona waktu masing masing.



Beberapa kondisi dimana kita dapat mempertimbangkan menggunakan tipe data DATETIME 



Karena TIMESTAMP memiliki batasan waktu, maka akan menyulitkan ketika digunakan untuk menyimpan data tanggal lahir, dimana bisa jadi tahun lahir dibawah 1970.







Selain itu, untuk data waktu yang nilainya bervariasi, maka kita bisa menggunakan DATETIME misal waktu yang hanya terdiri dari tahun dan bulan, seperti 2017-03-00 00:00:00







Mempertimbangkan kelebihan yang ada, maka jika kita hanya menggunakan satu zona waktu, misal Indonesia maka lebih disarankan untuk menggunakan DATETIME daripada TIMESTAMP



86 BAB 6 Tipe Data



BAB 7 Constrain Constrain merupakan aturan yang diterapkan pada kolom suatu tabel sehingga nilai pada tabel tersebut memenuhi kriteria/aturan yang telah ditetapkan. Dengan constrain ini, kita dapat membatasi data apa saja yang bisa dimasukkan ke dalam tabel, dengan demikian akurasi dan integritas data tetap dapat terjaga. Misal: kolom jenis kelamin harus diisi dengan nilai L atau P, jika diisi dengan selain itu, maka data akan ditolak. Bentuk constrain ini sangat banyak tidak terbatas pada bentuk tertentu, jika memenuhi kriteria diatas, maka bisa disebut constrain meskipun bentuknya stored program seperti trigger. Untuk membatasi pembahasan, pada bab ini, kita hanya akan membahas beberapa constrain eksplisit yang didukung oleh MySQL, yaitu NOT NULL, PRIMARY KEY, UNIQUE, FOREIGN KEY, ENUM, SET, dan CHECK. Umumnya, constrain didefinisikan bersamaan dengan pembuatan tabel, constrain terebut dapat didefinisikan pada level kolom maupun pada level tabel. Pada level kolom, constrain hanya berlaku pada kolom tersebut, jika pada level tabel, constrain tersebut dapat diterapkan pada beberapa kolom.



7.1. Constraint DEFAULT Constrain default akan memberikan nilai default pada kolom ketika kita memasukkan data pada tabel namun tidak mendefinisikan nilai pada kolom tersebut. Misal kita buat tabel penjualan dengan perintah: 1. CREATE TABLE `penjualan ` ( 2. `id_trx` INT(11) NOT NULL, 3. `id_pelanggan` INT(11) NOT NULL, 4. `tgl_trx` DATETIME NULL DEFAULT NOW(), 5. `total_trx` INT(11) NULL 6. )



Panduan Lengkap Query MySQL 87



Pada contoh diatas, kolom tgl_trx memiliki nilai default NOW() yang artinya tanggal dan waktu sekarang, misal: ‘2017-03-05 10:02:39’, sedangkan lainnya tidak memiliki nilai default. Mari kita coba memasukkan data: mysql> INSERT INTO penjualan (id_trx, id_pelanggan) VAlUES (1, 1); Query OK, 1 row affected (0.17 sec) mysql> SELECT * FROM penjualan; +--------+--------------+---------------------+-----------+ | id_trx | id_pelanggan | tgl_trx | total_trx | +--------+--------------+---------------------+-----------+ | 1 | 1 | 2017-03-05 10:02:40 | NULL | +--------+--------------+---------------------+-----------+ 1 row in set (0.05 sec)



Pada contoh diatas, terlihat bahwa kita tidak mendefinisikan nilai pada kolom tgl_trx, hasilnya, kolom tersebut akan berisi tanggal dan waktu ketika data dimasukkan. Perhatikan bahwa nilai pada kolom total_trx bernilai NULL, hal ini dikarenakan jika kita tidak mendefinisikan nilai default pada kolom yang dapat menerima NULL, maka MySQL akan menambahkan klausa DEFAULT NULL pada kolom tersebut. Namun demikian klausa DEFAULT tidak ditambahkan pada kolom dengan kriteria NOT NULL. Mari kita lihat definisi dari tabel pelanggan 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.



mysql> SHOW CREATE TABLE penjualan \G; *************************** 1. row *************************** Table: penjualan Create Table: CREATE TABLE `penjualan` ( `id_trx` int(11) NOT NULL, `id_pelanggan` int(11) NOT NULL, `tgl_trx` datetime DEFAULT CURRENT_TIMESTAMP, `total_trx` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 1 row in set (0.00 sec)



Pada baris ke 8 terlihat bahwa MySQL menambahkan klausa DEFAULT NULL. Selanjutnya, mari kita coba memasukkan data sebagai berikut: 88 BAB 7 Constrain



mysql> INSERT INTO penjualan (id_trx) VAlUES (3); ERROR 1364 (HY000): Field 'id_pelanggan' doesn't have a default value



Pada contoh diatas, kita tidak mendefinisikan nilai pada kolom id_pelanggan, hasilnya, kita mendapati error yang menyebutkan bahwa kolom id_pelanggan tidak memiliki nilai default.



7.2. NOT NULL Constrain NOT NULL mensyaratkan bahwa suatu kolom tidak boleh bernilai NULL, perlu diperhatikan bahwa NULL adalah tipe data khusus yang berarti nilai tidak diketahui, NULL tidak sama dengan angka 0 atau string kosong ''



Melanjutkan contoh pada tabel penjualan yang kita gunakan sebelumnya, mari kita masukkan data sebagai berikut: mysql> INSERT INTO penjualan (id_trx, id_pelanggan) VAlUES (3, NULL); ERROR 1048 (23000): Column 'id_pelanggan' cannot be null



Pada contoh diatas, terlihat bahwa jika kita memberi nilai NULL maka akan muncul pesan error Column ERROR 1048 (23000): 'id_pelanggan' cannot be null namun error ini tidak terjadi dika kita memberi string kosong '' pada kolom id_pelanggan



7.3. PRIMARY KEY Primary key atau kunci utama berarti satu atau lebih kolom berfungsi sebagai kunci (key) sehingga dapat membedakan antara baris satu dengan baris yang lain. Karena sebagai pembeda, maka nilai pada kolom (kombinasi antar kolom) yang berfungsi sebagai primary key harus unik, tidak boleh ada yang sama. Disamping itu, kolom tersebut juga tidak boleh bernilai NULL. Panduan Lengkap Query MySQL 89



Untuk mendefinisikan primary key, dapat dilakukan pada level kolom maupun level tabel. Misal untuk level kolom: 1. DROP TABLE IF EXISTS penjualan; 2. CREATE TABLE `penjualan` ( 3. `id_trx` INT(11) NOT NULL PRIMARY KEY, 4. `id_pelanggan` INT(11) NOT NULL, 5. `tgl_trx` DATETIME NOT NULL DEFAULT NOW(), 6. `total_trx` INT(11) NOT NULL DEFAULT 0 7. )



Pada contoh diatas, pada kolom id_trx kita definisikan atribut PRIMARY KEY setelah atribut NOT NULL, atribut NOT NULL juga dapat ditulis setelah atribut PRIMARY KEY. Perlu diperhatikan bahwa karena dalam satu tabel hanya boleh memiliki satu primary key, maka untuk pendefinisian primary key pada level kolom, hanya bisa didefinisikan pada satu kolom, pendefinisian pada kolom yang lain akan dianggap membuat primary key baru. Contoh untuk pendefinisian PRIMARY KEY pada level tabel: 1. DROP TABLE IF EXISTS penjualan; 2. CREATE TABLE `penjualan` ( 3. `id_trx` INT(11) NOT NULL, 4. `id_pelanggan` INT(11) NOT NULL, 5. `tgl_trx` DATETIME NOT NULL DEFAULT NOW(), 6. `total_trx` INT(11) NOT NULL DEFAULT 0, 7. PRIMARY KEY (id_trx) 8. )



Jika kolom didefinisikan sebagai primary key, maka kolom tersebut otomatis memiliki atribut NOT NULL, sehingga, pada kolom id_trx, kita dapat menghilangkan pendefinisian atribut NOT NULL, namun demikian, agar mudah dipahami disarankan untuk tetap menuliskan atribut NOT NULL tersebut. Beberapa hal yang perlu diketahui terkait primary key:



90 BAB 7 Constrain







Ketika mendefinisikan primary key, MySQL akan langsung membuat index yang terdiri dari kolom yang dijadikan sebagai primary key.







Tabel hanya boleh memiliki satu primary key, hal ini merupakan standar baku model database relasional yang juga diterapkan oleh MySQL. Satu primary key tersebut dapat terdiri dari lebih dari satu kolom, untuk membuatnya kita harus mendefinisikan primary key pada level tabel bukan kolom. Misal pada contoh sebelumnya kita buat PRIMARY KEY yang terdiri dari kolom id_trx dan id_pelanggan CREATE TABLE `penjualan` ( ... PRIMARY KEY (id_trx, id_pelanggan) )







Pada model database relasional setiap tabel harus memiliki PRIMARY KEY. Pada MySQL hal tersebut bukanlah suatu kewajiban, namun demikian sangat disarankan setiap tabel memiliki primary key, karena tanpa primary key, akan ada kemungkinan terdapat baris isinya sama persis, sehingga, jika baris tersebut dikenai operasi UPDATE atau DELETE maka semua baris yang nilainya sama akan terpengaruh.







Seperti telah disampaikan sebelumnya, nilai pada PRIMARY KEY harus unik, tidak boleh ada nilai yang sama, selain itu juga tidak boleh berisi nilai NULL. Misal, tabel pelanggan diatas memiliki primary key yang terdiri dari kolom id_trx dan id_pelanggan, data yang dapat kita masukkan adalah: +--------+--------------+---------------------+-----------+ | id_trx | id_pelanggan | tgl_trx | total_trx | +--------+--------------+---------------------+-----------+ | 1 | 1 | 2016-12-24 05:37:38 | 1000 | | 1 | 2 | 2016-12-24 05:37:55 | 500 | | 3 | 2 | 2016-12-24 05:46:49 | 750 | +--------+--------------+---------------------+-----------+



Pada data diatas, kombinasi nilai pada kolom id_trx dan id_pelanggan tidak ada yang sama. Panduan Lengkap Query MySQL 91



Kolom yang digunakan sebagai primary key akan otomatis dijadikan sebagai index bernama PRIMARY. Nama ini otomatis diberikan oleh MySQL dan tidak dapat diubah. mysql> SHOW INDEX FROM penjualan\G; *************************** 1. row *************************** Table: penjualan Non_unique: 0 Key_name: PRIMARY Seq_in_index: 1 Column_name: id_trx Collation: A Cardinality: 0 Sub_part: NULL Packed: NULL Null: Index_type: BTREE Comment: Index_comment: 1 row in set (0.00 sec)



Pada contoh diatas terlihat bahwa primary key yang kita buat otomatis diberi nama PRIMARY



7.4. UNIQUE Key Pada database relasional, constrain unique key mirip dengan primary key, dimana nilai pada kolom atau kombinasi antar kolom harus unik. Dalam teori database relasional, unique key dapat diartikan key kandidat yang tidak dijadikan sebagai primary key. Meskipun mirip, unique key constrain memiliki perbedaan mendasar dibanding dengan primary key. Adapun perbedaannya adalah: 



Baik primary key maupun unique key, keduanya akan dijadikan index, namun nama index untuk UNIQUE KEY dapat kita tentukan sendiri, sedangkan pada PRIMARY KEY, namanya selalu PRIMARY.



92 BAB 7 Constrain







Jika pada primary key satu tabel hanya bisa memiliki satu primary key, maka untuk unique key, satu tabel bisa memiliki lebih dari satu unique key.







Kolom yang memiliki atribut unique key dapat bernilai NULL, sehingga perlu diperhatikan pemberian atribut NULL pada kolom yang akan dijadikan sebagai unique key.



Sama seperti primary key, kita dapat mendefinisikan unique key pada level kolom dan tabel. Pada level kolom, kita dapat mendefinisikan unique key pada beberapa kolom, yang artinya kita akan membuat lebih dari satu unique key. Misal pada tabel penjualan kita buat unique key pada kolom id_trx dan id_pelanggan 1. DROP TABLE IF EXISTS penjualan; 2. CREATE TABLE `penjualan` ( 3. `id_trx` INT(11) NOT NULL UNIQUE, 4. `id_pelanggan` INT(11) NOT NULL UNIQUE, 5. `tgl_trx` DATETIME NOT NULL DEFAULT NOW(), 6. `total_trx` INT(11) NOT NULL DEFAULT 0 7. )



Pada contoh diatas, MySQL akan otomatis membuat dua buah index dengan nama sesuai dengan nama kolom, yaitu index bernama id_trx yang terdiri dari kolom id_trx, dan id_pelanggan yang terdiri dari kolom id_pelanggan Pada level tabel, kita dapat mendefinisikan sendiri nama index, selain itu, kita juga dapat membuat index yang terdiri dari gabungan dari beberapa kolom. Misal: 1. DROP TABLE IF EXISTS penjualan; 2. CREATE TABLE `penjualan` ( 3. `id_trx` INT(11) NULL, 4. `id_pelanggan` INT(11) NOT NULL, 5. `tgl_trx` DATETIME NOT NULL DEFAULT NOW(), 6. `total_trx` INT(11) NOT NULL DEFAULT 0, 7. CONSTRAINT unique_id_trx_id_pelanggan UNIQUE(id_trx, id_pelanggan) 8. )



Panduan Lengkap Query MySQL 93



Pada contoh diatas, index kita beri nama unique_id_trx_id_pelanggan, index tersebut terdiri dari dua kolom, yaitu kolom id_trx dan kolom id_pelanggan Jika kita tidak mendefinisikan nama index, maka MySQL akan memberi nama index tersebut sesuai dengan nama kolomnya. Misal CREATE TABLE `penjualan` ( ... `total_trx` INT(11) NOT NULL DEFAULT 0, UNIQUE(id_trx, id_pelanggan), UNIQUE(id_trx) )



Pada contoh diatas, MySQL akan membuat dua index, yaitu index dengan nama id_trx yang terdiri dari kolom id_trx dan id_pelanggan dan id_trx_2 yang terdiri dari hanya satu kolom, yaitu id_trx.



7.5. FOREIGN Key Foreign key atau kunci asing artinya suatu tabel memiliki key yang nilainya merujuk pada key yang ada di tabel lain. Foreign key digunakan untuk memvalidasi data pada suatu tabel terhadap data pada tabel lain (key antar tabel). Hubungan ini sering disebut referential integrity constraint Pembuatan foreign key dapat dilakukan pada saat pembuatan tabel. Misal kita akan membuat tabel pelanggan dan penjualan, dimana nilai pada kolom id_pelanggan yang ada pada tabel penjualan harus ada pada kolom id_pelanggan yang ada pada tabel pelanggan Tabel pelanggan: 1. CREATE TABLE `pelanggan` ( 2. `id_pelanggan` INT(11) NOT NULL AUTO_INCREMENT, 3. `nama` VARCHAR(50) NOT NULL, 4. `email` VARCHAR(50) NOT NULL, 5. PRIMARY KEY (`id_pelanggan`)



94 BAB 7 Constrain



6. )



Tabel penjualan: 1. CREATE TABLE `penjualan` ( 2. `id_trx` INT(11) NOT NULL, 3. `id_pelanggan` INT(11) NOT NULL, 4. `tgl_trx` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, 5. `total_trx` INT(11) NOT NULL DEFAULT '0', 6. PRIMARY KEY (`id_trx`), 7. FOREIGN KEY (`id_pelanggan`) 8. REFERENCES pelanggan (`id_pelanggan`) 9. )



Pada query yang digunakan untuk membuat tabel penjualan, kita gunakan klausa FOREIGN KEY. Klausa ini terdiri dari tiga bagian yaitu: 



Bagian pertama adalah kolom yang akan dijadikan sebagai foreign key. Pada contoh diatas adalah kolom id_pelanggan yang ada pada tabel penjualan. (FOREIGN KEY (`id_pelanggan`) )







Yang kedua adalah kolom pada tabel lain yang akan digunakan sebagai referensi, dalam contoh ini adalah kolom id_pelanggan yang ada pada tabel pelanggan (REFERENCES pelanggan (`id_pelanggan`) )







Yang ketiga adalah referensi aksi, yang artinya jika terjadi perubahan data pada kolom referensi (kolom id_pelanggan pada tabel pelanggan) yaitu berupa statemen UPDATE atau DELETE, maka kita tentukan aksi apa yang akan diterapkan pada kolom foreign key. Bagian ketiga ini tidak ada pada contoh. Kita akan membahasnya pada bagian 7.6 Referensi Aksi.



Ilustrasi kolom foreign key dan kolom referensi



Panduan Lengkap Query MySQL 95



Gambar 7.1 Ilustrasi Foreign Key Beberapa hal yang perlu diperhatikan ketika membuat foreign key, yaitu: 



Kedua kolom, baik kolom foreign key (kolom id_pelanggan pada tabel pelanggan) maupun kolom referensi (kolom id_pelanggan pada tabel penjualan), harus dijadikan index (harus PRIMARY KEY atau UNIQUE KEY). Pada contoh diatas, kolom id_pelanggan pada tabel pelanggan kita jadikan PRIMARY KEY yang otomatis akan dijadikan index, sedangkan kolom id_pelanggan pada tabel penjualan, otomatis juga akan dijadikan index ketika kita membuat foreign key, index tersebut memiliki nama sama dengan nama foreign key constraint.







Kedua kolom baik kolom foreign key maupun kolom referensi harus memiliki tipe data yang sama persis, termasuk penggunaan atribut UNSIGNED pada tipe data INT. INT(11) tidak sama dengan INT(11) UNSIGNED.







Storage Engine yang digunakan oleh kedua tabel harus InnoDB, engine yang lain, seperti MyISAM tidak mendukung foreign key constrain. Untuk mengecek storage engine yang ada beserta fitur yang dimiliki, jalankan perintah SHOW ENGINES mysql> SHOW ENGINES; +--------------------+---------+-----------------------+--------------+ | Engine | Support | Comment | Transactions | +--------------------+---------+-----------------------+--------------+



96 BAB 7 Constrain



| InnoDB | DEFAULT | Supports transactions | YES | | MRG_MYISAM | YES | Collection of ... | NO | | MEMORY | YES | Hash based, stored... | NO | | BLACKHOLE | YES | /dev/null storage... | NO | | MyISAM | YES | MyISAM storage ... | NO | | CSV | YES | CSV storage engine... | NO | | ARCHIVE | YES | Archive storage ... | NO | | PERFORMANCE_SCHEMA | YES | Performance Schema ...| NO | | FEDERATED | NO | Federated MySQL ... | NULL | +--------------------+---------+-----------------------+--------------+



Pada tabel diatas, agar tabel yang ditampilkan lebih simpel dan to the point, beberapa kolom dihilangkan. Pada tabel diatas, terlihat bahwa storage engine default adalah InnoDB, kita dapat mengubah default storage engine dengan mengubah variabel global storage engine: SET @@STORAGE_ENGINE = 'InnoDB';



Setelah foreign key berhasil dibuat, maka MySQL akan menjamin bahwa nilai (selain NULL) yang dimasukkan ke dalam kolom foreign key akan ada pada kolom referensi pada tabel referensi. Pada contoh diatas, nilai pada kolom id_pelanggan yang ada pada tabel penjualan akan selalu ada pada kolom id_pelanggan yang ada pada tabel pelanggan, sehingga, jika hal tersebut tidak terpenuhi baik ketika user memasukkan atau mengubah data (statemen INSERT atau UPDATE) maka akan muncul pesan error dan proses manipulasi data tidak dilanjutkan. Sebagai contoh misal tabel pelanggan berisi data sebagai berikut: +--------------+----------+---------------------+ | id_pelanggan | nama | email | +--------------+----------+---------------------+ | 1 | Anton | [email protected] | | 2 | Braskie | [email protected] | | 3 | Charlie | [email protected] | | 4 | Deni | [email protected] | +--------------+----------+---------------------+



Selanjutnya, kita tambahkan data pada tabel penjualan dengan id_pelanggan 5 sebagai berikut: Panduan Lengkap Query MySQL 97



mysql> INSERT INTO penjualan (id_pelanggan, tgl_trx, total_trx) VALUES (5, "2017-03-01", 150000); ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`toko_buku`.`penjualan`, CONSTRAINT `FK_penjualan_pelanggan` FOREIGN KEY (`id_pelanggan`) REFERENCES `pelanggan` (`id_pelanggan`) ON DELETE CASCADE ON UPDATE CASCADE)



Pada contoh diatas muncul pesan error karena pelanggan dengan id_pelanggan 5 tidak ada pada tabel pelanggan.



7.6. FOREIGN Key: Referensi Aksi Pada bagian sebelumnya telah kita singgung sedikit mengenai referensi aksi pada foreign key. Referensi aksi hanya dijalankan jika ada data pada kolom referensi yang di perbarui atau dihapus. Referensi aksi ini dapat didefinisikan dengan dua klausa:  



ON UPDATE nama_aksi yang akan dieksekusi jika data pada kolom referensi diupdate, dan ON DELETE nama_aksi yang akan dieksekusi jika ada data pada kolom referensi yang dihapus.



Untuk nama_aksi, terdapat tiga opsi yang dapat digunakan yaitu: 1. RESTRICT yang berarti terbatas. Maksudnya adalah perubahan data pada kolom referensi tidak diperkenankan jika nilai pada kolom tersebut sedang digunakan. Misal, data pada tabel penjualan adalah sebagai berikut: +--------+--------------+---------------------+-----------+ | id_trx | id_pelanggan | tgl_trx | total_trx | +--------+--------------+---------------------+-----------+ | 1 | 1 | 2017-03-05 10:41:42 | 100000 | +--------+--------------+---------------------+-----------+



Maka jika kita ubah data id_pelanggan pada tabel pelanggan yang memiliki nilai 1, akan muncul pesan error:



98 BAB 7 Constrain



mysql> UPDATE pelanggan SET id_pelanggan = 5 WHERE id_pelanggan = 1; ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`toko_buku`.`penjualan`, CONSTRAINT `penjualan_ibfk_1` FOREIGN KEY (`id_pelanggan`) REFERENCES `pelanggan` (`id_pelanggan`))



2. CASCADE yang artinya mengikuti. Maksudnya jika data pada kolom referensi diubah, maka data pada kolom foreign key juga ikut berubah. Pada contoh diatas, jika nilai id_pelanggan pada tabel pelanggan kita ubah nilainya dari satu menjadi 5, maka semua data pada kolom id_pelanggan tabel penjualan yang memiliki nilai 1 akan berubah menjadi 5, hal yang sama juga terjadi pada proses penghapusan data. 3. SET NULL. Maksudnya, jika data pada kolom referensi diubah, maka data yang ada pada kolom foreign key akan berubah menjadi NULL. Misal jika kita ubah data id_pelanggan pada tabel pelanggan dari 1 menjadi 5, maka data pada tabel penjualan yang memiliki id 1 akan berubah menjadi NULL. Penting diperhatikan bahwa karena data pada kolom foreign key akan diubah menjadi NULL, maka kolom tersebut harus bisa menerima nilai NULL, misal pada pembuatan tabel, agar dapat menerima nilai NULL, kita tidak boleh mendefinisikan NOT NULL pada kolom tersebut. 4. SET DEFAULT. Meskipun dapat diterima oleh parser MySQL, namun InnoDB tidak menjalankan aksi ini, artinya tidak terjadi perubahan apa apa pada kolom foreign key . 5. NO ACTION. Aksi ini sama dengan RESTRICT. Jika aksi tidak didefinisikan, maka secara default, MySQL akan menggunakan aksi RESTRICT. Berikut ini contoh penulisan foreign key lengkap dengan referensi aksi pada pembuatan tabel 1. CREATE TABLE `penjualan` ( 2. `id_trx` INT(11) NOT NULL, 3. `id_pelanggan` INT(11) NOT NULL, 4. `tgl_trx` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,



Panduan Lengkap Query MySQL 99



5. 6. 7. 8. 9. 10. )



`total_trx` INT(11) NOT NULL DEFAULT '0', PRIMARY KEY (`id_trx`), FOREIGN KEY (`id_pelanggan`) REFERENCES pelanggan (`id_pelanggan`) ON UPDATE CASCADE ON DELETE RESTRICT



Pada contoh diatas, jika data id_pelanggan pada tabel pelanggan diubah maka data id_pelanggan yang sama yang ada pada tabel penjualan juga akan berubah, sedangkan jika data id_pelanggan pada tabel pelanggan dihapus, maka jika data tersebut ada pada tabel penjualan maka proses akan dihentikan (restrict).



7.7. Check Constraint Pada MySQL terdapat constraint bernama check. Constraint ini akan mengecek data sebelum dimasukkan ke dalam tabel sesuai dengan syarat yang telah ditentukan. Untuk membuat constraint check, ketika membuat tabel kita tambahkan klausa check, misal: 1. CREATE TABLE `pelanggan` ( 2. `id_pelanggan` INT(11) NOT NULL AUTO_INCREMENT, 3. `nama` VARCHAR(50) NOT NULL, 4. `alamat` VARCHAR(255) NOT NULL, 5. `jenis_kelamin` CHAR(1) NULL DEFAULT 'L', 6. CHECK (jenis_kelamin IN('L', 'P')) 7. )



Pada contoh diatas, sebelum data dimasukkan atau ada perubahan data pada kolom jenis kelamin, akan dilakukan pengecekan apakah data bernilai L atau P, jika tidak keduanya, maka akan muncul pesan error. Sayangnya, sampai dengan versi 5.7, MySQL belum mendukung constraint ini. Ketika dibuat, parser MySQL tetap dapat menerimanya (tidak error), namun ketika kita memasukkan data selain L atau P, tidak ada pesan error apapun yang muncul.



100 BAB 7 Constrain



Sebagai alternatif constrain check, kita dapat menggunakan trigger untuk memvalidasi data sebelum dimasukkan atau di update.



7.8. Memberi Nama Constraint Sejauh ini, nama dari constraint yang kita buat ditentukan secara otomatis oleh MySQL. Nama constraint ini penting terutama ketika MySQL memunculkan pesan error yang terjadi saat constraint dilanggar, karena pada pesan error tersebut, MySQL akan menyebutkan nama constraint. Dengan memberi nama constraint dengan nama yang jelas, maka error tersebut akan dapat segera diatasi. Misal pada tabel pelanggan terdapat constraint unique sebagai berikut: 1. CREATE TABLE `penjualan` ( 2. `id_trx` INT(11) NOT NULL UNIQUE, 3. ... 4. )



Ketika kita isikan nilai 1 lebih dari satu kali pada kolom id_trx, maka akan muncul pesan error: SQL Error (1062): Duplicate entry '1' for key 'id_trx'



Dari pesan tersebut dapat diketahui bahwa terdapat duplikasi nilai pada kolom id_trx, namun demikian, jika constraint terdiri dari kombinasi dua kolom maka akan pesan error akan lebih susah dipahami. Misal: 1. CREATE TABLE `penjualan` ( 2. `id_trx` INT(11) NOT NULL, 3. `id_pelanggan` INT(11) NULL DEFAULT '1', 4. ... 5. UNIQUE (`id_trx`, `id_pelanggan`) 6. )



Panduan Lengkap Query MySQL 101



Pada tabel tersebut contrain unique di tentukan oleh nilai kolom id_trx dan id_pelanggan, sehingga jika kita isikan data 1 pada kolom tersebut dua kali, maka akan muncul pesan error: SQL Error (1062): Duplicate entry '1-1' for key 'id_trx'



MySQL menyebutkan duplikasi data pada key id_trx, dari pesan tersebut terlihat bahwa nama constraint diambil dari nama kolom pertama, yaitu id_trx, agar lebih mudah diidentifikasi, kita perlu mengubah nama constraint tersebut. Untuk mendefinisikan nama constrain, sebelum kita menuliskan jenis constraint, tambahkan klausa CONSTRAINT diikuti nama constraint. Misal 1. DROP TABLE IF EXISTS penjualan; 2. CREATE TABLE `penjualan` ( 3. `id_trx` INT(11) NOT NULL, 4. `id_pelanggan` INT(11) NULL DEFAULT '1', 5. `tgl_trx` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, 6. `total_trx` INT(11) NOT NULL DEFAULT '0', 7. CONSTRAINT id_trx_id_pelanggan UNIQUE (`id_trx`, `id_pelanggan`) 8. )



Pada contoh diatas, kita beri nama constrain sesuai dengan nama kolom yang terlibat yaitu id_trx dan id_pelanggan. Ketika kita masukkan data yang sama dua kali ke kolom id_trx dan id_pelanggan, maka kita akan mendapati pesan error: SQL Error (1062): Duplicate entry '1-1' for key 'id_trx_id_pelanggan'



Dari pesan diatas dapat langsung kita ketahui bahwa terdapat duplikasi data pada kombinasi kedua kolom tersebut. Selain constraint UNIQUE, kita juga dapat memberi nama constraint pada FOREIGN KEY constraint. Caranya juga sama yaitu dengan menambahkan klausa CONSTRAINT sebelum klausa FOREIGN KEY, misal: 102 BAB 7 Constrain



1. CREATE TABLE `penjualan` ( 2. `id_trx` INT(11) NOT NULL, 3. `id_pelanggan` INT(11) NOT NULL, 4. `tgl_trx` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, 5. `total_trx` INT(11) NOT NULL DEFAULT '0', 6. PRIMARY KEY (`id_trx`), 7. CONSTRAINT FK_penjualan_pelanggan FOREIGN KEY (`id_pelanggan`) 8. REFERENCES pelanggan (`id_pelanggan`) 9. ON UPDATE CASCADE ON DELETE RESTRICT 10. )



Ketika terjadi error: mysql> INSERT INTO `penjualan` VALUES (3, 5, '2017-03-05 18:57:54', 255000); ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`toko_buku`.`penjualan`, CONSTRAINT `FK_penjualan_pelanggan` FOREIGN KEY (`id_pelanggan`) REFERENCES `pelanggan` (`id_pelanggan`) ON DELETE NO ACTION ON UPDATE NO ACTION)



Pada



contoh



diatas



error



terjadi



pada



CONSTRAINT



`FK_penjualan_pelanggan`.



Meskipun dapat menentukan nama constraint sendiri, khusus untuk constrain primary key, seperti telah dibahas sebelumnya, kita tidak dapat menentukan nama sendiri, nama constrain akan selalu diberi nama PRIMARY, sehingga jika kita tambahkan klausa CONSTRAINT maka, tidak akan berpengaruh apa-apa.



7.9. Menampilkan Detail Constraint Semua constraint yang telah dibuat disimpan pada database information_schema. Untuk constraint yang dibuat pada level tabel disimpan pada tabel table_constraints, untuk menampilkan semua constrain, jalankan perintah berikut:



Panduan Lengkap Query MySQL 103



1. 2. 3.



SELECT * FROM information_schema.table_constraints WHERE constraint_schema = 'nama_database';



Contoh isi dari tabel table_constraints adalah sebagai berikut (hanya ditampilkan beberapa kolom saja): mysql> SELECT constraint_name, table_schema, table_name, constraint_type -> FROM information_schema.table_constraints -> WHERE constraint_schema = 'toko_buku'; +-------------------------------+--------------+------------------+-----------------+ | constraint_name | table_schema | table_name | constraint_type | +-------------------------------+--------------+------------------+-----------------+ | PRIMARY | toko_buku | buku | PRIMARY KEY | | PRIMARY | toko_buku | pengarang | PRIMARY KEY | | PRIMARY | toko_buku | penjualan | PRIMARY KEY | | FK_penjualan_pelanggan | toko_buku | penjualan | FOREIGN KEY | | PRIMARY | toko_buku | penjualan_detail | PRIMARY KEY | | FK_penjualan_detail_buku | toko_buku | penjualan_detail | FOREIGN KEY | | FK_penjualan_detail_penjualan | toko_buku | penjualan_detail | FOREIGN KEY | | id_transaksi | toko_buku | retur | UNIQUE | | PRIMARY | toko_buku | user | PRIMARY KEY | | email | toko_buku | user | UNIQUE | +-------------------------------+--------------+------------------+-----------------+ 10 rows in set (0.05 sec)



Sedangkan untuk data nama kolom yang dijadikan constraint, terdapat pada tabel key_usage_column 1. 2. 3.



SELECT * FROM information_schema.key_usage_column WHERE constraint_schema = 'nama_database';



Berikut contoh isi dari tabel key_usage_column (karena terdapat banyak sekali kolom, kita tampilkan hanya beberapa saja yang penting) mysql> SELECT constraint_name, table_schema, table_name, column_name -> FROM information_schema.key_column_usage -> WHERE constraint_schema = 'toko_buku'; +-------------------------------+--------------+------------------+---------------+ | constraint_name | table_schema | table_name | column_name | +-------------------------------+--------------+------------------+---------------+ | PRIMARY | toko_buku | buku | id_buku | | PRIMARY | toko_buku | pengarang | id_pengarang | | PRIMARY | toko_buku | penjualan | id_trx | | FK_penjualan_pelanggan | toko_buku | penjualan | id_pelanggan | | PRIMARY | toko_buku | penjualan_detail | id_trx_detail |



104 BAB 7 Constrain



| FK_penjualan_detail_buku | toko_buku | penjualan_detail | id_buku | | FK_penjualan_detail_penjualan | toko_buku | penjualan_detail | id_trx | | id_transaksi | toko_buku | retur | id_trx | | PRIMARY | toko_buku | user | username | | email | toko_buku | user | email | +-------------------------------+--------------+------------------+---------------+ 10 rows in set (0.05 sec)



Pada contoh diatas terlihat bahwa pada tabel key_column_usage, terdapat kolom column_name yang berisi nama kolom dimana constraint diterapkan Khusus untuk constraint FOREIGN referential_constraints 1. 2. 3.



KEY, dapat dilihat pada tabel



SELECT * FROM information_schema.referential_constraints WHERE constraint_schema = 'nama_database';



Contoh isi tabel referential_constraints: mysql> SELECT constraint_name, update_rule, delete_rule, table_name, referenced_table_name -> FROM information_schema.referential_constraints -> WHERE constraint_schema = 'toko_buku'; +-------------------------------+-------------+-------------+ | constraint_name | update_rule | delete_rule | +-------------------------------+-------------+-------------+ | FK_penjualan_pelanggan | CASCADE | CASCADE | | FK_penjualan_detail_buku | CASCADE | CASCADE | | FK_penjualan_detail_penjualan | CASCADE | CASCADE | +-------------------------------+-------------+-------------+ Lanjutan: +------------------+-----------------------+ | table_name | referenced_table_name | +------------------+-----------------------+ | penjualan | pelanggan | | penjualan_detail | buku | | penjualan_detail | penjualan | +------------------+-----------------------+ 3 rows in set (0.00 sec)



Terdapat cara alternatif untuk mengetahui constraint yang ada pada tabel yaitu melihat statement yang digunakan untuk membuat tabel, caranya, gunakan statement SHOW CREATE TABLE, misal: Panduan Lengkap Query MySQL 105



mysql> SHOW CREATE TABLE penjualan_detail\G; *************************** 1. row *************************** Table: penjualan_detail Create Table: CREATE TABLE `penjualan_detail` ( `id_trx_detail` int(11) NOT NULL AUTO_INCREMENT, `id_trx` int(11) DEFAULT NULL, `id_barang` int(11) DEFAULT NULL, `jml_barang` smallint(6) DEFAULT NULL, `harga_satuan` int(11) DEFAULT NULL, `diskon` float DEFAULT NULL, `total` int(11) DEFAULT NULL, PRIMARY KEY (`id_trx_detail`), KEY `FK_penjualan_detail_barang` (`id_barang`), KEY `FK_penjualan_detail_penjualan` (`id_trx`), CONSTRAINT `FK_penjualan_detail_barang` FOREIGN KEY (`id_barang`) REFERENCES `barang` (`id_barang`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `FK_penjualan_detail_penjualan` FOREIGN KEY (`id_trx`) REFERENCES `penjualan` (`id_trx`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC 1 row in set (0.00 sec)



7.10. Mengubah Constraint Karena melekat pada tabel, maka untuk mengubah constraint, kita harus mengubahnya melalui tabel dimana constrain tersebut berada. Adapun statemen yang digunakan adalah ALTER. Untuk mengubah constraint, terlebih dahulu kita hapus constraint tersebut, kemudian kita tambah dengan yang baru. Misal untuk mengubah constraint PRIMARY KEY: ALTER TABLE penjualan DROP PRIMARY KEY, ADD PRIMARY KEY(id_trx);



Mengubah UNIQUE KEY: ALTER TABLE pelanggan DROP INDEX unique_email, ADD CONSTRAINT unique_email UNIQUE (email);



106 BAB 7 Constrain



Mengubah FOREIGN KEY: ALTER TABLE penjualan_detail DROP FOREIGN KEY FK_penjualan_detail_barang; ALTER TABLE penjualan_detail ADD CONSTRAINT FK_penjualan_detail_barang FOREIGN KEY (id_barang) REFERENCES barang (id_barang) ON DELETE CASCADE ON UPDATE CASCADE;



Terkadang, untuk constraint yang kompleks, seperti pada FOERIGN KEY, kita tidak dapat menggabungkan statemen DROP dan ADD, melainkan harus kita jalankan satu per satu, seperti pada contoh query diatas.



7.11. Menghapus Constraint Seperti telah disampaikan sebelumnya, bahwa constraint melekat pada tabel, sehingga jika kita hapus tabel tersebut dengan statemen DROP TABLE maka semua constraint di dalamnya juga akan ikut terhapus, termasuk constrain FOREIGN KEY, Sedangkan dengan statemen ALTER TABLE, seperti yang telah kita gunakan sebelumnya, constrain dapat dihapus tanpa menghapus tabel. Penting diperhatikan bahwa ketika kita menghapus tabel, maka MySQL akan menghapus baris terlebih dahulu, sehingga, jika pada baris tersebut terikat pada constraint FOREIGN KEY dengan aksi referensi ON DELETE CASCADE, maka aturan aksi akan tetap berlaku, dimana jika tabel tersebut merupakan tabel yang dijadikan referensi, maka semua baris pada tabel yang di jadikan referensi akan ikut terhapus.



Panduan Lengkap Query MySQL 107



Halaman ini sengaja dikosongkan Jagowebdev.com



108 BAB 7 Constrain



BAB 8 Syntax Dasar Pengambilan Data Pada BAB ini, kita akan mulai membahas tentang SQL dari syntax yang paling dasar yaitu statemen SELECT, pada bab-bab berikutnya kita bahas berbagai syntax lainnya yang lebih kompleks. Statemen SELECT digunakan terutama untuk mengambil data dari database, statemen ini merupakan bagian paling penting dari SQL, karena request/query yang paling sering kita lakukan adalah mengambil data untuk ditampilkan ke user, baik sifatnya kompleks seperti laporan atau sekedar data sederhana. Penggunaan perintah SELECT ini memiliki banyak variasi dan terkadang menjadi rumit, karena pada kondisi tertentu akan melibatkan berbagai klausa tambahan untuk mengambil baris tertentu dari tabel. Penggunaan klausa ini akan menjadi kompleks manakala query melibatkan beberapa tabel dengan berbagai kriteria pengambilan data. Dengan memahami berbagai syntax/perintah dasar pengambilan data, maka akan memudahkan Anda untuk melakukan berbagai query pengambilan data termasuk data yang kompleks sekalipun.



8.1. Satemen SELECT Seperti disampaikan sebelumnya, statemen SELECT memiliki banyak variasi, yang paling sederhana adalah sebagai berikut: SELECT list_kolom FROM tabel



Pada SQL dan bahasa pemrograman secara umum, kata tertentu disebut keyword. Keyword ini memiliki arti khusus dan pada kondisi tertentu harus ada. Pada contoh diatas, kata SELECT dan FROM adalah keyword. Keyword SELECT menandakan bahwa statemen SELECT dimulai. Keyword ini diikuti nama kolom dari tabel yang ingin diambil datanya, sedangkan keyword FROM digunakan untuk menentukan tabel yang akan diambil datanya. Pada



Panduan Lengkap Query MySQL 109



buku ini, keyword juga sering di tulis klausa, intinya sama saja, bedanya klausa memiliki arti lebih umum Contoh diatas digunakan untuk mengambil data hanya dari satu kolom, untuk mengambil lebih dari satu kolom, kita gunakan tanda koma sebagai pemisah kolom, sedangkan untuk mengambil semua kolom, kita gunakan tanda bintang/asterik (*). SELECT * FROM table



Sebagai contoh, misal kita memiliki tabel buku1 sebagai berikut: +---------+----------------------+--------------+-------------+------------+-------+------+ | id_buku | judul | id_pengarang | id_penerbit | tgl_terbit | harga | stok | +---------+----------------------+--------------+-------------+------------+-------+------+ | 1 | Pemrograman Databa...| 1 | 1 | 2016-00-00 | 59000 | 5 | | 2 | PHP dan MySQL Lang...| 1 | 1 | 2016-00-00 | 75000 | 6 | | 3 | MySQL Untuk Pemula...| 3 | 4 | 2014-11-28 | 34800 | 2 | | 4 | Kumpulan Aplikasi ...| 3 | 4 | 2016-02-25 | 34800 | 3 | | 5 | Mahir Dalam 7 Hari...| 4 | 1 | 2013-00-00 | 68000 | 4 | +---------+----------------------+--------------+-------------+------------+-------+------+



Selanjutnya, kita gunakan tanda asterik untuk mengambil semua kolom dari tabel sebagai berikut: mysql> SELECT * FROM buku1; +---------+----------------------+--------------+-------------+------------+-------+------+ | id_buku | judul | id_pengarang | id_penerbit | tgl_terbit | harga | stok | +---------+----------------------+--------------+-------------+------------+-------+------+ | 1 | Pemrograman Databa...| 1 | 1 | 2016-00-00 | 59000 | 5 | | 2 | PHP dan MySQL Lang...| 1 | 1 | 2016-00-00 | 75000 | 6 | | 3 | MySQL Untuk Pemula...| 3 | 4 | 2014-11-28 | 34800 | 2 | | 4 | Kumpulan Aplikasi ...| 3 | 4 | 2016-02-25 | 34800 | 3 | | 5 | Mahir Dalam 7 Hari...| 4 | 1 | 2013-00-00 | 68000 | 4 | +---------+----------------------+--------------+-------------+------------+-------+------+ 5 rows in set (0.00 sec)



Pada contoh diatas, syntax akan menghasilkan tabel sama persis seperti yang ada pada database. Sebagai catatan, pada tabel yang memiliki banyak kolom, menyeleksi semua field hanya untuk digunakan beberapa saja tidak efektif, sehingga sebisa mungkin mendefinisikan nama field, hal ini merupakan salah satu bentuk optimasi query. Contoh statemen SELECT untuk menampilkan kolom tertentu: mysql> SELECT id_buku, judul FROM buku1;



110 BAB 8 Syntax Dasar Pengambilan Data



+---------+-----------------------------------------+ | id_buku | judul | +---------+-----------------------------------------+ | 1 | Pemrograman Database Menggunakan MySQL | | 2 | PHP dan MySQL Langkah Demi Langkah + CD | | 3 | MySQL Untuk Pemula | | 4 | Kumpulan Aplikasi PHP untuk Pemula | | 5 | Mahir Dalam 7 Hari: Coreldraw X6 | +---------+-----------------------------------------+ 5 rows in set (0.00 sec)



Pada contoh diatas kita tampilkan 2 kolom yaitu kolom id_buku dan pengarang. Urutan kolom yang ditampilkan sesuai dengan urutan kolom yang ditulis pada perintah SQL. Catatan: Pada BAB tentang constrain, telah disampaikan bahwa dianjurkan pada setiap tabel memiliki kolom primary key, kolom ini umumnya berada di paling kiri, yang pada contoh diatas kolom id_buku. Pada buku ini, Anda akan sering menemui pola seperti ini, karena hampir semua tabel yang dibahas pada buku ini memiliki kolom primary key yang beratribut auto_increment. Untuk membatasi data yang ditampilkan, statemen SELECT dapat di gabung dengan keyword lain, penulisan lengkapnya adalah sebagai berikut: SELECT nama_kolom FROM nama_tabel [WHERE kondisi] [GROUP BY nama_kolom] [ORDER BY nama_kolom] [HAVING kriteria] [LIMIT jumlah]



Keyword selain SELECT dan FROM bersifat opsional, jika disertakan, maka harus sesuai dengan urutan diatas.



Panduan Lengkap Query MySQL 111



8.2. Aturan Penulisan Syntax Tidak ada standar baku dalam penulisan syntax SQL, tidak juga harus seperti contoh statemen SELECT yang telah kita bahas sebelumnya, namun, untuk meminimalisir syntax eror dan agar syntax mudah dipahami dan diperbaiki, terdapat beberapa hal yang perlu diperhatikan, yaitu: 



Nama kolom, tabel, dan database bersifat case sensitive, yang artinya tidak membedakan huruf besar, misal SELECT judul FROM buku1 dapat ditulis select JUDUL from BUKU1







Setiap statemen dapat diakhiri dengan delimiter berupa tanda titik koma ( ; ), namun untuk query yang hanya terdiri dari satu statemen, maka tidak harus menggunakan delimiter.







Gunakan huruf kapital untuk keyword dan huruf kecil untuk yang bukan keyword, hal ini untuk mempermudah membedakan mana keyword dan mana yang bukan keyword.







Gunakan line break (enter), spasi dan indent secukupnya sehingga dapat dibedakan dengan jelas setiap bagian syntax SQL, khusus untuk keyword utama, pisahkan dengan baris baru







Gunakan pola penulisan secara konsisten sehingga dengan sekilas membaca kode, kita dapat langsung memahami "Alur" ceritanya.







Optional: gunakan backtick ( ` ) pada nama tabel, jika nama tabel tersebut sama dengan keyword yang telah digunakan oleh MySQL.



Contoh penulisan syntax sesuai dengan pola penulisan yang disarankan: 1. SELECT nama_item, `order`, 2. SUM(jml_byr) AS nilai_transaksi, 3. COUNT(jml_byr) AS jumlah_transaksi 4. FROM transaksi 5. WHERE nama_pelanggan LIKE "mitra%"



Pada contoh diatas, SELECT, FROM, dan WHERE merupakan keyword utama, sehingga kita tulis pada baris baru. Contoh penulisan query lebih dari satu statemen 112 BAB 8 Syntax Dasar Pengambilan Data



1. INSERT INTO buku (judul) VALUES ('MySQL'); 2. SELECT judul 3. FROM buku



Pada contoh diatas, statemen pertama adalah INSERT INTO buku (judul) VALUES ('MySQL') sedangkan statemen kedua adalah SELECT judul FROM buku, keduanya dipisah dengan titik koma



8.3. Statemen SELECT DISTINCT Statemen SELECT DISTINCT digunakan untuk mengambil data yang unik pada suatu kolom, artinya, jika terdapat data yang sama, yang diambil hanya satu data, contoh: 1. SELECT DISTINCT(id_penerbit) 2. FROM buku1



Hasil: +-------------+ | id_penerbit | +-------------+ | 1 | | 4 | +-------------+



Perlu diperhatikan bahwa DISTINCT ini hanya dapat digunakan pada satu kolom, misal jika kita jalankan query berikut: 1. SELECT DISTINCT(id_penerbit), DISTINCT(id_pengarang) 2. FROM buku1



Maka kita akan mendapatkan pesan error: SQL Error (1064): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DISTINCT(id_pengarang) FROM buku1' at line 1



Panduan Lengkap Query MySQL 113



8.4. WHERE Pada contoh sebelumnya kita telah belajar bagaimana mengambil data dari database. Dalam praktek, kita sering mengambil data berdasarkan kriteria tertentu, misal berdasarkan penerbit, pengarang, tahun terbit, dll. Untuk keperluan tersebut, kita gunakan klausa WHERE Contoh penggunaan klausa WHERE: 1. SELECT judul 2. FROM buku1 3. WHERE id_penerbit = 4



Hasil yang kita peroleh: +------------------------------------+ | judul | +------------------------------------+ | Desain Grafis dengan Powerpoint | | MySQL Untuk Pemula | | Kumpulan Aplikasi PHP untuk Pemula | +------------------------------------+



Pada contoh diatas, kita hanya menampilkan judul buku yang memiliki id_penerbit 4.



8.5. GROUP BY Klausa GROUP BY digunakan untuk mengelompokkan data berdasarkan kolom tertentu, misal mengelompokkan data buku berdasarkan id_penerbit. Klausa ini harus digunakan bersama fungsi agregasi seperti COUNT() dan SUM(), karena untuk kolom yang tidak di kelompokkan, akan diambil hanya satu data, perhatikan query berikut: 1. SELECT id_penerbit, judul 2. FROM buku1 3. GROUP BY id_penerbit



114 BAB 8 Syntax Dasar Pengambilan Data



Hasil yang kita peroleh: +-------------+----------------------------------------+ | id_penerbit | judul | +-------------+----------------------------------------+ | 1 | Pemrograman Database Menggunakan MySQL | | 4 | MySQL Untuk Pemula | +-------------+----------------------------------------+



Dari hasil diatas terlihat bahwa data dikelompokkan berdasarkan id_penerbit yaitu 1 dan 4, namun pada kolom judul, data yang diambil hanya satu, yaitu hanya baris pertama dari masing masing id_penerbit. Dengan fungsi agregasi, kita dapat memperoleh berbagai informasi terkait data yang dikelompokkan, misal menghitung jumlah buku yang diterbitkan oleh masing masing penerbit, contoh: 1. SELECT id_penerbit, COUNT(judul) 2. FROM buku1 3. GROUP BY id_penerbit



Hasil: +-------------+--------------+ | id_penerbit | COUNT(judul) | +-------------+--------------+ | 1 | 3 | | 4 | 2 | +-------------+--------------+



Dari hasil diatas diketahui bahwa terdapat 3 buku yang diterbitkan oleh penerbit dengan id_penerbit 1, dan 2 buku oleh penerbit dengan id_penerbit 4. MySQL menyediakan berbagai fungsi agregasi. Fungsi ini dibahas lebih lanjut pada BAB 12 Function. Pada bab bab selanjutnya Anda akan menemukan berbagai variasi penggunaan klausa GROUP BY.



Panduan Lengkap Query MySQL 115



8.6. ORDER BY Sejauh ini, kita telah berhasil menampilkan data dari database menggunakan kriteria tertentu. Jika kita perhatikan, urutan data yang ditampilkan sama persis dengan dengan urutan yang ada di dalam tabel database. Untuk keperluan tertentu, misal menampilkan data berdasarkan publikasi terbaru, maka kita perlu untuk mengubah urutan data tersebu, untuk mengurutkan data berdasarkan kolom tertentu, gunakan klausa ORDER BY. Contoh penggunaan ORDER BY: 1. 2. 3. 4.



SELECT id_buku, judul, tgl_terbit FROM buku1 WHERE id_penerbit = 1 ORDER BY tgl_terbit DESC



Hasil yang kita peroleh: +---------+-----------------------------------------+------------+ | id_buku | judul | tgl_terbit | +---------+-----------------------------------------+------------+ | 1 | Pemrograman Database Menggunakan MySQL | 2016-00-00 | | 2 | PHP dan MySQL Langkah Demi Langkah + CD | 2016-00-00 | | 5 | Mahir Dalam 7 Hari: Coreldraw X6 | 2013-00-00 | +---------+-----------------------------------------+------------+



Pada contoh diatas, kita menggunakan opsi DESC (descending) untuk mengurutkan data dari yang terbesar ke terkecil, jika kita tidak memberikan opsi apa-apa, secara default, MySQL akan mengurutkannya secara ascending (atau dengan opsi ASC). Selain dapat mengurutkan data dengan kriteria satu kolom, kita juga dapat mengurutkan data dengan kriteria lebih dari satu kolom. Pada model pengurutan ini, data akan diurutkan mulai dari kolom paling kiri yang ada pada klausa ORDER BY, misal kita urutkan data berdasarkan tanggal terbit dan judul, jalankan query berikut: 1. 2. 3. 4.



SELECT id_buku, judul, tgl_terbit FROM buku1 WHERE id_penerbit = 1 ORDER BY tgl_terbit DESC, judul DESC



116 BAB 8 Syntax Dasar Pengambilan Data



Hasil: +---------+-----------------------------------------+------------+ | id_buku | judul | tgl_terbit | +---------+-----------------------------------------+------------+ | 1 | Pemrograman Database Menggunakan MySQL | 2016-00-00 | | 2 | PHP dan MySQL Langkah Demi Langkah + CD | 2016-00-00 | | 5 | Mahir Dalam 7 Hari: Coreldraw X6 | 2013-00-00 | +---------+-----------------------------------------+------------+



Penjelasan: Pada contoh diatas, setelah MySQL mengurutkan data berdasarkan tanggal terbit secara descending, selanjutnya, karena terdapat data dengan tgl_terbit yang sama, yaitu pada id_buku 1 dan 2, maka data akan diurutkan lagi berdasarkan kolom judul. Jika pada kolom pertama tidak ada data yang sama, maka tidak dilakukan pengurutan pada kolom kedua, misal: 1. 2. 3. 4.



SELECT id_buku, judul, tgl_terbit FROM buku1 WHERE id_penerbit = 4 ORDER BY tgl_terbit DESC, judul DESC



Hasil: +---------+------------------------------------+------------+ | id_buku | judul | tgl_terbit | +---------+------------------------------------+------------+ | 4 | Kumpulan Aplikasi PHP untuk Pemula | 2016-02-25 | | 3 | MySQL Untuk Pemula | 2014-11-28 | +---------+------------------------------------+------------+



Pada contoh diatas, karena tidak ada data tgl_terbit yang sama, maka tidak dilakukan pengurutan pada kolom judul.



8.7. HAVING Sebelumnya, kita telah membahas tentang klausa WHERE, nah, klausa HAVING ini sama seperti klausa WHERE, bedanya: 1. Klausa WHERE hanya dapat digunakan pada kolom riil pada tabel, sedangkan klausa HAVING dapat digunakan baik kolom riil tabel Panduan Lengkap Query MySQL 117



maupun kolom alias. Hal ini dikarenakan klausa HAVING dijalankan setelah statemen SELECT, sehingga semua nama kolom (termasuk kolom alias) telah selesai terbaca, sedangkan klausa WHERE dijalankan sebelum statemen SELECT. 2. Klausa HAVING dapat dijalankan setelah klausa GROUP BY sedangkan WHERE tidak. Pada query yang kompleks dengan banyak fungsi agregasi, klausa having ini sangat bermanfaat untuk memfilter data yang ingin ditampilkan. Berikut ini berbagai contoh query menggunakan klausa HAVING Contoh 1: Klausa HAVING sederhana 1. SELECT judul, tgl_terbit 2. FROM buku1 3. HAVING tgl_terbit >= "2016-00-00" AND judul LIKE "%php%"



Hasil: +-----------------------------------------+------------+ | judul | tgl_terbit | +-----------------------------------------+------------+ | PHP dan MySQL Langkah Demi Langkah + CD | 2016-00-00 | | Kumpulan Aplikasi PHP untuk Pemula | 2016-02-25 | +-----------------------------------------+------------+



Pada query diatas, klausa HAVING dapat diganti dengan klausa WHERE, keduanya akan menghasilkan output yang sama. Contoh 2: Aritmetika Pada Kolom Pada contoh kali ini, kita akan menampilkan judul buku, harga, nilai diskon ( 10% dari harga buku ), dan harga buku setelah diskon. Selanjutnya, dengan klausa HAVING kita ambil data buku yang memiliki harga setelah diskon diatas 50.000, querynya adalah: 1. SELECT judul, 2. harga, 3. ROUND(0.1 * harga) AS diskon, 4. harga - ROUND(harga * 0.1) AS harga_diskon



118 BAB 8 Syntax Dasar Pengambilan Data



5. FROM buku1 6. HAVING harga_diskon > 50000



Hasil: +-----------------------------------------+-------+--------+--------------+ | judul | harga | diskon | harga_diskon | +-----------------------------------------+-------+--------+--------------+ | Pemrograman Database Menggunakan MySQL | 59000 | 5900 | 53100 | | PHP dan MySQL Langkah Demi Langkah + CD | 75000 | 7500 | 67500 | | Mahir Dalam 7 Hari: Coreldraw X6 | 68000 | 6800 | 61200 | +-----------------------------------------+-------+--------+--------------+



Pada contoh diatas klausa HAVING diterapkan pada kolom alias yaitu harga_diskon, jika menggunakan klausa WHERE maka query akan berbentuk seperti berikut: 1. SELECT judul, 2. harga, 3. ROUND(0.1 * harga) AS diskon, 4. harga - ROUND(harga * 0.1) AS harga_diskon 5. FROM buku1 6. WHERE harga - ROUND(harga * 0.1) > 50000



Pada contoh diatas terlihat bahwa pada klausa WHERE kita harus menulis ulang formula penghitungan harga_diskon, hal ini karena klausa WHERE tidak mengenali kolom alias. Contoh 3: klausa HAVING setelah GROUP BY Seperti pembahasan kita tentang klausa GROUP BY, kali ini kita akan mengambil data jumlah buku yang dikelompokkan berdasarkan id_penerbit, namun dengan jumlah buku kurang dari 3 1. 2. 3. 4.



SELECT id_penerbit, COUNT(judul) AS jumlah_buku FROM buku1 GROUP BY id_penerbit HAVING jumlah_buku < 3



Hasil: +-------------+-------------+ | id_penerbit | jumlah_buku |



Panduan Lengkap Query MySQL 119



+-------------+-------------+ | 4 | 2 | +-------------+-------------+



Pada query diatas, kita menggunakan kolom alias pada having, jika menggunakan nama kolom, klausa having dapat kita ubah menjadi HAVING COUNT(judul) < 3. Karena dijalankan setelah klausa GROUP BY, maka kita tidak dapat mengganti HAVING dengan WHERE



8.8. LIMIT Sejauh ini, kita telah berhasil menampilkan data berdasarkan kriteria tertentu menggunakan klausa WHERE, namun, data yang ditampilkan tidak terbatas, semuanya ditampilkan. Untuk keperluan tertentu, kita perlu untuk membatasi banyaknya data yang diambil, misal menampilkan 10 buku terbaru. Untuk keperluan tersebut, kita gunakan klausa LIMIT. Contoh kita ambil 3 data buku terbaru: 1. 2. 3. 4. 5.



SELECT judul, tgl_terbit FROM buku WHERE id_penerbit = 1 ORDER BY tgl_terbit DESC, judul ASC LIMIT 3



Perhatikan bahwa kali ini kita menggunakan tabel buku, bukan buku1. Tabel ini berisi lebih banyak data, tabel ini telah disertakan pada file SQL buku ini. Hasil yang kita peroleh: +-----------------------------------------+------------+ | judul | tgl_terbit | +-----------------------------------------+------------+ | Pemrograman Database Menggunakan MySQL | 2016-00-00 | | Pemrograman PHP Dan MySQL Untuk Pemula | 2016-00-00 | | PHP dan MySQL Langkah Demi Langkah + CD | 2016-00-00 | +-----------------------------------------+------------+



Pada contoh diatas, MySQL akan mengambil semua data, kemudian mengurutkannya secara descending berdasarkan tanggal terbit, kemudian mengambil 3 baris teratas. 120 BAB 8 Syntax Dasar Pengambilan Data



Lebih lanjut, MySQL juga menyediakan opsi untuk mengambil sejumlah data tertentu yang dimulai dari baris/posisi tertentu, posisi ini dinamakan offset. Fitur ini sering digunakan untuk keperluan pagination. Sebagai contoh, melanjutkan query sebelumnya, kali ini kita tampilkan 5 data berikutnya: 1. 2. 3. 4. 5.



SELECT judul, tgl_terbit FROM buku WHERE id_penerbit = 1 ORDER BY tgl_terbit DESC, judul ASC LIMIT 3, 5



Perhatikan bahwa ketika kita menggunakan offset, maka parameter pertama bukan jumlah baris yang ingin diambil tetapi baris ke berapa yang ingin diambil kemudian baru dilanjutkan jumlah baris yang ingin diambil. Pada contoh diatas, untuk mengambil data mulai baris ke-4, kita menggunakan offset 3 bukan 4, karena index baris dimulai dari 0 (0,1,2,3…), sehingga, baris ke 4 bernilai 3. Perhatikan urutan penulisan keyword, terutama posisi penulisan ORDER BY. Ketika ditulis bersamaan dengan klausa WHERE dan LIMIT, maka klausa ORDER BY harus ditulis setelah klausa WHERE dan sebelum klausa LIMIT, agar mudah diingat, bahwa operasi bersifat umum ke spesifik. Pada contoh diatas: 



MySQL akan memfilter data sehingga yang diambil adalah data buku dengan id_penerbit 1, kemudian, MySQL menyimpan data tersebut ke dalam temporary tabel (klausa WHERE)







Selanjutnya, temporary tabel tersebut akan diurutkan sesuai dengan tanggal terbit dan judul (klausa ORDER BY)







Setelah diurutkan, MySQL akan mengambil 3 data pertama untuk ditampilkan ke user (klausa LIMIT)



Dari urutan diatas terlihat bahwa MySQL mengerjakannya dari umum (WHERE) ke spesifik (ORDER BY), kemudian LIMIT.



Panduan Lengkap Query MySQL 121



8.9. Mendefinisikan Nama Tabel Jika query yang kita buat melibatkan lebih dari satu tabel (seperti pada JOIN - dibahas pada BAB 10) dan nama kolom pada tabel-tabel tersebut ada yang sama maka bisa dipastikan akan terjadi konflik pada nama kolom. Untuk mengatasinya, kita perlu menyertakan nama tabel pada kolom yang ada pada statemen SELECT, sehingga MySQL tahu kolom tersebut diambil dari tabel yang mana. Misal: kita memilki tabel pengarang dan penerbit sebagai berikut: Tabel pengarang: mysql> SELECT * FROM pengarang LIMIT 5; +--------------+-----------------------------------+ | id_pengarang | nama | +--------------+-----------------------------------+ | 1 | R. H. Sianipar | | 2 | Abdul Kadir | | 3 | Jubilee Enterprise | | 4 | Madcoms | | 5 | Ricky Rachmanto & Grafisku Studio | +--------------+-----------------------------------+ 5 rows in set (0.00 sec)



Tabel penerbit: mysql> SELECT id_penerbit, nama FROM penerbit LIMIT 5; +-------------+---------------------------+ | id_penerbit | nama | +-------------+---------------------------+ | 1 | Andi Publisher | | 2 | Informatika | | 3 | PT. Elex Media Komputindo | | 4 | Jubilee | | 5 | Lokomedia | +-------------+---------------------------+ 5 rows in set (0.00 sec)



122 BAB 8 Syntax Dasar Pengambilan Data



Selanjutnya kita tampilkan data buku beserta pengarang dan penerbitnya sebagai berikut: 1. 2. 3. 4. 5. 6.



SELECT judul, tgl_terbit, pengarang.nama, penerbit.nama FROM buku, pengarang, penerbit WHERE buku.id_pengarang = pengarang.id_pengarang AND buku.id_penerbit = penerbit.id_penerbit ORDER BY tgl_terbit DESC LIMIT 5



Hasil: +-----------------------------------------+------------+--------------------+----------------+ | judul | tgl_terbit | nama | nama | +-----------------------------------------+------------+--------------------+----------------+ | Desain Grafis dengan Powerpoint | 2016-08-29 | Jubilee Enterprise | Jubilee | | Otodidak Membuat Blog dengan Blogger | 2016-02-29 | Jubilee Enterprise | Jubilee | | Kumpulan Aplikasi PHP untuk Pemula | 2016-02-25 | Jubilee Enterprise | Jubilee | | PHP dan MySQL Langkah Demi Langkah + CD | 2016-00-00 | R. H. Sianipar | Andi Publisher | | Pemrograman PHP Dan MySQL Untuk Pemula | 2016-00-00 | Madcoms | Andi Publisher | +-----------------------------------------+------------+--------------------+----------------+



Pada contoh diatas, tabel pengarang dan penerbit sama-sama memiliki kolom nama, sehingga wajib menuliskan nama tabel, jika tidak, maka akan muncul pesan error SQL Error (1052): Column 'nama' in field list is ambiguous yang artinya kolom nama ambigu apakah dari tabel penulis atau penerbit. Perhatikan bahwa kita menggunakan tanda dot (titik) untuk memisahkan nama tabel dengan nama kolom.



8.10. Alias Pada contoh contoh sebelumnya, terlihat bahwa data yang ditampilkan ke user selalu berbentuk tabel dengan nama kolom sesuai dengan nama yang kita definisikan dalam klausa SELECT. Pada kondisi tertentu, kita perlu mengubah nama kolom hasil query agar tabel hasil query tersebut dapat diolah lebih lanjut dengan mudah, seperti ditampilkan dalam web menggunakan PHP, nama kolom baru ini disebut kolom alias. Beberapa kondisi dimana nama kolom perlu diubah adalah ketika menggunakan fungsi agregat (seperti SUM, COUNT, dll), melakukan operasi aritmetika pada kolom, dan kolom hasil query memiliki nama



Panduan Lengkap Query MySQL 123



sama, seperti pada contoh sebelumnya dimana terdapat dua kolom dengan nama yang sama. Selain pada kolom, ketika query dijalankan kita juga dapat mengubah nama tabel, perubahan nama tabel ini sifatnya hanya sementara, saat query dijalankan saja. Hal ini hanya untuk memudahkan agar query lebih mudah ditulis dan dibaca, terutama jika query yang ditulis panjang.



8.10.1. Kolom Alias Untuk membuat alias pada kolom, gunakan keyword AS. Misal pada contoh query sebelumnya, kita ubah output nama, sesuai dengan nama tabel dimana kolom tersebut berada, selain itu, kita ubah kolom judul menjadi Judul Buku. Query yang kita jalankan: 1. 2. 3. 4. 5. 6. 7. 8. 9.



SELECT judul AS 'Judul Buku', tgl_terbit AS 'Tanggal Terbit', pengarang.nama AS Pengarang, penerbit.nama AS Penerbit FROM buku, pengarang, penerbit WHERE buku.id_pengarang = pengarang.id_pengarang AND buku.id_penerbit = penerbit.id_penerbit ORDER BY tgl_terbit DESC LIMIT 5



Hasil yang kita peroleh: +-------------------------------+----------------+--------------------+----------------+ | Judul Buku | Tanggal Terbit | Pengarang | Penerbit | +-------------------------------+----------------+--------------------+----------------+ | Desain Grafis dengan Powerp...| 2016-08-29 | Jubilee Enterprise | Jubilee | | Otodidak Membuat Blog denga...| 2016-02-29 | Jubilee Enterprise | Jubilee | | Kumpulan Aplikasi PHP untuk...| 2016-02-25 | Jubilee Enterprise | Jubilee | | PHP dan MySQL Langkah Demi ...| 2016-00-00 | R. H. Sianipar | Andi Publisher | | Pemrograman PHP Dan MySQL U...| 2016-00-00 | Madcoms | Andi Publisher | +-------------------------------+----------------+--------------------+----------------+



Perhatikan bahwa pada contoh diatas, kita mendefinisikan alias menggunakan keyword AS, disamping itu, jika nama kolom alias menggunakan spasi, maka harus berada di dalam tanda kutip, seperti pada 'Judul Buku' dan 'Tanggal Terbit'.



124 BAB 8 Syntax Dasar Pengambilan Data



Selain menggunakan keyword AS, kolom alias juga dapat ditulis tanpa keyword apapun, cukup menggunakan spasi. Contoh: 1. SELECT judul 'Judul Buku', 2. tgl_terbit 'Tanggal Terbit', 3. pengarang.nama Pengarang, 4. penerbit.nama Penerbit 5. FROM buku, pengarang, penerbit 6. ...



Penulis pribadi lebih memilih menggunakan keyword AS karena akan lebih mudah mengidentifikasi bahwa kolom tersebut adalah kolom alias. Contoh lain penggunaan alias: mysql> SELECT judul, YEAR(tgl_terbit) AS tahun_terbit -> FROM buku -> ORDER BY tgl_terbit DESC -> LIMIT 5; +-----------------------------------------+--------------+ | judul | tahun_terbit | +-----------------------------------------+--------------+ | Desain Grafis dengan Powerpoint | 2016 | | Otodidak Membuat Blog dengan Blogger | 2016 | | Kumpulan Aplikasi PHP untuk Pemula | 2016 | | Pemrograman Database Menggunakan MySQL | 2016 | | PHP dan MySQL Langkah Demi Langkah + CD | 2016 | +-----------------------------------------+--------------+ 5 rows in set (0.00 sec)



8.10.2. Tabel Alias Seperti telah kita bahas sebelumnya, jika query yang kita buat melibatkan lebih dari satu tabel maka akan lebih aman jika kita menuliskan nama tabel. Pada contoh diatas, nama tabel cukup panjang, sehingga jika field yang kita tuliskan banyak, maka akan mengulang penulisan nama tabel sebanyak field yang kita definisikan, agar lebih sederhana, kita dapat menggunakan alias untuk nama tabel Contoh:



Panduan Lengkap Query MySQL 125



1. 2. 3. 4. 5. 6. 7. 8. 9.



SELECT bk.judul AS 'Judul Buku', bk.tgl_terbit AS 'Tanggal Terbit', pg.nama AS Pengarang, pn.nama AS Penerbit FROM buku AS bk, pengarang AS pg, penerbit AS pn WHERE bk.id_pengarang = pg.id_pengarang AND bk.id_penerbit = pn.id_penerbit ORDER BY tgl_terbit DESC LIMIT 5



Sama seperti pada kolom alias, kita juga dapat mengabaikan penggunaan AS, sehingga kode yang kita tulis menjadi: 1. 2. 3. 4. 5. 6. 7. 8. 9.



SELECT bk.judul 'Judul Buku', bk.tgl_terbit 'Tanggal Terbit', pg.nama Pengarang, pn.nama Penerbit FROM buku bk, pengarang pg, penerbit pn WHERE bk.id_pengarang = pg.id_pengarang AND bk.id_penerbit = pn.id_penerbit ORDER BY tgl_terbit DESC LIMIT 5



126 BAB 8 Syntax Dasar Pengambilan Data



BAB 9 Operator Pada MySQL, terdapat tiga jenis operator yang didukung yaitu: operator aritmetika (aritmethic operator), operator pembanding (comparison operator), dan operator logika (logical operator). Pada bagian ini kita akan membahas ketiga jenis operator tersebut.



9.1. Operator Aritmetika Operator aritmetika digunakan untuk melakukan operasi bilangan, seperti penjumlahan dan pengurangan, adapun operator aritmetika yang didukung oleh MySQL adalah: No



Jenis Operator



Keterangan



1



DIV



Pembagian integer



2



/



Operator pembagian



3



-



Operator Minus atau Operator pengurangan



4



% atau MOD



Operator Modulo (sisa bagi)



5



+



Operator Penjumlahan



6



*



Operator Perkalian Tabel 9.1 Operator Aritmetika



Kita semua pasti sudah familiar dengan operator +, -, * m dan /, yang masih asing mungkin operator DIV dan (% atau MOD). Operator DIV digunakan untuk menghitung berapa banyak suatu bilangan dapat dibagi secara bulat. Misal 7 DIV 3 akan menghasilkan 2. Angka dua ini diperoleh dengan membagi 7 dengan 3 kemudian hasilnya, yaitu 2.33 dijadikan bilangan bulat, yaitu 2, jika 7 diganti 2, (2 DIV 3) maka akan menghasilkan nilai 0 Panduan Lengkap Query MySQL 127



9.1.1. Operator prioritas Ketika kita menggunakan beberapa operator secara bersamaan, maka urutan operator yang akan dieksekusi adalah perkalian (*), pembagian (/), modulo (%), penjumlahan (+), dan terakhir pengurangan (-). Contoh: SELECT 2 * 3 + 4 / 2



Query diatas akan menghasilkan angka 8, yaitu 6 (2+3) ditambah 2 (4/2). Kita dapat mengubah prioritas ini dengan menambahkan tanda kurung, misal: SELECT 2 * (3 + 4) / 2



maka hasil yang kita peroleh adalah 7, yang diperoleh dari 2 x 7 / 2



9.1.2. Operator Penjumlahan Fungsi penjumlahan dapat digunakan untuk berbagai keperluan, misal, pada tabel buku, kita ingin menaikkan harga Rp 1.100 untuk setiap judul buku, query yang kita gunakan: 1. SELECT judul, harga, harga + 1000 AS markup 2. FROM buku 3. LIMIT 3;



Hasil: +-----------------------------------------+-------+--------+ | judul | harga | markup | +-----------------------------------------+-------+--------+ | Pemrograman Database Menggunakan MySQL | 59000 | 60000 | | PHP dan MySQL Langkah Demi Langkah + CD | 75000 | 76000 | | MySQL Untuk Pemula | 34800 | 35800 | +-----------------------------------------+-------+--------+ Pada contoh diatas, kolom markup merupakan kolom alias.



128 BAB 9 Operator



9.1.3. Operator Minus atau Operator Pengurangan Pada MySQL, tanda minus memiliki dua kegunaan yang pertama untuk membuat bilangan menjadi minus, yang kedua untuk melakukan fungsi pengurangan. Untuk membuat nilai menjadi minus, kita cukup menambahkan tanda minus di depan nama kolom, misal: 1. SELECT judul, harga, -harga AS harga_minus 2. FROM buku 3. LIMIT 3;



Hasil: +-----------------------------------------+-------+-------------+ | judul | harga | harga_minus | +-----------------------------------------+-------+-------------+ | Pemrograman Database Menggunakan MySQL | 59000 | -59000 | | PHP dan MySQL Langkah Demi Langkah + CD | 75000 | -75000 | | MySQL Untuk Pemula | 34800 | -34800 | +-----------------------------------------+-------+-------------+



Jika kolom yang kita tambahkan tanda minus memiliki tipe data selain numeric, maka akan dihasilkan nilai -0. Fungsi kedua dari tanda minus ini adalah sebagai operator pengurangan. Misal kita ingin menampilkan data judul, harga, diskon sebesar Rp. 1.100, dan harga setelah diskon, query yang kita jalankan: 1. SELECT judul, harga, 1100 AS diskon, harga - 1100 AS harga_diskon 2. FROM buku 3. LIMIT 3;



Hasil yang kita peroleh: +-----------------------------------------+-------+--------+--------------+ | judul | harga | diskon | harga_diskon | +-----------------------------------------+-------+--------+--------------+ | Pemrograman Database Menggunakan MySQL | 59000 | 1100 | 57900 | | PHP dan MySQL Langkah Demi Langkah + CD | 75000 | 1100 | 73900 | | MySQL Untuk Pemula | 34800 | 1100 | 33700 | +-----------------------------------------+-------+--------+--------------+



Panduan Lengkap Query MySQL 129



9.1.4. Operator Perkalian Operator perkalian digunakan untuk melakukan operasi perkalian seperti perkalian matematika pada umumnya. Misal pada tabel buku kita ingin menampilkan data judul, harga, diskon sebesar 25% (0.25), dan harga setelah diskon, query yang kita jalankan: 1. SELECT judul, harga, "25%" AS diskon, harga - (harga * 0.25) AS harga_diskon 2. FROM buku 3. LIMIT 3;



Hasil yang kita peroleh: +-----------------------------------------+-------+--------+--------------+ | judul | harga | diskon | harga_diskon | +-----------------------------------------+-------+--------+--------------+ | Pemrograman Database Menggunakan MySQL | 59000 | 25% | 44250.00 | | PHP dan MySQL Langkah Demi Langkah + CD | 75000 | 25% | 56250.00 | | MySQL Untuk Pemula | 34800 | 25% | 26100.00 | +-----------------------------------------+-------+--------+--------------+



Pada query diatas, untuk menerapkan persentase diskon, kita tidak dapat menggunakan tanda persen, melainkan harus kita ubah ke dalam format desimal.



9.1.5. Operator Pembagian Operator pembagian digunakan untuk melakukan operasi pembagian seperti pembagian pada umumnya. Contoh pada tabel buku kita tampilkan data judul, harga, dan harga setelah diskon, query yang kita jalankan: 1. SELECT judul, harga, harga / 2 AS harga_diskon 2. FROM buku 3. LIMIT 3;



Hasil yang kita peroleh: +-----------------------------------------+-------+--------------+ | judul | harga | harga_diskon | +-----------------------------------------+-------+--------------+ | Pemrograman Database Menggunakan MySQL | 59000 | 29500.0000 | | PHP dan MySQL Langkah Demi Langkah + CD | 75000 | 37500.0000 |



130 BAB 9 Operator



| MySQL Untuk Pemula | 34800 | 17400.0000 | +-----------------------------------------+-------+--------------+



9.1.6. Operator Modulo Operator Modul0, yaitu % atau MOD digunakan untuk menghitung sisa bagi, misal 7 % 3 akan menghasilkan 1. Angka 1 ini diperoleh dari 7 / 3 = 2 masih sisa 1. Contoh lain 6 % 3 maka hasilnya 0 (nol). Sebagai contoh misal data pada tabel buku1 adalah sebagai berikut: mysql> SELECT judul, stok FROM buku1; +-----------------------------------------+------+ | judul | stok | +-----------------------------------------+------+ | Pemrograman Database Menggunakan MySQL | 5 | | PHP dan MySQL Langkah Demi Langkah + CD | 0 | | MySQL Untuk Pemula | 2 | | Kumpulan Aplikasi PHP untuk Pemula | 1 | | Mahir Dalam 7 Hari: Coreldraw X6 | 4 | +-----------------------------------------+------+ 5 rows in set (0.00 sec)



Selanjutnya kita jalankan query berikut: 1. SELECT judul, stok % 2 AS sisa 2. FROM buku1



Hasil yang kita peroleh: +-----------------------------------------+------+ | judul | sisa | +-----------------------------------------+------+ | Pemrograman Database Menggunakan MySQL | 1 | | PHP dan MySQL Langkah Demi Langkah + CD | 0 | | MySQL Untuk Pemula | 0 | | Kumpulan Aplikasi PHP untuk Pemula | 1 | | Mahir Dalam 7 Hari: Coreldraw X6 | 0 | +-----------------------------------------+------+



Hati hati, pada contoh diatas, stok dengan nilai 2 akan menghasilkan nilai 0, demikian juga dengan stok yang kosong (nilai stok 0), namun pada stok yang nilainya 1, akan menghasilkan nilai 1. Panduan Lengkap Query MySQL 131



Penggunaan modulo juga dapat menggunakan operator maupun fungsi MOD. Query diatas dapat diganti dengan query berikut: Operator MOD 1. SELECT judul, stok MOD 2 AS sisa 2. FROM buku1



Fungsi MOD 1. SELECT judul, MOD(stok, 2) AS sisa 2. FROM buku1



9.1.7. Operator DIV Operator div ini kebalikan dari operator modulo, jika pada module menghasilkan sisa bagi, operator DIV menghasilkan bilangan bulat dari pembagian tersebut. Misal kita ingin mengetahui hasil yang kita dapatkan jika stok buku dibagi 2 1. SELECT judul, stok DIV 2 AS sisa 2. FROM buku1



Hasil yang kita peroleh: +-----------------------------------------+------+ | judul | sisa | +-----------------------------------------+------+ | Pemrograman Database Menggunakan MySQL | 2 | | PHP dan MySQL Langkah Demi Langkah + CD | 0 | | MySQL Untuk Pemula | 1 | | Kumpulan Aplikasi PHP untuk Pemula | 0 | | Mahir Dalam 7 Hari: Coreldraw X6 | 2 | +-----------------------------------------+------+



Pada contoh diatas, stok yang jumlahnya kurang dari dua akan menghasilkan nilai 0



132 BAB 9 Operator



9.2. Operator Pembanding Operator pembanding digunakan untuk membandingkan dua buah nilai (nilai yang berada di sebelah kiri dan yang berada di sebelah kanan). Daftar operator pembanding yang didukung oleh MySQL: Keterangan



Operator A>B



True jika A Lebih besar dari B



A= B



True jika A lebih besar atau sama dengan B



A SELECT 1 = '1 '; +----------+ | 1 = '1 ' | +----------+ | 1 | +----------+ mysql> SELECT 1 = ' +--------------+



1



';



Panduan Lengkap Query MySQL 133



| 1 = ' 1 ' | +--------------+ | 1 | +--------------+ mysql> SELECT 'a' = 'A'; +-----------+ | 'a' = 'A' | +-----------+ | 1 | +-----------+



Berdasarkan kriteria diatas, jika kita ingin mencari buku dengan tanggal terbit 2016-00-00, kita dapat menjalankan query berikut: 1. SELECT judul, tgl_terbit 2. FROM buku 3. WHERE tgl_terbit = "2016-00-00"



Pada contoh diatas, kita membandingkan kolom tgl_terbit yang memiliki tipe data DATE dengan string "2016-00-00"



9.3. Operator Logika Disamping operator pembanding, MySQL juga mendukung operator logika yaitu AND dan OR. Logika OR bernilai true jika salah satu argumen bernilai terpenuhi (bernilai true) sedangkan logika AND akan bernilai true jika semua argumen bernilai true Nilai Sebelah Kiri



Operator



Nilai Sebelah Kanan



Hasil



True



OR



True



True



True



OR



False



True



True



AND



True



True



True



AND



False



False



Tabel 9.3. Operator Logika 134 BAB 9 Operator



Melanjutkan contoh query pada tabel buku, kali ini kita akan menampilkan data buku dengan id_penerbit 1 atau 2, query yang kita jalankan: 1. 2. 3. 4. 5.



SELECT judul, tgl_terbit, id_penerbit FROM buku WHERE id_penerbit = 1 OR id_penerbit = 2 ORDER BY tgl_terbit DESC LIMIT 5



Hasil yang kita peroleh: +----------------------------------------------+------------+-------------+ | judul | tgl_terbit | id_penerbit | +----------------------------------------------+------------+-------------+ | Pemrograman Database Menggunakan MySQL | 2016-00-00 | 1 | | PHP dan MySQL Langkah Demi Langkah + CD | 2016-00-00 | 1 | | Pemrograman PHP Dan MySQL Untuk Pemula | 2016-00-00 | 1 | | Pemrograman Stored Procedure Pada MySQL + cd | 2015-00-00 | 1 | | Belajar Sendiri Pasti Bisa CSS3 + cd | 2015-00-00 | 1 | +----------------------------------------------+------------+-------------+



Contoh lain kita ambil data dengan kriteria id_penerbit = 1 dan tahun terbit lebih besar atau sama dengan 2016 1. 2. 3. 4. 5.



SELECT judul, tgl_terbit, id_penerbit FROM buku WHERE id_penerbit = 1 AND tgl_terbit >= "2016-00-00" ORDER BY tgl_terbit DESC LIMIT 5



Hasil: +-----------------------------------------+------------+-------------+ | judul | tgl_terbit | id_penerbit | +-----------------------------------------+------------+-------------+ | Pemrograman Database Menggunakan MySQL | 2016-00-00 | 1 | | PHP dan MySQL Langkah Demi Langkah + CD | 2016-00-00 | 1 | | Pemrograman PHP Dan MySQL Untuk Pemula | 2016-00-00 | 1 | +-----------------------------------------+------------+-------------+



Perlu diperhatikan bahwa ketika menggabungkan operator OR dan AND maka terkadang hasil yang diperoleh tidak sesuai dengan yang diharapkan. Contoh kita akan mengambil data buku dengan kriteria:



Panduan Lengkap Query MySQL 135







id_penerbit = 1 atau id_penerbit = 2







dan tahun terbit 2016



Biasanya, query yang kita gunakan adalah: 1. SELECT judul, tgl_terbit, id_penerbit 2. FROM buku 3. WHERE id_penerbit = 1 OR id_penerbit = 4 AND tgl_terbit >= "2016-00-00" 4. ORDER BY tgl_terbit DESC 5. LIMIT 8



Hasil yang kita peroleh adalah sebagai berikut: +----------------------------------------------+------------+-------------+ | judul | tgl_terbit | id_penerbit | +----------------------------------------------+------------+-------------+ | Desain Grafis dengan Powerpoint | 2016-08-29 | 4 | | Otodidak Membuat Blog dengan Blogger | 2016-02-29 | 4 | | Kumpulan Aplikasi PHP untuk Pemula | 2016-02-25 | 4 | | Pemrograman Database Menggunakan MySQL | 2016-00-00 | 1 | | PHP dan MySQL Langkah Demi Langkah + CD | 2016-00-00 | 1 | | Pemrograman PHP Dan MySQL Untuk Pemula | 2016-00-00 | 1 | | Pemrograman Stored Procedure Pada MySQL + cd | 2015-00-00 | 1 | | Belajar Sendiri Pasti Bisa CSS3 + cd | 2015-00-00 | 1 | +----------------------------------------------+------------+-------------+



Pada contoh diatas, semua buku dengan id_penerbit 1 akan ditampilkan semua kapanpun tahun terbitnya. Hal ini dikarenakan operator AND akan dievaluasi terlebih dahulu (karena AND memiliki prioritas lebih tinggi) baru kemudian operator OR, sehingga pada contoh diatas, MySQL akan menampilkan: 



Data buku dengan tgl_terbit >= "2016-00-00" dan id_penerbit 4, hal ini dikarenakan diantara keduanya terdapat operator AND.







Semua data buku dengan id_penerbit 1



Nah, untuk membuat output sesuai yang kita harapkan, kita harus mengelompokkan operator menggunakan tanda kurung, karena semua yang ada di dalam tanda kurung memiliki prioritas lebih dibanding yang lain termasuk operator AND. Selanjutnya, mari kita perbaiki query dengan menambahkan tanda kurung:



136 BAB 9 Operator



1. SELECT judul, tgl_terbit, id_penerbit 2. FROM buku 3. WHERE (id_penerbit = 1 OR id_penerbit = 4) AND tgl_terbit >= "2016-00-00" 4. ORDER BY tgl_terbit DESC 5. LIMIT 8



Hasil: +-----------------------------------------+------------+-------------+ | judul | tgl_terbit | id_penerbit | +-----------------------------------------+------------+-------------+ | Desain Grafis dengan Powerpoint | 2016-08-29 | 4 | | Otodidak Membuat Blog dengan Blogger | 2016-02-29 | 4 | | Kumpulan Aplikasi PHP untuk Pemula | 2016-02-25 | 4 | | Pemrograman Database Menggunakan MySQL | 2016-00-00 | 1 | | PHP dan MySQL Langkah Demi Langkah + CD | 2016-00-00 | 1 | | Pemrograman PHP Dan MySQL Untuk Pemula | 2016-00-00 | 1 | +-----------------------------------------+------------+-------------+



9.4. Operator IN Operator IN digunakan untuk membandingkan data yang ada pada kolom tertentu dengan sekelompok nilai yang telah ditentukan. Adapun syntax yang digunakan adalah: SELECT kolom FROM tabel WHERE kolom IN (nilai1, nilai2, nilai3, ...) Contoh kita ingin menampilkan data buku dengan id_penerbit 1, 3, dan 4, query yang kita jalankan adalah: 1. 2. 3. 4.



SELECT judul, tgl_terbit, id_penerbit FROM buku WHERE id_penerbit IN (1, 3, 4) LIMIT 7



Hasil yang kita peroleh: +-----------------------------------------+------------+-------------+ | judul | tgl_terbit | id_penerbit | +-----------------------------------------+------------+-------------+ | Pemrograman Database Menggunakan MySQL | 2016-00-00 | 1 |



Panduan Lengkap Query MySQL 137



| PHP dan MySQL Langkah Demi Langkah + CD | 2016-00-00 | 1 | | MySQL Untuk Pemula | 2014-11-28 | 4 | | Kumpulan Aplikasi PHP untuk Pemula | 2016-02-25 | 4 | | Pemrograman PHP Dan MySQL Untuk Pemula | 2016-00-00 | 1 | | Blogger untuk Pemula | 2015-06-15 | 3 | | Ide Bisnis Bermodal Blog | 2014-12-08 | 3 | +-----------------------------------------+------------+-------------+



Jika kita perhatikan operator IN ini sama dengan operator OR, bedanya penulisannya lebih ringkas, dimana kita tidak perlu menuliskan nama field berulangkali, dan secara internal, ketika menjalankan operator IN, MySQL akan mengubahnya menjadi OR, jadi, bisa di katakan bahwa operator IN merupakan alias dari operator OR. Pada query diatas, jika kita ubah menjadi OR, klausa WHERE menjadi WHERE id_penerbit = 1 OR id_penerbit = 3 OR id_operator = 4



9.5. Operator BETWEEN Operator BETWEEN digunakan untuk mengevaluasi nilai pada suatu range tertentu, range ini terdiri dari nilai minimum dan nilai maksimum. Adapun format penulisannya adalah sebagai berikut: SELECT kolom FROM tabel WHERE kolom BETWEEN nilai_minimum AND nilai_maksimum



Penting diperhatikan bahwa kriteria tersebut akan cocok dengan data yang memiliki nilai sama dengan nilai_minimum dan nilai_maksimum. Jika dibuat dalam bentuk operator pembanding, maka akan berbentuk seperti query berikut: SELECT kolom FROM tabel WHERE kolom >= nilai_minimum AND kolom = "2016-00-00" 5. ) 6. LIMIT 5



Hasil: +------------------------------------+-------------+------------+ | judul | id_penerbit | tgl_terbit | +------------------------------------+-------------+------------+ | MySQL Untuk Pemula | 4 | 2014-11-28 | | Kumpulan Aplikasi PHP untuk Pemula | 4 | 2016-02-25 | | Blogger untuk Pemula | 3 | 2015-06-15 | | Ide Bisnis Bermodal Blog | 3 | 2014-12-08 | | Jago Wordpress | 3 | 2014-11-03 | +------------------------------------+-------------+------------+



Operator NOT ini sering digunakan bersama dengan operator IN. Contoh kita ambil data buku dengan id_penerbit selain 1, 3, dan 4 1. SELECT judul, tgl_terbit, id_penerbit 2. FROM buku 3. WHERE id_penerbit NOT IN (1, 3, 4)



Hasil: +----------------------------------------------+------------+-------------+ | judul | tgl_terbit | id_penerbit | +----------------------------------------------+------------+-------------+ | Trik Kolaborasi ANDROID dengan PHP dan MySQL | 2015-12-22 | 5 | | Cara Efektif Belajar Framework Laravel | 2015-04-15 | 5 | | Framework PHP Yii 2 | 2016-00-00 | 7 | +----------------------------------------------+------------+-------------+



Contoh lain kita ambil data buku yang terbit di luar bulan Juni s.d Desember 2016 1. SELECT judul, tgl_terbit, id_penerbit 2. FROM buku 3. WHERE id_penerbit NOT IN (1, 3, 4)



Hasil: 140 BAB 9 Operator



+-----------------------------------------+--------------+-------+ | judul | id_pengarang | harga | +-----------------------------------------+--------------+-------+ | Pemrograman Database Menggunakan MySQL | 1 | 59000 | | PHP dan MySQL Langkah Demi Langkah + CD | 1 | 75000 | | MySQL Untuk Pemula | 3 | 34800 | | Kumpulan Aplikasi PHP untuk Pemula | 3 | 34800 | | Pemrograman PHP Dan MySQL Untuk Pemula | 4 | 69000 | +-----------------------------------------+--------------+-------+



9.7. Operator LIKE Jika pada operator pembanding kita menggunakan operator sama dengan ( = ) untuk mengecek apakah suatu data memiliki nilai yang sama persis dengan nilai tertentu, maka untuk mengecek apakah suatu data mengandung string/kata tertentu kita gunakan operator LIKE. Operator LIKE memiliki dua wildcard (karakter khusus yang digunakan untuk mewakili satu atau lebih karakter) yaitu: 



Wildcard % yang digunakan untuk mewakili satu karakter atau lebih, dan







Wildcard _ yang digunakan untuk mewakili hanya satu karakter



Wildcard % Wildcard % dapat diletakkan dimana saja di dalam teks yang dicari baik di depan, tengah, maupun belakang, dan dapat digunakan lebih dari satu kali. mari kita bahas satu per satu dengan contoh. Contoh 1: kita akan mencari judul buku yang mengandung kata depan MySQL, query yang kita jalankan: 1. SELECT judul, tgl_terbit 2. FROM buku 3. WHERE judul LIKE "MySQL%";



Hasil yang kita peroleh: +--------------------+------------+ | judul | tgl_terbit | +--------------------+------------+ | MySQL Untuk Pemula | 2014-11-28 | +--------------------+------------+



Panduan Lengkap Query MySQL 141



Contoh 2: Kita cari judul buku yang berakhiran MySQL, query yang kita jalankan: 1. SELECT judul, tgl_terbit 2. FROM buku 3. WHERE judul LIKE "%MySQL";



Hasil: +----------------------------------------------+------------+ | judul | tgl_terbit | +----------------------------------------------+------------+ | Pemrograman Database Menggunakan MySQL | 2016-00-00 | | Trik Kolaborasi ANDROID dengan PHP dan MySQL | 2015-12-22 | +----------------------------------------------+------------+



Contoh 3: Kita cari judul buku yang mengandung kata MySQL, query yang kita jalankan: 1. SELECT judul, tgl_terbit 2. FROM buku 3. WHERE judul LIKE "%MySQL%";



Hasil: +----------------------------------------------+------------+ | judul | tgl_terbit | +----------------------------------------------+------------+ | Pemrograman Database Menggunakan MySQL | 2016-00-00 | | PHP dan MySQL Langkah Demi Langkah + CD | 2016-00-00 | | MySQL Untuk Pemula | 2014-11-28 | | Pemrograman PHP Dan MySQL Untuk Pemula | 2016-00-00 | | Trik Kolaborasi ANDROID dengan PHP dan MySQL | 2015-12-22 | | Pemrograman Stored Procedure Pada MySQL + cd | 2015-00-00 | +----------------------------------------------+------------+



Contoh 4: Kita cari judul buku yang mengandung kata MySQL dan Pemula, query yang kita jalankan: 1. SELECT judul, tgl_terbit 2. FROM buku 3. WHERE judul LIKE "%MySQL%pemula%";



Hasil: 142 BAB 9 Operator



+----------------------------------------+------------+ | judul | tgl_terbit | +----------------------------------------+------------+ | MySQL Untuk Pemula | 2014-11-28 | | Pemrograman PHP Dan MySQL Untuk Pemula | 2016-00-00 | +----------------------------------------+------------+



Model keempat ini sering digunakan untuk form pencarian di website dimana keyword yang dimasukkan lebih dari satu kata Wildcard _ Sama seperti wildcard %, wildcard _ juga dapat diletakkan dimana saja di dalam teks pencarian. Karena merupakan karakter khusus yang digunakan oleh MySQL, maka jika pada teks yang kita cari mengandung karakter tersebut, maka kita harus meng-escape karakter tersebut menggunakan backslash (\) Contoh 1: kita cari judul buku yang mengandung kata MySQL maupun MSSQL, maka query yang kita gunakan: 1. SELECT judul, tgl_terbit 2. FROM buku 3. WHERE judul LIKE "%M_SQL%";



Contoh lain kita akan mencari kata yang terdiri dari 5 karakter, dimana 3 karakter paling belakang adalah SQL 1. SELECT judul, tgl_terbit 2. FROM buku 3. WHERE judul LIKE "%__SQL%";



Kriteria diatas akan cocok dengan kata PQSQL, MSSQL, DBSQL, dst. Menggabungkan dengan NOT Seperti telah kita pelajari sebelumnya, kita dapat menggunakan operator NOT untuk membalik kondisi, kita juga dapat menggabungkan operator NOT dengan LIKE, sebagai contoh kita mencari judul buku yang tidak mengandung kata SQL dan Pemula, query yang kita jalankan: Panduan Lengkap Query MySQL 143



1. SELECT judul, tgl_terbit 2. FROM buku 3. WHERE judul NOT LIKE "%SQL%Pemula%";



Hasil: +-------------------------------------------------------+------------+ | judul | tgl_terbit | +-------------------------------------------------------+------------+ | Pemrograman Database Menggunakan MySQL | 2016-00-00 | | PHP dan MySQL Langkah Demi Langkah + CD | 2016-00-00 | | Kumpulan Aplikasi PHP untuk Pemula | 2016-02-25 | | Blogger untuk Pemula | 2015-06-15 | | Ide Bisnis Bermodal Blog | 2014-12-08 | | ... | ... | +-------------------------------------------------------+------------+



9.8. Mengevaluasi NULL NULL merupakan tipe data khusus yang artinya nilai tidak terdefinisi. NULL



tidak sama dengan 0 pada numeric, teks kosong pada string, atau 0000-0000 pada tipe data date, oleh karena itu, kita tidak dapat menggunakan operator pembanding apapun untuk menguji apakah suatu kolom bernilai NULL atau tidak. Misal kita memiliki tabel penerbit dengan data sebagai berikut: mysql> SELECT nama, telp FROM penerbit; +---------------------------+----------------+ | nama | telp | +---------------------------+----------------+ | Andi Publisher | 0274-561881 | | Informatika | 0813-2220-1946 | | PT. Elex Media Komputindo | NULL | | Jubilee | | | Lokomedia | 0274-9515000 | | Maxikom | 0711-7336565 | +---------------------------+----------------+ 6 rows in set (0.00 sec)



Pada contoh diatas, data telp PT. Elex Media Komputindo bernilai NULL, sedangkan pada Jubilee berisi string kosong '', selanjutnya, kita cari data penerbit yang data nomor teleponnya nya kosong dengan menjalankan query berikut: 144 BAB 9 Operator



1. SELECT nama, telp 2. FROM penerbit 3. WHERE telp = '';



Hasil yang kita peroleh: +---------+------+ | nama | telp | +---------+------+ | Jubilee | | +---------+------+



Pada contoh diatas terlihat bahwa hanya Jubilee yang cocok dengan query yang kita jalankan. Untuk menguji apakah suatu kolom bernilai NULL, kita harus menggunakan IS NULL. Mari kita perbaiki query dengan menggunakan IS NULL 1. SELECT nama, telp 2. FROM penerbit 3. WHERE telp = '' OR telp IS NULL;



Hasil: +---------------------------+------+ | nama | telp | +---------------------------+------+ | PT. Elex Media Komputindo | NULL | | Jubilee | | +---------------------------+------+



Seperti operator lain, kita juga dapat menggunakan operator NOT untuk membalik kondisi, sehingga untuk mencari kolom yang tidak mengandung nilai NULL, kita gunakan IS NOT NULL, misal:



1. SELECT nama, telp 2. FROM penerbit 3. WHERE telp != '' AND telp IS NOT NULL;



Hasil: Panduan Lengkap Query MySQL 145



+----------------+----------------+ | nama | telp | +----------------+----------------+ | Andi Publisher | 0274-561881 | | Informatika | 0813-2220-1946 | | Lokomedia | 0274-9515000 | | Maxikom | 0711-7336565 | +----------------+----------------+



146 BAB 9 Operator



BAB 10 JOIN Pada MySQL Pada praktiknya, sebuah database terdiri dari banyak tabel, bahkan ada yang hingga ratusan tabel, hal tersebut terkadang memang diperlukan agar prinsip prinsip pengelolaan database yang baik dapat tetap terjaga seperti integritas dan konsistensi data. Tabel tabel tersebut umumnya berhubungan/berelasi antara satu dengan yang lain, sehingga untuk menampilkan informasi tertentu yang melibatkan lebih dari satu tabel, kita perlu menggabungkan beberapa tabel menjadi satu, proses ini dinamakan JOIN. Pada bab ini kita akan membahas lebih jauh berbagai jenis JOIN yang dapat diterapkan pada MySQL



10.1. Prinsip Dasar JOIN Ketika menggabungkan tabel, kita perlu memegang beberapa prinsip dasar sehingga kita dapat memiliki gambaran tabel akhir yang akan dihasilkan, disamping itu, ketika dihadapkan pada kondisi dimana kita harus menggabungkan tabel, kita tahu apa yang harus kita lakukan. Beberapa prinsip penggabungan tabel: 



Identifikasi primary key dan foreign key dari tabel yang akan kita gabungkan. Primary key adalah field kunci yang unik yang yang membedakan tiap row dari suatu tabel. Sedangkan foreign key adalah field pada tabel lain yang menjadi referensi dari primary key, artinya nilai foreign key pada tabel tersebut berasal dari nilai primary key tabel lain. Tidak seperti primary key, foreign key tidak harus unik, dalam satu tabel beberapa row bisa memiliki key yang sama. Dalam join tabel, primary key dan foreign key tidak harus ada, namun dengan adanya kedua key tersebut akan sangat memudahkan dalam menggabungkan tabel.







Identifikasikan hubungan antar tabel yang akan di gabung, apakah one to one, one to many, atau many to one. Dengan Panduan Lengkap Query MySQL 147



mengidentifikasikan sifat hubungan antar tabel tersebut, kita tahu apa yang harus kita lakukan dan tahu bentuk tabel yang akan dihasilkan. 



Tentukan tabel utama dari tabel yang akan digabungkan. Maksudnya disini adalah dari tabel yang ingin kita gabungkan, tabel mana yang akan ditampilkan dan tabel mana yang sifatnya hanya pelengkap. Misal kita ingin menampilkan data buku beserta penerbitnya, adapun field yang ingin kita tampilkan adalah Judul Buku dan Nama Penerbit. Pada tabel buku terdapat field id_penerbit yang merupakan foreign key dari field id_penerbit yang ada di tabel penerbit. Pada kondisi demikian tabel buku merupakan tabel utama yang akan kita tampilkan, sedangkan tabel penerbit merupakan tabel pelengkap.



10.2. Jenis JOIN Tidak seperti pada database lainnya, pada MySQL, hanya terdapat dua jenis join yaitu inner join dan outer join. Keduanya akan kita bahas lebih jauh pada sub bab berikutnya. Pada bagian ini kita akan menggunakan tabel buku dan tabel penerbit.



10.2.1. INNER JOIN Atau CROSS JOIN Pada inner/cross join, data yang yang ditampilkan hanya data yang ada di kedua tabel, jika digambarkan dalam bentuk irisan, tampak seperti gambar berikut:



buku



penerbit



Gambar 10.1 Ilustrasi INNER JOIN Misal kita tampilkan semua data buku hanya yang ada data penerbitnya. Perintah SQL yang kita jalankan: 148 BAB 10 JOIN Pada MySQL



1. SELECT judul, nama 2. FROM buku 3. INNER JOIN penerbit ON buku.id_penerbit = penerbit.id_penerbit;



Hasil yang kita peroleh: +-------------------------------------------------------+-----------------------+ | judul | nama | +-------------------------------------------------------+-----------------------+ | Pemrograman Database Menggunakan MySQL | Andi Publisher | | PHP dan MySQL Langkah Demi Langkah + CD | Andi Publisher | | MySQL Untuk Pemula | Jubilee | | Kumpulan Aplikasi PHP untuk Pemula | Jubilee | | Pemrograman PHP Dan MySQL Untuk Pemula | Andi Publisher | | ... | ... | +-------------------------------------------------------+-----------------------+



Klausa INNER JOIN dapat diganti dengan CROSS JOIN, atau cukup dengan JOIN saja, ketiganya akan menghasilkan output yang sama. Pada buku ini, kita akan selalu menggunakan klausa JOIN tanpa tambahan INNER atau CROSS.



10.2.2. OUTER JOIN Model join yang kedua adalah OUTER JOIN. Seperti namanya, OUTER JOIN akan menampilkan semua data pada salah satu tabel dan data pada pada tabel lain yang terhubung dengan tabel pertama. OUTER JOIN ini dibagi menjadi tiga yaitu LEFT OUTER JOIN, RIGHT OUTER JOIN, dan FULL OUTER JOIN, namun, sampai dengan saat ini, MySQL hanya men-support LEFT OUTER JOIN dan RIGHT OUTER JOIN.



10.2.2.1. LEFT OUTER JOIN atau LEFT JOIN LEFT OUTER JOIN akan menampilkan semua data pada tabel sebelah kiri dan data yang ada di tabel sebelah kanan khusus yang datanya ada pada tabel sebelah kiri. Jika digambarkan dalam bentuk irisan akan tampak seperti gambar berikut:



Panduan Lengkap Query MySQL 149



buku



penerbit



Gambar 10.2 Ilustrasi LEFT OUTER JOIN Contoh 1: Misal kita tampilkan semua data judul buku beserta nama penerbitnya. Perintah SQL yang kita jalankan: 1. SELECT judul, nama 2. FROM buku 3. LEFT OUTER JOIN penerbit ON buku.id_penerbit = penerbit.id_penerbit;



Hasil yang kita peroleh: +-------------------------------------------------------+------------------------+ | judul | nama | +-------------------------------------------------------+------------------------+ | Pemrograman Database Menggunakan MySQL | Andi Publisher | | PHP dan MySQL Langkah Demi Langkah + CD | Andi Publisher | | ... | ... | | Mudah Menggunakan Internet Untuk Pemula | Andi Publisher | | Framework PHP Yii 2 | NULL | | From Zero To A Pro: Java Script Dan jQuery | Andi Publisher | | From Zero To A Pro: Pemrograman Aplikasi Android + cd | Andi Publisher | | Belajar Sendiri Pasti Bisa CSS3 + cd | Andi Publisher | +-------------------------------------------------------+------------------------+ 21 rows in set (0.00 sec)



Perhatikan bahwa kolom nama penerbit yang id_penerbitnya tidak ada di tabel buku akan menghasilkan nilai NULL Penulisan LEFT OUTER JOIN dapat disederhanakan hanya dengan menuliskan LEFT JOIN saja. Dalam buku ini, penulis selalu menggunakan model kedua karena penulisannya yang lebih ringkas dan dalam praktek, kita akan sering menemui model penulisan ini. Seperti yang telah kita pelajari pada bab sebelumnya, kita dapat menguji nilai NULL dengan klausa IS NOT NULL, melanjutkan contoh query diatas, mari kita hilangkan data buku yang nama penerbitnya bernilai NULL, kita ubah query menjadi: 150 BAB 10 JOIN Pada MySQL



1. 2. 3. 4.



SELECT judul, nama FROM buku LEFT JOIN penerbit ON buku.id_penerbit = penerbit.id_penerbit WHERE nama IS NOT NULL



Jika query tersebut dijalankan, hasil yang diperoleh sama seperti contoh ketika kita menggunakan INNER JOIN/JOIN Contoh 2: Tabel kedua terdapat lebih dari satu data Pada contoh sebelumnya hubungan antara tabel buku dan penerbit adalah satu ke banyak ke satu (many to one) dimana satu judul buku hanya bisa diterbitkan oleh satu penerbit (Gambar 10.3).



Gambar 10.3 Ilustrasi Relasi Many to One Pada kasus yang sering terjadi, hubungan antara tabel pertama dan kedua adalah satu ke banyak (one to many) dimana data pada tabel pertama terhubung ke banyak data pada tabel ke dua (Gambar 10.4).



Gambar 10.4 Ilustrasi Relasi One to Many



Panduan Lengkap Query MySQL 151



Pada contoh Gambar 10.4, satu buku dapat dibeli berkali kali, dengan kata lain beberapa transaksi dapat terjadi pada satu buku. Pada model seperti ini, penggunaan LEFT JOIN akan memberikan hasil di luar ekspektasi, misal data pada tabel buku adalah sebagai berikut: +---------+----------------------------------------+ | id_buku | judul | +---------+----------------------------------------+ | 3 | MySQL Untuk Pemula | | 4 | Kumpulan Aplikasi PHP untuk Pemula | | 5 | Pemrograman PHP Dan MySQL Untuk Pemula | +---------+----------------------------------------+



Kita juga memiliki tabel penjualan_detail dengan data sebagai berikut: +---------------+---------+------------+--------------+--------+-------+ | id_trx_detail | id_buku | jml_barang | harga_satuan | diskon | total | +---------------+---------+------------+--------------+--------+-------+ | 2 | 4 | 1 | 34800 | 0 | 34800 | | 6 | 4 | 2 | 34800 | 0 | 69600 | | 12 | 5 | 1 | 69000 | 0 | 69000 | | 16 | 5 | 1 | 69000 | 0 | 69000 | | 19 | 5 | 1 | 69000 | 0 | 69000 | +---------------+---------+------------+--------------+--------+-------+



Kolom id_buku pada tabel ini merupakan foreign key dari kolom id_buku pada tabel buku. Selanjutnya, kita ingin menampilkan data banyaknya transaksi untuk masing masing buku. Query yang kita jalankan adalah: 1. 2. 3. 4.



SELECT id_buku, judul, jml_barang, total FROM buku LEFT JOIN penjualan_detail ON buku.id_buku = penjualan_detail.id_buku



Hasil yang kita peroleh: +---------+----------------------------------------+------------+-------+ | id_buku | judul | jml_barang | total | +---------+----------------------------------------+------------+-------+ | 3 | MySQL Untuk Pemula | NULL | NULL | | 4 | Kumpulan Aplikasi PHP untuk Pemula | 1 | 34800 | | 4 | Kumpulan Aplikasi PHP untuk Pemula | 2 | 69600 | | 5 | Pemrograman PHP Dan MySQL Untuk Pemula | 1 | 69000 | | 5 | Pemrograman PHP Dan MySQL Untuk Pemula | 1 | 69000 | | 5 | Pemrograman PHP Dan MySQL Untuk Pemula | 1 | 69000 | +---------+----------------------------------------+------------+-------+



152 BAB 10 JOIN Pada MySQL



Pada contoh diatas, baris dengan id_buku 4 dan 5 ditampilkan lebih dari satu kali karena pada tabel transaksi_detail, data dengan id_buku tersebut jumlahnya lebih dari satu. Pada contoh ini, id_buku 4 dan 5 merupakan data irisan pada kedua tabel (Gambar 10.2) sehingga semua data yang mengandung id_buku tersebut ditampilkan.



10.2.2.2. RIGHT OUTER JOIN atau RIGHT JOIN Kebalikan dari LEFT OUTER JOIN, RIGHT OUTER JOIN akan menampilkan semua data pada tabel yang ada di sebelah kanan dan data yang ada di sebelah kiri khusus yang memiliki hubungan dengan tabel di sebelah kanan. Jika digambarkan dalam bentuk irisan akan tampak seperti gambar berikut:



buku



penerbit



Gambar 10.5 Ilustrasi RIGHT OUTER JOIN Misal kita tampilkan semua data penerbit beserta data buku yang diterbitkan. Perintah SQL yang kita jalankan: 1. 2. 3. 4.



SELECT judul, nama FROM buku RIGHT JOIN penerbit ON buku.id_penerbit = penerbit.id_penerbit



Seperti pada contoh LEFT JOIN, pada contoh diatas penulis menyingkat RIGHT OUTER JOIN menjadi hanya RIGHT JOIN Hasil yang kita peroleh adalah: +------------------------------------------+------------------------+ | judul | nama | +------------------------------------------+------------------------+ | Pemrograman Database Menggunakan MySQL | Andi Publisher | | PHP dan MySQL Langkah Demi Langkah + CD | Andi Publisher | | ... | ... | | Belajar Sendiri Pasti Bisa CSS3 + cd | Andi Publisher |



Panduan Lengkap Query MySQL 153



| NULL | Informatika | | NULL | Maxikom | +------------------------------------------+------------------------+



Kebalikan dari LEFT JOIN, pada contoh diatas, untuk penerbit yang tidak ada data bukunya, maka kolom judul akan bernilai NULL, seperti contoh LEFT JOIN, kita dapat menghilangkan baris yang bernilai NULL dengan klausa IS NOT NULL 1. 2. 3. 4. 5.



SELECT judul, nama FROM buku RIGHT JOIN penerbit ON buku.id_penerbit = penerbit.id_penerbit WHERE judul IS NOT NULL



10.2.2.3. FULL OUTER JOIN FULL OUTER JOIN digunakan untuk menampilkan semua data baik data tabel yang ada di sebelah kiri maupun data tabel yang ada di sebelah kanan. Jika digambarkan dalam bentuk diagram irisan, maka akan tampak seperti gambar berikut:



buku



penerbit



Gambar 10.6 Ilustrasi FULL OUTER JOIN Seperti telah kita bahas sebelumnya, MySQL belum mendukung model penggabungan seperti ini, namun demikian, kita tetap dapat melakukannya secara tidak langsung yaitu dengan menggabungkan LEFT JOIN dan RIGHT JOIN Sebagai contoh kita gabungkan data tabel buku dan data tabel penerbit sebagai berikut:



154 BAB 10 JOIN Pada MySQL



1. 2. 3. 4. 5. 6. 7.



SELECT judul, nama FROM buku LEFT JOIN penerbit ON buku.id_penerbit = penerbit.id_penerbit UNION SELECT judul, nama FROM buku RIGHT JOIN penerbit ON buku.id_penerbit = penerbit.id_penerbit



Hasil yang kita peroleh adalah: +-------------------------------------------------------+-----------------+ | judul | nama | +-------------------------------------------------------+-----------------+ | Pemrograman Database Menggunakan MySQL | Andi Publisher | | PHP dan MySQL Langkah Demi Langkah + CD | Andi Publisher | | ... | ... | | Framework PHP Yii 2 | NULL | | From Zero To A Pro: Java Script Dan jQuery | Andi Publisher | | From Zero To A Pro: Pemrograman Aplikasi Android + cd | Andi Publisher | | Belajar Sendiri Pasti Bisa CSS3 + cd | Andi Publisher | | NULL | Informatika | | NULL | Maxikom | +-------------------------------------------------------+-----------------+



Pada contoh diatas, UNION digunakan untuk menggabungkan tabel hasil query SELECT. Lebih jauh tentang UNION akan kita bahas pada BAB 15.



10.2.3. Menghafal JOIN Dari berbagai jenis join yang telah kita bahas diatas kita dapat menyimpulkan ada tiga model join yang didukung oleh MySQL yaitu INNER / CROSS JOIN, LEFT OUTER JOIN, dan RIGHT OUTER JOIN. Agar dapat mudah menghafal ketiganya, usahakan selalu konsisten dalam penulisan JOIN, penulis sendiri selalu menulis ketiganya sebagai berikut: 1. JOIN sebagai pengganti inner / cross join 2. LEFT JOIN sebagai pengganti left outer join 3. RIGHT JOIN sebagai pengganti right outer join



Panduan Lengkap Query MySQL 155



10.3. Join Banyak Tabel Dengan klausa JOIN, kita dapat menggabungkan tabel dengan jumlah yang tidak terbatas, misal kita gabungkan tabel buku, penerbit, dan pengarang, query yang kita jalankan adalah: 1. 2. 3. 4. 5. 6.



SELECT judul, pg.nama AS nama_pengarang, pn.nama AS nama_penerbit FROM buku LEFT JOIN pengarang AS pg ON buku.id_pengarang = pg.id_pengarang LEFT JOIN penerbit AS pn ON buku.id_penerbit = pn.id_penerbit



Hasil yang kita peroleh: +-------------------------------------------------------+----------------+----------------+ | judul | nama_pengarang | nama_penerbit | +-------------------------------------------------------+----------------+----------------+ | Pemrograman Database Menggunakan MySQL | R. H. Sianipar | Andi Publisher | | PHP dan MySQL Langkah Demi Langkah + CD | R. H. Sianipar | Andi Publisher | | ... | ... | ... | | Mudah Menggunakan Internet Untuk Pemula | Madcoms | Andi Publisher | | Framework PHP Yii 2 | Yosef Murya | NULL | | From Zero To A Pro: Java Script Dan jQuery | Abdul Kadir | Andi Publisher | | From Zero To A Pro: Pemrograman Aplikasi Android + cd | Abdul Kadir | Andi Publisher | | Belajar Sendiri Pasti Bisa CSS3 + cd | Abdul Kadir | Andi Publisher | +-------------------------------------------------------+----------------+----------------+



Pada contoh diatas, pertama-tama MySQL akan menggabungkan tabel buku dengan tabel pengarang, hasil dari penggabungan tersebut akan digabungkan lagi dengan tabel penerbit. Pada penggabungan model outer join seperti diatas, urutan tabel harus diperhatikan karena MySQL akan menampilkan semua data tabel yang ada di paling kiri. Hal ini tidak berlaku pada model INNER JOIN. Pada INNER JOIN, MySQL akan menentukan sendiri tabel mana yang akan di proses terlebih dahulu, prioritas tabel tergantung banyak faktor seperti primary key, foreign key, index, dll Contoh INNER JOIN untuk beberapa tabel: 1. SELECT judul, pg.nama AS nama_pengarang, pn.nama AS nama_penerbit 2. FROM buku 3. JOIN pengarang AS pg 4. ON buku.id_pengarang = pg.id_pengarang



156 BAB 10 JOIN Pada MySQL



5. JOIN penerbit AS pn 6. ON buku.id_penerbit = pn.id_penerbit



Jika query tersebut dijalankan maka tidak ada baris yang bernilai NULL seperti yang terjadi pada contoh sebelumnya.



10.4. Klausa USING dan NATURAL JOIN 10.4.1. Klausa USING Pada contoh sebelumnya, kita menuliskan JOIN dengan mendefinisikan hubungan antar tabel menggunakan klausa ON, contoh pada LEFT JOIN, kita tulis query seperti berikut ini: 1. SELECT judul, nama 2. FROM buku 3. LEFT JOIN penerbit ON buku.id_penerbit = penerbit.id_penerbit



Terdapat cara lain agar penulisan menjadi lebih singkat yaitu mengganti klausa ON dengan klausa USING(kolom). Syarat menggunakan klausa USING adalah nama kolom yang digunakan pada klausa USING harus ada pada kedua tabel. Pada contoh diatas, tabel buku dan penerbit sama sama memiliki kolom id_penerbit, sehingga query diatas dapat kita ubah menjadi: 1. SELECT judul, nama 2. FROM buku 3. LEFT JOIN penerbit USING (id_penerbit);



Contoh penerapan USING pada penggabungan beberapa tabel sekaligus: 1. 2. 3. 4.



SELECT judul, pg.nama AS pengarang FROM buku LEFT JOIN pengarang AS pg USING (id_pengarang) LEFT JOIN penerbit AS pn USING (id_penerbit)



Panduan Lengkap Query MySQL 157



Setelah mengetahui manfaat klausa USING, maka ketika mendesain tabel, penting untuk memperhatikan nama field-field yang berhubungan (Primary Key dan Foreign Key), sebisa mungkin field tersebut diberi nama yang sama, sehingga akan memudahkan ketika melakukan penggabungan tabel, disamping itu, pada tabel yang kompleks pengidentifikasian field akan menjadi lebih mudah.



10.4.2. Natural JOIN Sejauh ini, ketika kita melakukan join tabel, kita harus mendefinisikan bentuk join (INNER atau OUTER JOIN) dan hubungan antar tabel yang digabungkan menggunakan klausa ON atau USING. Nah, ternyata terdapat cara yang lebih mudah, yaitu cukup mendefinisikan bentuk JOIN-nya saja, tanpa mendefinisikan hubungan antar tabel, caranya, tambahkan klausa NATURAL sebelum klausa bentuk join. Dengan klausa ini, MySQL akan otomatis mendefinisikan hubungan antar tabel dengan mencari semua field yang namanya sama yang ada pada tabel yang digabungkan. NATURAL JOIN ini dapat diterapkan untuk semua jenis JOIN baik INNER/CROSS JOIN maupun OUTER JOIN. Contoh 1: Penerapan pada OUTER JOIN. Pada contoh kali ini, kita gabungkan tabel buku dengan tabel penulis dengan menambahkan klausa NATURAL sebelum klausa LEFT JOIN atau RIGHT JOIN 1. SELECT judul, nama 2. FROM buku 3. NATURAL LEFT JOIN pengarang



Hasil yang kita peroleh sama, yaitu: +------------------------------------------+----------------------+ | judul | nama | +------------------------------------------+----------------------+ | Pemrograman Database Menggunakan MySQL | R. H. Sianipar | | PHP dan MySQL Langkah Demi Langkah + CD | R. H. Sianipar | | MySQL Untuk Pemula | Jubilee Enterprise | | Kumpulan Aplikasi PHP untuk Pemula | Jubilee Enterprise | | Pemrograman PHP Dan MySQL Untuk Pemula | Madcoms | | ... | ... | +------------------------------------------+----------------------+



158 BAB 10 JOIN Pada MySQL



Contoh 2 Penerapan pada OUTER JOIN. Pada contoh ini kita akan menggabungkan tabel buku dan tabel pengarang dengan menambahkan klausa NATURAL sebelum klausa JOIN 1. SELECT judul, nama 2. FROM buku 3. NATURAL JOIN pengarang



Hasilnya sama seperti contoh sebelumnya: +------------------------------------------+----------------------+ | judul | nama | +------------------------------------------+----------------------+ | Pemrograman Database Menggunakan MySQL | R. H. Sianipar | | PHP dan MySQL Langkah Demi Langkah + CD | R. H. Sianipar | | MySQL Untuk Pemula | Jubilee Enterprise | | Kumpulan Aplikasi PHP untuk Pemula | Jubilee Enterprise | | Pemrograman PHP Dan MySQL Untuk Pemula | Madcoms | | ... | ... | +------------------------------------------+----------------------+



Contoh 3 Penerapan pada OUTER JOIN dengan lebih dari satu tabel. Contoh kali ini kita akan menggabungkan tabel buku, pengarang, dan penerbit menggunakan NATURAL JOIN 1. 2. 3. 4. 5.



SELECT judul, pn.nama AS nama_penerbit , pg.nama AS nama_pengarang FROM buku NATURAL LEFT JOIN pengarang pg NATURAL LEFT JOIN penerbit pn



Hasil : +------------------------------------------+---------------+--------------------+ | judul | nama_penerbit | nama_pengarang | +------------------------------------------+---------------+--------------------+ | Pemrograman Database Menggunakan MySQL | NULL | R. H. Sianipar | | PHP dan MySQL Langkah Demi Langkah + CD | NULL | R. H. Sianipar | | MySQL Untuk Pemula | NULL | Jubilee Enterprise | | Kumpulan Aplikasi PHP untuk Pemula | NULL | Jubilee Enterprise | | Pemrograman PHP Dan MySQL Untuk Pemula | NULL | Madcoms | | ... | NULL | ... | +------------------------------------------+---------------+--------------------+



Perhatikan bahwa pada kolom nama_penerbit, semua data bernilai NULL, hal ini disebabkan karena pada tabel penerbit dan buku sama sama Panduan Lengkap Query MySQL 159



memiliki kolom id_penerbit dan url, sehingga karena tidak ada data url yang sama antara tabel buku dan tabel penerbit, maka tidak ada data penerbit yang cocok dengan data buku. Hati hati ketika menggunakan NATURAL JOIN, pastikan bahwa nama kolom yang sama benar benar menjadi penghubung kedua tabel, jika tidak, maka kita akan memperoleh hasil yang tidak diharapkan, seperti pada contoh 3



10.5. Pendefinisian Tabel dan Penggunaan Alias Seperti telah kita bahas pada BAB 4, bahwa kita dapat menyertakan nama tabel ketika menuliskan nama kolom pada query SELECT. Penyertaan nama tabel ini sifatnya optional, namun ketika tabel yang ingin kita gabungkan memiliki nama field yang sama, maka nama tabel wajib untuk disertakan. Contoh kita akan menampilkan data buku, penerbit, dan url dari buku tersebut, untuk itu gabungkan tabel buku dan tabel penerbit. Sejauh yang telah kita pelajari, maka query yang akan kita jalankan adalah: 1. SELECT judul, nama, url 2. FROM buku 3. LEFT JOIN penerbit USING (id_penerbit)



Namun ketika kita jalankan, kita akan mendapatkan pesan error sebagai berikut: #1052 - Column 'url' in field list is ambiguous



Pesan error tersebut disebabkan karena MySQL tidak tahu field url pada tabel mana yang harus digunakan, tabel buku atau tabel penerbit. Untuk itu kita harus mendefinisikan nama tabel pada field url tersebut. Mari kita ubah querynya menjadi:



160 BAB 10 JOIN Pada MySQL



1. SELECT judul, nama, buku.url 2. FROM buku 3. LEFT JOIN penerbit USING (id_penerbit)



Maka hasil yang kita peroleh: +-------------------------+-----------------+------------------------------+ | judul | nama | url | +-------------------------+-----------------+------------------------------+ | Pemrograman Database ...| Andi Publisher | http://andipublisher.com/p...| | PHP dan MySQL Langkah...| Andi Publisher | http://andipublisher.com/p...| | MySQL Untuk Pemula ...| Jubilee | http://thinkjubilee.com/sh...| | Kumpulan Aplikasi PHP...| Jubilee | http://thinkjubilee.com/sh...| | Pemrograman PHP Dan M...| Andi Publisher | http://andipublisher.com/p...| +-------------------------+-----------------+------------------------------+



Catatan: Setiap kali kita menemukan pesan error yang mengandung kata ambiguous, maka dapat dipastikan terdapat nama field yang sama. Nama yang sama ini tidak hanya berlaku pada field, namun juga untuk nama tabel, seperti ketika melakukan query pada dua tabel dengan nama yang sama, pada database berbeda Ketika tabel yang digabungkan kompleks, misal melibatkan banyak kolom dan banyak tabel atau bahkan melibatkan lebih dari satu database, maka untuk menyederhanakan dan memudahkan, kita dapat menggunakan alias, yaitu menggunakan keyword AS. Alias ini dapat diterapkan baik untuk kolom, tabel, maupun database, penggunaan alias ini juga telah dibahas pada BAB 4.



10.6. Self Join Ketika kita menjalankan query join, kita dapat menggabungkan tabel yang sama dalam satu query atau sering disebut dengan istilah self join. Misal kita memiliki tabel buku_ref yang didalamnya terdapat kolom referensi yang berisi ID buku tertentu. Bentuk tabel seperti berikut ini: +---------+-----------------------------------------+------------+-----------+ | id_buku | judul | tgl_terbit | referensi | +---------+-----------------------------------------+------------+-----------+ | 1 | Pemrograman Database Menggunakan MySQL | 2016-00-00 | 3 |



Panduan Lengkap Query MySQL 161



| 2 | PHP dan MySQL Langkah Demi Langkah + CD | 2016-00-00 | 4 | | 3 | MySQL Untuk Pemula | 2014-11-28 | 1 | | 4 | Kumpulan Aplikasi PHP untuk Pemula | 2016-02-25 | 2 | | 5 | Mahir Dalam 7 Hari: Coreldraw X6 | 2013-00-00 | 0 | +---------+-----------------------------------------+------------+-----------+



Selanjutnya, kita akan menampilkan judul buku utama dan judul buku referensi, query yang kita gunakan: 1. SELECT buku_ref.judul, bk_ref.judul as judul_ref 2. FROM buku_ref 3. LEFT JOIN buku_ref AS bk_ref 4. ON buku_ref.id_buku = bk_ref.referensi



Hasil yang kita peroleh adalah: +-----------------------------------------+-----------------------------------------+ | judul | judul_ref | +-----------------------------------------+-----------------------------------------+ | MySQL Untuk Pemula | Pemrograman Database Menggunakan MySQL | | Kumpulan Aplikasi PHP untuk Pemula | PHP dan MySQL Langkah Demi Langkah + CD | | Pemrograman Database Menggunakan MySQL | MySQL Untuk Pemula | | PHP dan MySQL Langkah Demi Langkah + CD | Kumpulan Aplikasi PHP untuk Pemula | | Mahir Dalam 7 Hari: Coreldraw X6 | NULL | +-----------------------------------------+-----------------------------------------+



Pada contoh diatas, terdapat judul_ref yang bernilai NULL, hal ini karena nilai pada kolom referensi tidak ada pada kolom id_buku.



10.7. Join Dengan Kondisi Tertentu Ketika menggabungkan tabel menggunakan klausa JOIN, kita dapat memfilter data yang ingin ditampilkan sesuai dengan kondisi yang kita inginkan. Misal kita ingin menampilkan data buku beserta penerbitnya dengan kriteria: (1) judul buku mengandung kata kata MySQL dan (2) buku diterbitkan oleh Andi Publisher. Selain itu kita batasi jumlah yang ditampilkan sebanyak 3 row. Query yang kita jalankan: 1. 2. 3. 4. 5.



SELECT judul, nama AS nama_penerbit FROM buku LEFT JOIN penerbit USING (id_penerbit) WHERE judul LIKE "%mysql%" AND nama LIKE "%andi%" LIMIT 3



162 BAB 10 JOIN Pada MySQL



Hasil yang kita peroleh adalah: +-----------------------------------------+----------------+ | judul | nama_penerbit | +-----------------------------------------+----------------+ | Pemrograman Database Menggunakan MySQL | Andi Publisher | | PHP dan MySQL Langkah Demi Langkah + CD | Andi Publisher | | Pemrograman PHP Dan MySQL Untuk Pemula | Andi Publisher | +-----------------------------------------+----------------+



Sampai sejauh ini, hasil yang kita peroleh sesuai dengan yang kita harapkan, namun kita perlu berhati hati, terkadang, untuk alasan kesederhanaan, kondisi yang seharusnya berada pada klausa WHERE, kita definisikan pada pada klausa ON. Hal ini terkadang menghasilkan output yang tidak diharapkan, untuk itu, sebaiknya hindari penggunaan cara tersebut. Perhatikan beberapa contoh berikut Contoh 1: Penerapan pada OUTER JOIN. Sebagai contoh, kita tampilkan data judul beserta nama penerbitnya dengan kriteria nama penerbit tidak mengandung kata andi. Jalankan query berikut: 1. SELECT judul, nama AS nama_penerbit 2. FROM buku 3. LEFT JOIN penerbit 4. ON buku.id_penerbit = penerbit.id_penerbit 5. AND nama LIKE "%andi%"



Hasil: +-------------------------------------------+----------------+ | judul | nama_penerbit | +-------------------------------------------+----------------+ | Pemrograman Database Menggunakan MySQL | Andi Publisher | | PHP dan MySQL Langkah Demi Langkah + CD | Andi Publisher | | MySQL Untuk Pemula | NULL | | Kumpulan Aplikasi PHP untuk Pemula | NULL | | Pemrograman PHP Dan MySQL Untuk Pemula | Andi Publisher | | ... | ... | +-------------------------------------------+----------------+



Pada contoh diatas, MySQL akan menampilkan semua data tabel yang ada di sebelah kiri, yaitu tabel buku sedangkan untuk kolom penerbit, MySQL



Panduan Lengkap Query MySQL 163



akan menampilkan data penerbit yang mengandung kata andi, jika tidak menemukannya maka MySQL akan menampilkan NULL Hal tersebut dikarenakan pada OUTER JOIN, yang pada contoh ini LEFT JOIN, MySQL akan menampilkan semua data tabel yang ada di sebelah kiri (tabel buku - yang ada pada klausa FROM), sedangkan untuk data yang ada pada tabel di sebelah kanan (penerbit) MySQL akan memfilternya menggunakan kondisi pada klausa ON Contoh 2: Penerapan pada INNER JOIN. Selanjutnya kita gabungkan kedua tabel menggunakan model INNER JOIN, jalankan query berikut: 1. SELECT judul, nama AS nama_penerbit 2. FROM buku 3. JOIN penerbit 4. ON buku.id_penerbit = penerbit.id_penerbit 5. AND nama NOT LIKE "%andi%"



Hasil yang kita peroleh adalah: +----------------------------------------------+---------------------------+ | judul | nama_penerbit | +----------------------------------------------+---------------------------+ | MySQL Untuk Pemula | Jubilee | | Kumpulan Aplikasi PHP untuk Pemula | Jubilee | | Blogger untuk Pemula | PT. Elex Media Komputindo | | Ide Bisnis Bermodal Blog | PT. Elex Media Komputindo | | Jago Wordpress | PT. Elex Media Komputindo | | Desain Grafis dengan Powerpoint | Jubilee | | Otodidak Membuat Blog dengan Blogger | Jubilee | | Buku Sakti Wordpress | PT. Elex Media Komputindo | | Database Systems + CD | PT. Elex Media Komputindo | | Trik Kolaborasi ANDROID dengan PHP dan MySQL | Lokomedia | | Cara Efektif Belajar Framework Laravel | Lokomedia | +----------------------------------------------+---------------------------+



Pada contoh diatas, hasil yang kita peroleh sesuai dengan apa yang kita harapkan. Hal ini disebabkan karena pada INNER JOIN, MySQL hanya akan menampilkan data yang sesuai dengan kondisi pada klausa ON



164 BAB 10 JOIN Pada MySQL



Dengan cara kerja seperti diatas, maka sebaiknya kita tidak menyatakan kondisi pada klausa ON melainkan pada klausa WHERE, karena selain hasil yang kita peroleh akan selalu konsisten, alur query juga dapat dipahami dengan mudah. Contoh 3: Gabungan INNER JOIN dan OUTER JOIN. Selanjutnya, mari kita lanjutkan contoh query diatas dengan mendefinisikan kondisi pada klausa WHERE. Jalankan query outer join berikut ini 1. 2. 3. 4.



SELECT judul, nama AS nama_penerbit FROM buku LEFT JOIN penerbit ON buku.id_penerbit = penerbit.id_penerbit WHERE nama LIKE "%andi%"



dan query inner join berikut ini: 1. 2. 3. 4.



SELECT judul, nama AS nama_penerbit FROM buku JOIN penerbit ON buku.id_penerbit = penerbit.id_penerbit WHERE nama LIKE "%andi%"



Hasil yang kita peroleh akan sama yaitu +-------------------------------------------------------+----------------+ | judul | nama_penerbit | +-------------------------------------------------------+----------------+ | Pemrograman Database Menggunakan MySQL | Andi Publisher | | PHP dan MySQL Langkah Demi Langkah + CD | Andi Publisher | | Pemrograman PHP Dan MySQL Untuk Pemula | Andi Publisher | | Pemrograman Stored Procedure Pada MySQL + cd | Andi Publisher | | Mahir Dalam 7 Hari: Coreldraw X6 | Andi Publisher | | Mudah Menggunakan Internet Untuk Pemula | Andi Publisher | | From Zero To A Pro: Java Script Dan jQuery | Andi Publisher | | From Zero To A Pro: Pemrograman Aplikasi Android + cd | Andi Publisher | | Belajar Sendiri Pasti Bisa CSS3 + cd | Andi Publisher | +-------------------------------------------------------+----------------+



Kedua query diatas menghasilkan output yang sama dikarenakan pada klausa WHERE, MYSQL akan menyimpan tabel hasil query ke dalam temporary tabel kemudian memfilter tabel tersebut sesuai kondisi pada klausa WHERE baru kemudian menampilkan hasilnya. Panduan Lengkap Query MySQL 165



10.8. Implisit JOIN Pada pembahasan diatas, kita selalu menggunakan kata-kata JOIN untuk menggabungkan tabel. Karena tertulis dengan jelas, maka join model ini disebut juga dengan eksplisit JOIN. Pada SQL, terdapat model lain untuk menjalankan query antar tabel yaitu yang disebut implisit join. Disebut implisit join karena hubungan antar tabel tidak didefinisikan dengan jelas, melainkan hanya dinyatakan dengan kondisi pada klausa where. Contoh kita tampilkan data judul dan data penerbit menggunakan model implisit join 1. SELECT judul, nama_penerbit 2. FROM buku, penerbit 3. WHERE buku.id_penerbit = penerbit.id_penerbit



Pada contoh diatas terlihat bahwa implisit join dilakukan dengan menghubungkan kolom yang sama di dalam klausa WHERE. Jika kita ubah menjadi eksplisit join, maka bentuk query akan menjadi seperti berikut ini: 1. SELECT judul, nama_penerbit 2. FROM buku 3. JOIN penerbit ON buku.id_penerbit = penerbit.id_penerbit



Kedua query diatas menghasilkan output yang sama. Pada model implisit join, kita hanya bisa melakukan INNER JOIN (seperti pada query diatas) dan tidak bisa melakukan OUTER JOIN seperti pada model eksplisit join. THETA Style dan ANSI Style Model implisit join ini juga sering disebut dengan istilah THETA STYLE sedangkan model eksplisit join disebut juga ANSI STYLE. Model THEA STYLE dibuat ketika awal standar SQL dibuat (sebelum versi 2), setelah muncul standar SQL versi 2.0, mulailah digunakan klausa JOIN. 166 BAB 10 JOIN Pada MySQL



Pada buku ini, kita selalu menggunakan model ANSI STYLE, karena dengan model ini, hubungan antar tabel dapat diidentifikasi dengan jelas sehingga lebih mudah untuk dipahami dan lebih mudah untuk diperbaiki terutama jika query yang kita buat kompleks.



Panduan Lengkap Query MySQL 167



Halaman ini sengaja dikosongkan Jagowebdev.com



168 BAB 10 JOIN Pada MySQL



BAB 11 Manipulasi Data: INSERT, UPDATE, dan DELETE Pada BAB ini kita akan membahas berbagai statemen SQL untuk memanipulasi data pada tabel baik menambahkan (INSERT), mengubah (UPDATE), dan menghapus (DELETE). Statemen SQL untuk memanipulasi data ini disebut Data Manipulation Language (DML)



11.1. Menambahkan Data Untuk menambahkan data, kita gunakan statement INSERT. Format penulisannya adalah: INSERT INTO nama_tabel (daftar_kolom) VALUES (daftar_nilai)



Terdapat dua cara mendefinisikan statemen INSERT, yaitu dengan mendefinisikan daftar_kolom yang ingin ditambahkan datanya atau tanpa mendefinisikannya.



11.1.1. Mendefinisikan Nama Kolom Contoh: misal kita memiliki tabel penjualan dengan struktur tabel sebagai berikut: 1. CREATE TABLE `penjualan` ( 2. `id_trx` INT(11) NOT NULL AUTO_INCREMENT, 3. `id_pelanggan` INT(11) NOT NULL, 4. `tgl_trx` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, 5. `total_trx` INT(11) NOT NULL, 6. PRIMARY KEY (`id_trx`) 7. )



Selanjutnya kita masukkan data ke dalam tabel tersebut:



Panduan Lengkap Query MySQL 169



mysql> INSERT INTO penjualan (id_pelanggan, tgl_trx, total_trx) VALUES (1, '2017-03-05 16:55:10', 150000); Query OK, 1 row affected (0.08 sec)



Mari kita tes hasilnya: mysql> SELECT * FROM penjualan; +--------+--------------+---------------------+-----------+ | id_trx | id_pelanggan | tgl_trx | total_trx | +--------+--------------+---------------------+-----------+ | 1 | 1 | 2017-03-05 16:55:10 | 150000 | +--------+--------------+---------------------+-----------+ 2 rows in set (0.00 sec)



Pada contoh diatas, kita memasukkan data dengan mendefinisikan nama kolom, yaitu id_pelanggan, tgl_trx, dan total_trx, kita tidak mendefinisikan kolom id_trx karena kolom tersebut memiliki atribut AUTO_INCREMENT dimana data pada kolom tersebut akan otomatis diisi oleh MySQL dengan nilai integer mulai dari 1. Dengan mendefinisikan nama kolom, query lebih mudah dipahami dan lebih fleksibel, karena kita tahu kolom apa yang akan diisi datanya, disamping itu, metode ini juga tidak memperhatikan urutan kolom, sehingga jika struktur tabel berubah, misal urutan kolom berubah atau ada penambahan kolom, statemen INSERT yang telah kita buat tidak perlu diubah. Adapun kelemahan metode ini adalah kita harus mengetahui nama kolom pada tabel.



11.1.2. Tanpa Mendefinisikan Nama Kolom Cara lain memasukkan data ke tabel dengan statemen INSERT adalah tanpa mendefinisikan nama kolom, format penulisannya adalah INSERT INTO nama_tabel VALUES (daftar_nilai)



Contoh: kita masukkan data ke semua kolom pada tabel penjualan



170 BAB 11 Manipulasi Data: INSERT, UPDATE, dan DELETE



mysql> INSERT INTO penjualan VALUES (LAST_INSERT_ID() + 1, 2, '2017-03-10', 125000); Query OK, 1 row affected (0.08 sec)



Hasilnya adalah: mysql> SELECT * FROM penjualan; +--------+--------------+---------------------+-----------+ | id_trx | id_pelanggan | tgl_trx | total_trx | +--------+--------------+---------------------+-----------+ | 1 | 1 | 2017-03-05 16:55:10 | 150000 | | 2 | 1 | 2017-03-14 17:01:02 | 150000 | | 3 | 1 | 2017-03-14 17:01:15 | 135000 | | 4 | 2 | 2017-03-14 00:00:00 | 125000 | +--------+--------------+---------------------+-----------+ 4 rows in set (0.00 sec)



Pada contoh diatas, data pada klausa VALUES akan dimasukkan sesuai dengan urutan kolom. Perhatikan bahwa pada contoh diatas, kita menggunakan fungsi LAST_INSERT_ID(). Fungsi ini bermanfaat untuk mengambil nilai terakhir dari AUTO_INCREMENT yang terakhir dimasukkan, dalam contoh ini adalah 3, kemudian nilai tersebut kita tambahkan 1 menjadi 4. Keuntungan menggunakan metode ini adalah kita tidak perlu mengingat nama tiap-tiap kolom, kita hanya perlu mengetahui urutannya saja. Namun demikian, metode ini memiliki kelemahan yaitu: 1. Agar data yang dimasukkan sesuai dengan kolom yang ada, kita harus ingat urutan kolom. 2. Harus mendefinisikan data untuk semua kolom, jika ada satu saja yang terlewat, maka akan terjadi error. 3. Terikat dengan struktur tabel, jika strukturnya berubah, misal urutan kolom atau ada penambahan kolom, maka kita harus mengubah statement INSERT yang telah kita buat. Penting diperhatikan bahwa ketika menggunakan metode ini, maka semua kolom harus diberi nilai, meskipun kolom tersebut memiliki atribut default



Panduan Lengkap Query MySQL 171



value, atau dengan kata lain jumlah data pada VALUES harus sama dengan jumlah kolom. Jika tidak, maka akan muncul pesan error: mysql> INSERT INTO penjualan VALUES (11, '2017-03-10', 125000); ERROR 1136 (21S01): Column count doesn't match value count at row 1



Error tersebut dikarenakan tabel penjualan memiliki 4 kolom, sedangkan data yang akan dimasukkan hanya untuk 3 kolom.



11.1.3. Kolom Dengan Nilai Default Setiap kolom yang tidak kita definisikan akan diisi dengan nilai default nya, misal pada tabel diatas, kita beri atribut DEFAULT pada kolom tgl_trx dengan nilai CURRENT_TIMESTAMP yang artinya waktu sekarang (waktu data di masukkan), misal: mysql> INSERT INTO penjualan (id_pelanggan, total_trx) VALUES (1, 150000); Query OK, 1 row affected (0.04 sec) mysql> SELECT * FROM penjualan; +--------+--------------+---------------------+-----------+ | id_trx | id_pelanggan | tgl_trx | total_trx | +--------+--------------+---------------------+-----------+ | 1 | 1 | 2017-03-05 16:55:10 | 150000 | | 2 | 1 | 2017-03-14 17:01:02 | 150000 | +--------+--------------+---------------------+-----------+ 2 rows in set (0.00 sec)



Pada contoh diatas, 2017-03-14 dimasukkan.



17:01:02 merupakan waktu data



Jika kolom memiliki constraint NOT NULL dan tidak memiliki nilai default maka jika tidak didefinisikan, akan muncul pesan error Contoh query tanpa nilai default: mysql> INSERT INTO penjualan (total_trx) VALUES (175000);



172 BAB 11 Manipulasi Data: INSERT, UPDATE, dan DELETE



ERROR 1364 (HY000): Field 'id_pelanggan' doesn't have a default value



Error diatas terjadi karena kolom total_trx memiliki atribut NOT NULL tetapi tidak memiliki nilai default. Selain tidak mendefinisikan nama kolom, nilai default juga dapat diperoleh dengan memberi klausa DEFAULT pada VALUES, misal: mysql> INSERT INTO penjualan (id_pelanggan, tgl_trx, total_trx) VALUES (1, DEFAULT, 135000); Query OK, 1 row affected (0.16 sec) mysql> SELECT * FROM penjualan; +--------+--------------+---------------------+-----------+ | id_trx | id_pelanggan | tgl_trx | total_trx | +--------+--------------+---------------------+-----------+ | 1 | 1 | 2017-03-05 16:55:10 | 150000 | | 2 | 1 | 2017-03-14 17:01:02 | 150000 | | 3 | 1 | 2017-03-14 17:01:15 | 135000 | +--------+--------------+---------------------+-----------+ 9 rows in set (0.10 sec)



Pada contoh diatas, klausa DEFAULT menghasilkan CURRENT_TIMESTAMP ( 2017-03-14 17:01:15 ) yang merupakan nilai atribut default pada kolom tgl_trx



11.1.4. Memasukkan Data Turunan Pada kondisi tertentu, data yang akan kita masukkan merupakan data hasil olahan, baik itu fungsi agregasi maupun hasil dari query lain. Misal data pada tabel penjualan akan kita masukkan ke tabel penjualan_rekap yang berisi data hasil rekap penjualan harian. Adapun struktur dari tabel penjualan_rekap adalah adalah sebagai berikut: 1. CREATE TABLE `penjualan_rekap` ( 2. `id_rekap` INT(11) NOT NULL AUTO_INCREMENT, 3. `tgl_trx` DATE NULL DEFAULT NULL, 4. `tgl_rekap` DATETIME NULL DEFAULT CURRENT_TIMESTAMP, 5. `total_trx` INT(11) NULL DEFAULT NULL, 6. PRIMARY KEY (`id_trx`)



Panduan Lengkap Query MySQL 173



7. )



Sedangkan data pada tabel penjualan adalah: mysql> SELECT * FROM penjualan; +--------+--------------+---------------------+-----------+ | id_trx | id_pelanggan | tgl_trx | total_trx | +--------+--------------+---------------------+-----------+ | 1 | 1 | 2017-03-05 16:55:10 | 150000 | | 2 | 1 | 2017-03-14 17:01:02 | 150000 | | 3 | 1 | 2017-03-14 17:01:15 | 135000 | | 4 | 2 | 2017-03-14 00:00:00 | 125000 | +--------+--------------+---------------------+-----------+ 4 rows in set (0.00 sec)



Selanjutnya mari kita masukkan data ke tabel penjualan_rekap. Jalankan perintah berikut: 1. INSERT INTO penjualan_rekap (tgl_trx, total_trx) 2. VALUES ('2017-03-14', ( SELECT SUM(total_trx) 3. FROM penjualan 4. WHERE DATE(tgl_trx) = '2017-03-14' 5. ) 6. );



Cek hasilnya: mysql> SELECT * FROM penjualan_rekap; +----------+------------+---------------------+-----------+ | id_rekap | tgl_trx | tgl_rekap | total_trx | +----------+------------+---------------------+-----------+ | 1 | 2017-03-14 | 2017-03-14 17:35:37 | 410000 | +----------+------------+---------------------+-----------+ 1 row in set (0.00 sec)



Pada contoh diatas, nilai total_trx merupakan hasil dari penjumlahan (fungsi SUM()) kolom total_trx yang ada pada tabel penjualan yang terjadi tanggal 2017-03-14, yaitu 150000 + 135000 + 125000 = 410000 Pada contoh diatas, kita memasukkan data dengan mendefinisikan nama kolom, jika kita tidak mendefinisikan nama kolom, maka format query nya



174 BAB 11 Manipulasi Data: INSERT, UPDATE, dan DELETE



agak sedikit berbeda, dimana kita tidak menuliskan klausa VALUES, format penulisannya adalah: INSERT INTO nama_tabel SELECT...



Melanjutkan contoh sebelumnya, mari kita masukkan data tanpa mendefinisikan nama kolom. Query yang kita jalankan adalah: 1. 2. 3. 4.



INSERT INTO penjualan_rekap SELECT LAST_INSERT_ID(), '2017-03-05', NOW(), SUM(total_trx) FROM penjualan WHERE DATE(tgl_trx) = '2017-03-05'



Hasil yang kita peroleh: mysql> SELECT * FROM penjualan_rekap; +----------+------------+---------------------+-----------+ | id_rekap | tgl_trx | tgl_rekap | total_trx | +----------+------------+---------------------+-----------+ | 1 | 2017-03-14 | 2017-03-14 17:35:37 | 600000 | | 2 | 2017-03-05 | 2017-03-14 17:48:41 | 150000 | +----------+------------+---------------------+-----------+ 2 rows in set (0.00 sec)



Pada contoh diatas, fungsi NOW() akan menghasilkan waktu sekarang, yaitu 2017-03-14 17:48:41



Pada kedua contoh diatas, data diperoleh dari hasil query pada tabel lain. Perlu diperhatikan bahwa, kita tidak bisa menggunakan data pada tabel yang akan dimasukkan datanya, misal, kita akan menambahkan data pada tabel penjualan_rekap dengan hasil akhir sebagai berikut: +----------+------------+---------------------+-----------+ | id_rekap | tgl_trx | tgl_rekap | total_trx | +----------+------------+---------------------+-----------+ | 1 | 2017-03-14 | 2017-03-14 17:35:37 | 410000 | | 2 | 2017-03-05 | 2017-03-14 17:48:41 | 150000 | | 3 | 2017-03-12 | 2017-03-14 17:48:41 | 150000 | +----------+------------+---------------------+-----------+



Query yang dijalankan adalah:



Panduan Lengkap Query MySQL 175



1. INSERT INTO penjualan_rekap VALUES ( 2. ( SELECT MAX(id_rekap) + 1 3. FROM penjualan_rekap) 4. , '2017-03-12' 5. , NOW() 6. , 150000 7. );



Ketika menjalankan perintah tersebut, kita akan mendapatkan pesan error: SQL Error (1093): You can't specify target table 'penjualan_rekap' for update in FROM clause



11.1.5. Memasukkan Banyak Data Dengan Satu Statemen Untuk memasukan data lebih dari satu baris, kita dapat menggabungkannya menjadi satu statement. Cara ini lebih efisien dan hemat resource dari pada menjalankan banyak statemen INSERT. Adapun format penulisannya adalah: INSERT INTO nama_tabel (kolom1, kolom2, kolom3) VALUES (value1, value2, value3), (value1, value2, value3), dst...



Contoh kita tambahkan beberapa data pada tabel penjualan: 1. INSERT INTO penjualan (id_pelanggan, tgl_trx, total_trx) 2. VALUES (2, DEFAULT, 100000) 3. ,(2, DEFAULT, 250000) 4. ,(3, DEFAULT, 125000)



Hasilnya: mysql> SELECT * FROM penjualan; +--------+--------------+---------------------+-----------+ | id_trx | id_pelanggan | tgl_trx | total_trx | +--------+--------------+---------------------+-----------+ | 1 | 1 | 2017-03-05 16:55:10 | 150000 | | 2 | 1 | 2017-03-14 17:48:41 | 150000 | | 3 | 1 | 2017-03-14 17:48:41 | 135000 | | 4 | 2 | 2017-03-10 00:00:00 | 125000 |



176 BAB 11 Manipulasi Data: INSERT, UPDATE, dan DELETE



| 5 | 2 | 2017-03-14 18:32:22 | 100000 | | 6 | 2 | 2017-03-14 18:32:22 | 250000 | | 7 | 3 | 2017-03-14 18:32:22 | 125000 | +--------+--------------+---------------------+-----------+ 7 rows in set (0.00 sec)



Ketika memasukkan data dalam jumlah besar dan terjadi error, maka data sebelumnya tetap masuk, misal, pada contoh diatas, ketika terjadi error pada data ke tiga, maka data pertama dan kedua tetap masuk. Untuk memastikan semua data berhasil dimasukkan atau tidak sama sekali, gunakan Transaksi yang dibahas pada BAB 24 Transaksi Sama seperti ketika memasukkan data, kita juga dapat memasukkan banyak data tanpa mendefinisikan nama kolom, formatnya juga sama yaitu: INSERT INTO nama_tabel VALUES (value1, value2, value3), (value1, value2, value3), dst...



Statemen ini sangat bermanfaat terutama ketika kita menggunakan bahas pemrograman lain untuk menjalankan query MySQL. Penting diperhatikan bahwa ketika kita memasukkan data dalam jumlah besar, maka kita harus membagi data ke beberapa statemen INSERT misal setiap 3000 data, jika tidak maka, server MySQL akan hang dan data gagal dimasukkan



11.1.6. Alternatif Syntax Selain yang telah kita bahas diatas, kita juga dapat menjalankan statemen INSERT menggunakan klausa SET, misal: mysql> INSERT INTO penjualan -> SET id_pelanggan = 3, tgl_trx = DEFAULT, total_trx = 115000; Query OK, 1 row affected (0.14 sec)



Panduan Lengkap Query MySQL 177



Model syntax diatas mensyaratkan kita untuk mendefinisikan nama kolom beserta nilainya, keuntungan menggunakan model ini adalah kita tahu persis data apa yang akan dimasukkan pada kolom, karena data tersebut disandingkan langsung dengan nama kolom. Selain itu, syntax ini mirip dengan syntax pada statemen UPDATE, sehingga, ketika menggunakannya pada aplikasi lain, seperti PHP akan memudahkan pembuatan logika programnya. Kelemahan model ini adalah kita bisa saja melewatkan kolom tertentu yang tidak memiliki nilai default, disamping itu kita tidak dapat menggunakan model ini untuk memasukkan data lebih dari satu baris.



11.1.7. Pembatasan Panjang Data Ketika memasukkan data pada tabel, terdapat beberapa hal yang perlu diperhatikan terutama terkait dengan tipe data yang ada pada tiap kolom: 



Pada kolom dengan tipe data numeric, jika data yang dimasukkan melebihi batas maksimal nilai dari tipe data yang digunakan, maka akan digunakan nilai maksimal dari tipe data tersebut. Misal kolom dengan tipe data TINYINT, dimana batas maksimalnya adalah 124, maka ketika diisi dengan 250, nilai yang masuk adalah 124.







Pada kolom dengan tipe data karakter, jika data yang dimasukkan melebihi batas maksimal nilai dari tipe data yang digunakan, maka teks akan terpotong. Misal kolom dengan tipe data CHAR(5), ketika diisi dengan string 'jakarta', maka yang masuk adalah 'jakar'. Hal in juga berlaku untuk tipe data text yang dapat menampung maksimal 65.535 karakter.







Jika tipe data kolom adalah numeric, maka jika kita tidak bisa memasukkan data kombinasi numeric dan non numeric, seperti '17a', jika tidak, maka akan muncul pesan error: mysql> INSERT INTO `penjualan_rekap` VALUES ('1', '2017-0122', '2017-01-22', '17a'); ERROR 1265 (01000): Data truncated for column 'total_trx' at row 1



178 BAB 11 Manipulasi Data: INSERT, UPDATE, dan DELETE







Memasukkan tanggal yang tidak valid pada kolom dengan tipe data tanggal dan/atau waktu DATE atau DATETIME akan menghasilkan nilai o sesuai tipe datanya, 0000-00-00 untuk DATE dan 0000-00-00 00:00:00 untuk DATETIME



11.2. Statemen UPDATE Statemen UPDATE digunakan untuk mengubah satu atau lebih data pada tabel. Proses update dilakukan dengan membaca baris yang ada sesuai kriteria yang telah ditentukan. Statemen ini umumnya digunakan dengan klausa WHERE yang digunakan untuk membatasi hanya baris yang diupdate, tanpa klausa ini, semua baris akan terkena proses update. Format umum statemen UPDATE adalah: UPDATE tabel SET col1 = val1, col2 = value2 [WHERE ...] [ORDER BY ...] [LIMIT ...]



Catatan: Klausa WHERE, ORDER BY, dan LIMIT sifatnya opsional



11.2.1. UPDATE Semua Baris Untuk mengupdate semua baris, kita tidak perlu menggunakan klausa WHERE. Contoh kali ini kita akan mengubah nama pada tabel pelanggan. Data pada tabel pelanggan adalah sebagai berikut: mysql> SELECT * FROM pelanggan; +--------------+---------+------------+ | id_pelanggan | nama | alamat | +--------------+---------+------------+ | 1 | Alfa | Jakarta | | 2 | Beta | Semarang | | 3 | Charlie | Surakarta | | 4 | Delta | Yogyakarta | +--------------+---------+------------+ 4 rows in set (0.03 sec)



Kita ubah nama menjadi huruf kapital semua: Panduan Lengkap Query MySQL 179



mysql> UPDATE pelanggan SET nama = UPPER(nama); Query OK, 4 rows affected (0.35 sec) Rows matched: 4 Changed: 4 Warnings: 0



Fungsi UPPER() digunakan untuk mengubah string menjadi huruf kapital. Pada informasi hasil query, terlihat bahwa query cocok dengan keseluruhan baris ( matched: 4 ) hal ini karena kita tidak menggunakan klausa WHERE atau LIMIT untuk membatasi data yang diupdate, selanjutnya, Changed: 4 berarti bahwa kolom nama pada semua baris mengalami perubahan. Jika kita jalankan kembali statemen yang sama, maka kita akan memperoleh hasil sebagai berikut: mysql> UPDATE pelanggan SET nama = UPPER(nama); Query OK, 0 rows affected (0.00 sec) Rows matched: 4 Changed: 0 Warnings: 0



Dari informasi diatas terlihat bahwa query cocok pada semua baris, namun tidak ada data yang diubah, karena semua data pada kolom nama sudah berupa huruf kapital. Jika suatu kolom memiliki nilai default, maka jika kita update nilai kolom tersebut dengan nilai DEFAULT, maka nilai kolom tersebut akan berubah menjadi nilai defaultnya, misal, kita memiliki tabel penjualan dengan data sebagai berikut: mysql> SELECT * FROM penjualan; +--------+--------------+---------------------+-----------+ | id_trx | id_pelanggan | tgl_trx | total_trx | +--------+--------------+---------------------+-----------+ | 1 | 1 | 2017-03-05 16:55:10 | 150000 | | 2 | 1 | 2017-03-14 17:48:41 | 150000 | | 3 | 1 | 2017-03-14 17:48:41 | 135000 | +--------+--------------+---------------------+-----------+ 3 rows in set (0.00 sec)



Selanjutnya kita update semua kolom pada tgl_trx dengan memberi nilai DEFAULT



180 BAB 11 Manipulasi Data: INSERT, UPDATE, dan DELETE



mysql> UPDATE penjualan SET tgl_trx = DEFAULT; Query OK, 3 rows affected (0.08 sec) Rows matched: 3 Changed: 3 Warnings: 0 mysql> SELECT * FROM penjualan; +--------+--------------+---------------------+-----------+ | id_trx | id_pelanggan | tgl_trx | total_trx | +--------+--------------+---------------------+-----------+ | 1 | 1 | 2017-03-15 08:05:05 | 150000 | | 2 | 1 | 2017-03-15 08:05:05 | 150000 | | 3 | 1 | 2017-03-15 08:05:05 | 135000 | +--------+--------------+---------------------+-----------+ 3 rows in set (0.00 sec)



Karena kolom tgl_trx memiliki atribut DEFAULT CURRENT_TIMESTAMP, maka nilai kolom tersebut berubah menjadi waktu sekarang



11.2.2. UPDATE Baris Tertentu Untuk mengupdate hanya baris tertentu, kita gunakan klausa WHERE atau LIMIT. Misal kita update data kolom tgl_trx pada tabel penjualan sebagai berikut: mysql> UPDATE penjualan SET tgl_trx = '2017-03-05' WHERE DATE(tgl_trx) = DATE(NOW()); Query OK, 3 rows affected (0.11 sec) Rows matched: 3 Changed: 3 Warnings: 0 mysql> SELECT * FROM penjualan; +--------+--------------+---------------------+-----------+ | id_trx | id_pelanggan | tgl_trx | total_trx | +--------+--------------+---------------------+-----------+ | 1 | 1 | 2017-03-05 00:00:00 | 150000 | | 2 | 1 | 2017-03-05 00:00:00 | 95000 | | 3 | 1 | 2017-03-05 00:00:00 | 135000 | +--------+--------------+---------------------+-----------+ 3 rows in set (0.00 sec)



Query diatas mengubah data kolom tgl_trx yang memiliki nilai tanggal sekarang, yaitu 2017-03-15 dengan jam berapapun, menjadi tanggal 201705-03. Fungsi DATE() berfungsi mengambil tanggal dari kolom tgl_trx, selanjutnya hasilnya dibandingkan dengan tanggal sekarang DATE(NOW()). Kebetulan semua data memiliki tanggal yang sama sehingga ketiganya diupdate. Panduan Lengkap Query MySQL 181



Dengan ORDER BY dan LIMIT, kita bisa meng-update beberapa baris berdasarkan urutan tertentu, misal kita ingin mengubah 2 baris pertama data tabel pelanggan yang diurutkan menurun berdasarkan id_pelanggan: mysql> UPDATE pelanggan SET nama = LOWER(nama) ORDER BY id_pelanggan DESC LIMIT 2; Query OK, 2 rows affected (0.07 sec) Rows matched: 2 Changed: 2 Warnings: 0 mysql> SELECT * FROM pelanggan; +--------------+---------+------------+ | id_pelanggan | nama | alamat | +--------------+---------+------------+ | 1 | ALFA | Jakarta | | 2 | BETA | Semarang | | 3 | charlie | Surakarta | | 4 | delta | Yogyakarta | +--------------+---------+------------+ 4 rows in set (0.00 sec)



Pada query diatas, MySQL akan mengurutkan data berdasarkan kolom id_pelanggan (kolom pada klausa ORDER BY) dari nilai yang paling besar (klausa DESC), kemudian, dengan klausa LIMIT, MySQL akan mengambil dua baris pertama, yaitu baris dengan id_pelanggan 4 dan 3, selanjutnya mengubah kolom nama pada baris tersebut menjadi huruf kecil.



11.2.3. UPDATE Baris Berdasarkan Nilai Pada Kolom Lain Ketika mengupdate data suatu kolom, kita dapat menggunakan nilai pada kolom lain sebagai acuan, misal, pada tabel penjualan, kita tambahkan kolom diskon yang berisi nilai diskon dan kolom total_neto yang berisi hasil perkalian kolom total_trx dan kolom diskon. ALTER TABLE `penjualan` ADD COLUMN `diskon` DECIMAL(10,2) NOT NULL AFTER `total_trx`, ADD COLUMN `total_neto` INT NOT NULL AFTER `diskon`;



Data tabel penjualan menjadi: 182 BAB 11 Manipulasi Data: INSERT, UPDATE, dan DELETE



mysql> SELECT * FROM penjualan; +--------+--------------+---------------------+-----------+--------+------------+ | id_trx | id_pelanggan | tgl_trx | total_trx | diskon | total_neto | +--------+--------------+---------------------+-----------+--------+------------+ | 1 | 1 | 2017-03-05 00:00:00 | 150000 | 0.00 | 0 | | 2 | 1 | 2017-03-05 00:00:00 | 95000 | 0.00 | 0 | | 3 | 1 | 2017-03-05 00:00:00 | 135000 | 0.00 | 0 | +--------+--------------+---------------------+-----------+--------+------------+ 3 rows in set (0.00 sec)



Selanjutnya kita update kolom diskon dengan memberi nilai 0.1 (10%) dan kita sesuaikan nilai pada kolom total_neto menjadi harga setelah diskon mysql> UPDATE penjualan SET diskon = 0.1, total_neto = total_trx (total_trx * diskon); Query OK, 3 rows affected (0.11 sec) Rows matched: 3 Changed: 3 Warnings: 0



Pada query diatas, MySQL akan memeriksa baris satu per satu. Pertama tama MySQL akan mengubah nilai pada kolom diskon menjadi 0.1, selanjutnya mengubah nilai pada kolom total_neto dengan mengalikan nilai pada kolom total_trx dengan nilai pada kolom diskon (total_trx * diskon) kemudian hasilnya dikurangkan dengan nilai pada kolom total_trx yaitu total_trx - (total_trx * diskon) Hasilnya adalah: mysql> SELECT * FROM penjualan; +--------+--------------+---------------------+-----------+--------+------------+ | id_trx | id_pelanggan | tgl_trx | total_trx | diskon | total_neto | +--------+--------------+---------------------+-----------+--------+------------+ | 1 | 1 | 2017-03-05 00:00:00 | 150000 | 0.10 | 135000 | | 2 | 1 | 2017-03-05 00:00:00 | 95000 | 0.10 | 85500 | | 3 | 1 | 2017-03-05 00:00:00 | 135000 | 0.10 | 121500 | +--------+--------------+---------------------+-----------+--------+------------+ 3 rows in set (0.00 sec)



Panduan Lengkap Query MySQL 183



11.2.4. UPDATE Baris Berdasarkan Query Tertentu Ketika menjalankan statemen UPDATE, nilai yang akan kita masukkan ke dalam suatu kolom dapat diperoleh dari output suatu query, misal kita memiliki tabel penjualan_detail dengan data sebagai berikut: mysql> SELECT * FROM penjualan_detail; +---------------+--------+-----------+------------+--------------+--------+--------+ | id_trx_detail | id_trx | id_barang | jml_barang | harga_satuan | diskon | total | +---------------+--------+-----------+------------+--------------+--------+--------+ | 1 | 2 | 9 | 1 | 250000 | 0 | 250000 | | 2 | 2 | 4 | 1 | 35000 | 0 | 35000 | | 3 | 2 | 6 | 2 | 55000 | 0 | 110000 | | 4 | 3 | 9 | 1 | 250000 | 0 | 250000 | | 5 | 3 | 10 | 2 | 55000 | 0 | 110000 | | 6 | 1 | 4 | 1 | 35000 | 0 | 35000 | +---------------+--------+-----------+------------+--------------+--------+--------+



Selanjutnya kita akan mengupdate kolom total_trx yang ada pada tabel penjualan berdasarkan nilai pada kolom total yang ada pada tabel penjualan_detail. Nilai kolom total tersebut di kelompokkan menjadi satu berdasarkan id_trx yang sama. Setelah mengupdate nilai pada kolom total_trx pada tabel penjualan, selanjutnya kita sesuaikan nilai pada kolom total_neto. Query yang kita jalankan adalah: 1. UPDATE penjualan 2. SET total_trx = ( SELECT SUM(total) 3. FROM penjualan_detail 4. WHERE id_trx = penjualan.id_trx 5. ), 6. total_neto = total_trx - ( total_trx * diskon )



Jika berhasil, maka tabel penjualan akan tampak seperti tabel berikut: mysql> SELECT * FROM penjualan; +--------+--------------+---------------------+-----------+--------+------------+ | id_trx | id_pelanggan | tgl_trx | total_trx | diskon | total_neto | +--------+--------------+---------------------+-----------+--------+------------+ | 1 | 1 | 2017-03-05 00:00:00 | 35000 | 0.10 | 31500 | | 2 | 1 | 2017-03-05 00:00:00 | 395000 | 0.10 | 355500 | | 3 | 1 | 2017-03-05 00:00:00 | 360000 | 0.10 | 324000 |



184 BAB 11 Manipulasi Data: INSERT, UPDATE, dan DELETE



+--------+--------------+---------------------+-----------+--------+------------+ 3 rows in set (0.00 sec)



Penjelasan: Pada query diatas, karena tidak ada klausa WHERE atau LIMIT, MySQL akan memeriksa satu persatu baris pada tabel penjualan, kemudian pada setiap baris yang diperiksa, MySQL akan menjalankan statemen: 1. SELECT SUM(total) 2. FROM penjualan_detail 3. WHERE id_trx = penjualan.id_trx



Ketika berada pada baris pertama, query akan berbentuk seperti ini: 1. SELECT SUM(total) 2. FROM penjualan_detail 3. WHERE id_trx = 1



yang hasilnya adalah: +------------+ | SUM(total) | +------------+ | 35000 | +------------+



Sehingga, pada baris pertama, query pada statemen UPDATE akan berbentuk: 1. UPDATE penjualan 2. SET total_trx = 35000, 3. total_neto = total_trx - ( total_trx * diskon )



Proses ini berlangsung hingga baris terakhir pada tabel penjualan.



Panduan Lengkap Query MySQL 185



Penting diperhatikan bahwa ketika mengupdate kolom dengan nilai berdasarkan hasil suatu query, maka harus dipastikan hasil query tersebut hanya terdiri dari 1 data (1 baris dan 1 kolom), jika tidak, maka akan muncul pesan error



11.3. Statemen DELETE Statemen DELETE digunakan untuk menghapus baris pada tabel. Penting diperhatikan bahwa tidak ada statemen untuk mengembalikan baris yang terhapus, seperti statemen UNDELETE atau UNDO, sehingga sekali data dihapus, maka tidak dapat dikembalikan lagi.



11.3.1.Menghapus Data Pada Tabel Pada statemen DELETE, kita dapat menggunakan klausa WHERE, ORDER BY, dan LIMIT. Ketika menjalankan statemen ini, selalu gunakan klausa WHERE, jika tidak maka semua data akan terhapus. Adapun format penulisannya adalah: DELETE FROM nama_tabel [WHERE ...] [ORDER BY ...] [LIMIT...]



Jika kita ingin menghapus baris tertentu pada suatu tabel, pastikan data yang digunakan pada klausa WHERE bernilai unik, seperti data pada kolom primary key, hal ini untuk memastikan tidak ada baris lain yang ikut terhapus. Misal pada tabel penjualan_detail terdapat data sebagai berikut: mysql> SELECT * FROM penjualan_detail; +---------------+--------+-----------+------------+--------------+--------+--------+ | id_trx_detail | id_trx | id_barang | jml_barang | harga_satuan | diskon | total | +---------------+--------+-----------+------------+--------------+--------+--------+ | 1 | 2 | 9 | 1 | 250000 | 0 | 250000 | | 2 | 2 | 4 | 1 | 35000 | 0 | 35000 | | 3 | 2 | 6 | 2 | 55000 | 0 | 110000 | | 4 | 3 | 9 | 1 | 250000 | 0 | 250000 |



186 BAB 11 Manipulasi Data: INSERT, UPDATE, dan DELETE



| 5 | 3 | 10 | 2 | 55000 | 0 | 110000 | | 6 | 1 | 4 | 1 | 35000 | 0 | 35000 | +---------------+--------+-----------+------------+--------------+--------+--------+ 6 rows in set (0.00 sec)



Selanjutnya kita hapus data dengan id_trx 2 dan id_barang 9. Query yang kita jalankan adalah: mysql> DELETE FROM penjualan_detail WHERE id_trx = 2 AND id_barang = 9; Query OK, 1 row affected (0.09 sec)



Pada query diatas, data dihapus sebanyak 1 baris ( 1 row affected )



11.3.2. Menghapus Data Lebih Dari Satu Tabel Pada kondisi tertentu, kita perlu untuk menghapus data yang ada di beberapa tabel sekaligus, sebagai contoh karena tabel penjualan merupakan hasil rekap dari tabel penjualan_detail, maka ketika kita menghapus data pada tabel penjualan_detail, kita juga harus menghapus data terkait yang ada pada tabel penjualan. Format penulisan statemen DELETE yang melibatkan banyak tabel adalah: DELETE FROM nama_tabel1, nama_tabel2 USING tabel_referensi [WHERE ...]



Pada statemen diatas, data pada tabel yang berada setelah klausa FROM dan sebelum klausa USING akan dihapus. Sebagai contoh, misal kita akan menghapus data pada tabel penjualan dan penjualan_detail yang memiliki id_trx = 2. Query yang kita jalankan adalah: 1. DELETE 2. FROM penjualan, penjualan_detail 3. USING penjualan JOIN penjualan_detail 4. WHERE penjualan.id_trx = 2 5. AND penjualan.id_trx = penjualan_detail.id_trx



Panduan Lengkap Query MySQL 187



Pada



contoh



diatas,



klausa



AND



penjualan.id_trx



=



penjualan_detail.id_trx (baris 5) harus ditulis, jika tidak, maka semua



data pada tabel penjualan_detail akan terhapus, karena pada klausa WHERE hanya terdapat kriteria penjualan.id_trx = 2 Penulisan statemen DELETE model ini memang agak rumit dan berisiko, terutama pada klausa USING dimana tabel referensi didefinisikan, untuk itu kita harus berhati hati, jika tidak yakin, kita dapat menjalankan beberapa statemen DELETE untuk masing masing tabel. Selain itu, statemen model ini juga dapat digantikan dengan penggunaan FOREIGN KEY constrain yang dibahas pada BAB 7 Constraint.



11.3.3. Menghapus Semua Baris Sebelumnya telah kita bahas bahwa jika statemen DELETE tanpa disertai klausa WHERE, maka semua baris akan dihapus, selain cara tersebut, terdapat cara lain untuk mengosongkan tabel yaitu dengan TRUNCATE TABLE yang jauh lebih cepat daripada statemen DELETE. Dengan statemen DELETE, MySQL akan menghapus baris satu per satu, sehingga memakan waktu lama terutama jika tabel tersebut berisi banyak data. Sedangkan dengan statemen TRUNCATE, MySQL akan menghapus tabel tersebut (drop) dan membuatnya kembali, sehingga waktu eksekusi menjadi lebih cepat. Selain lebih cepat dalam menghapus semua data, nilai pada kolom dengan atribut AUTO_INCREMENT akan direset menjadi 1, sehingga ketika kita masukkan data pada kolom tersebut, data yang dimasukkan bernilai 1. Hal ini tidak terjadi jika kita menggunakan statemen DELETE FROM, meskipun tabel telah kosong, nilai AUTO_INCREMENT akan tetap berlanjut dari nilai terakhir yang digunakan. Contoh penggunaan statemen TRUNCATE: misal kita akan menghapus semua data pada tabel penjualan, statemen yang kita jalankan adalah: mysql> TRUNCATE TABLE penjualan; Query OK, 0 rows affected (0.31 sec)



188 BAB 11 Manipulasi Data: INSERT, UPDATE, dan DELETE



Perhatikan bahwa pada query diatas, terdapat informasi 0 baris yang dihapus (0 rows affected). Karena proses TRUNCATE secara internal akan menghapus tabel, maka MySQL tidak menghitung jumlah baris yang ada, sehingga jumlah baris yang dihapus (biasanya 0) tidak mencerminkan jumlah baris yang dihapus. Perlu diperhatikan jika terdapat trigger yang melibatkan tabel yang ingin dikosongkan, maka statemen TRUNCATE tidak memicu trigger, sebaliknya, dengan statemen DELETE, karena penghapusan dilakukan per-baris, maka trigger akan aktif.



Panduan Lengkap Query MySQL 189



Halaman ini sengaja dikosongkan Jagowebdev.com



190 BAB 11 Manipulasi Data: INSERT, UPDATE, dan DELETE



BAB 12 Functions Seperti pada bahasa pemrograman pada umumnya, MySQL juga menyediakan berbagai fungsi yang digunakan untuk memanipulasi data, baik data yang ditampilkan ke user, maupun data yang diolah lebih lanjut. Pada BAB ini, kita akan membahas beberapa fungsi yang paling sering digunakan, diantaranya fungsi terkait karakter, angka, tanggal dan konversi nilai. Disamping itu, kita juga akan membahas tentang fungsi komposit (composite function) atau fungsi di dalam fungsi.



12.1. Mengenal Fungsi Fungsi adalah sebuah perintah dengan nama tertentu yang digunakan untuk memanipulasi data. Sebuah fungsi dapat menerima banyak nilai (argumen) tetapi banyaknya nilai yang dihasilkan selalu tunggal. Meskipun dapat menerima banyak argumen, beberapa fungsi tidak mengharuskan kita untuk menyertakan argumen tersebut. Berdasarkan pembuatannya, fungsi dapat dibagi menjadi dua yaitu fungsi yang telah disediakan oleh MySQL atau yang disebut built-in function dan fungsi yang didefinisikan sendiri oleh user atau user-defined function Pada BAB ini, kita hanya membahas tentang built-in function. Berdasarkan cara kerjanya, fungsi dibagi menjadi dua, yaitu scalar dan agregat. Istilah skalar berasal dari matematika yang artinya operasi dilakukan pada satu buah nilai. Dalam konteks tabel database, fungsi ini hanya melibatkan nilai pada sebuah kolom. Sebagai contoh fungsi LTRIM akan menghilangkan spasi yang ada di sebelah kiri suatu nilai. Kebalikan dari skalar, pada fungsi agregasi (agregate function) dalam operasinya melibatkan banyak data. Dalam konteks tabel database, fungsi ini melibatkan nilai pada kolom yang berada di baris (row) yang berbeda. Sebagai contoh, fungsi SUM digunakan untuk menjumlahkan nilai pada kolom tertentu yang berada di beberapa baris yang berbeda. Karena Panduan Lengkap Query MySQL 191



membutuhkan pembahasan tersendiri, fungsi agregasi ini kita bahas tersendiri pada BAB 13. Fungsi skalar dapat dikelompokkan menjadi tiga yaitu fungsi yang digunakan untuk memanipulasi karakter, angka, dan date/time. Kita akan membahas ketiganya pada satu per satu. Bentuk umum dari fungsi skalar adalah: NAMAFUNGSI(argumen1, argumen2, dst..)



Penjelasan: 



Fungsi selalu disertai dengan tanda kurung buka dan kurung tutup baik ada atau tidak ada argumen. Tanda kurung ini menandakan bahwa ekspresi tersebut merupakan fungsi.







Antara nama fungsi dengan kurung buka dapat diberi jarak atau spasi, misal NAMAFUNGSI (), namun demikian, beberapa fungsi tidak memperbolehkan adanya spasi tersebut.



12.2. Fungsi Karakter Fungsi karakter digunakan untuk memanipulasi data berjenis karakter. Data berjenis karakter ini sering disebut juga string sehingga fungsi karakter juga biasa disebut fungsi string (string function). Pada bagian ini, kita akan membahas tujuh jenis fungsi karakter yaitu: LEFT, RIGHT, SUBSTRING, LTRIM, RTRIM, UPPER, dan LOWER Untuk lebih mudahnya fungsi yang kita bahas disini akan mengambil data dari tabel buku yang berisi data sebagai berikut: +---------+-------------------------+--------------+-------------+------------+-------+ | id_buku | judul | id_pengarang | id_penerbit | tgl_terbit | harga | +---------+-------------------------+--------------+-------------+------------+-------+ | 1 | Pemrograman Database ...| 1 | 1 | 16/01/2016 | 59000 | | 2 | PHP dan MySQL Langkah...| 1 | 1 | 16/01/2016 | 75000 | | 3 | MySQL Untuk Pemula ...| 3 | 4 | 28/11/2014 | 34800 | | 4 | Kumpulan Aplikasi PHP...| 3 | 4 | 25/02/2016 | 34800 | | 5 | Mahir Dalam 7 Hari: C...| 4 | 1 | 01/01/2013 | 68000 | +---------+-------------------------+--------------+-------------+------------+-------+



192 BAB 12 Functions



12.2.1. Fungsi LEFT Fungsi LEFT digunakan untuk mengambil teks dengan jumlah huruf tertentu yang dihitung mulai dari kiri (left). Format penulisannya adalah: LEFT(teks, jumlah huruf yang diambil)



Fungsi diatas menerima dua argumen yaitu teks dan jumlah huruf yang diambil, kedua argumen ini bersifat mandatory (wajib ada). Salah satu contoh penggunaan fungsi ini adalah ketika kita mengambil data tanggal yang berbentuk string. Misal kita akan mengambil data buku berdasarkan tanggal terbit: 1. SELECT judul, LEFT(tgl_terbit, 2) AS tanggal 2. FROM buku



Hasil yang kita peroleh: +-----------------------------------------+---------+ | judul | tanggal | +-----------------------------------------+---------+ | Pemrograman Database Menggunakan MySQL | 16 | | PHP dan MySQL Langkah Demi Langkah + CD | 16 | | MySQL Untuk Pemula | 28 | | Kumpulan Aplikasi PHP untuk Pemula | 25 | | Mahir Dalam 7 Hari: Coreldraw X6 | 01 | +-----------------------------------------+---------+



Pada contoh diatas, karena format tanggal dd/mm/yyyy, untuk memperoleh dua digit tanggal, kita ambil dua karakter paling kiri. Meskipun format tanggal seperti ini tidak ideal, namun pada kondisi tertentu (desainer database yang berbeda-beda), bisa jadi kita menemui bentuk semacam ini.



12.2.2. Fungsi RIGHT Fungsi selanjutnya yang kita bahas adalah fungsi RIGHT. Seperti terjemahan RIGHT yang berarti kanan, fungsi ini akan mengambil



Panduan Lengkap Query MySQL 193



teks/karakter dengan jumlah huruf tertentu yang dimulai dari sebelah kanan. Format penulisannya adalah: RIGHT(teks, jumlah huruf yang diambil)



Sama seperti fungsi LEFT, fungsi RIGHT juga menerima dua argumen. Kedua argumen ini wajib diisi, jika tidak, maka akan muncul pesan error. Melanjutkan contoh sebelumnya, kita akan mengambil data judul buku beserta tahun terbitnya, query yang kita jalankan: 1. SELECT judul, RIGHT(tgl_terbit, 2) AS tahun 2. FROM buku



Hasil yang kita peroleh: +-----------------------------------------+-------+ | judul | tahun | +-----------------------------------------+-------+ | Pemrograman Database Menggunakan MySQL | 2016 | | PHP dan MySQL Langkah Demi Langkah + CD | 2016 | | MySQL Untuk Pemula | 2014 | | Kumpulan Aplikasi PHP untuk Pemula | 2016 | | Mahir Dalam 7 Hari: Coreldraw X6 | 2013 | +-----------------------------------------+-------+



Pada query diatas, kita mengambil 4 karakter dari kolom tgl_terbit mulai dari kanan, sehingga kita peroleh data tahun terbit. Permasalahan yang sering ditemui ketika menggunakan fungsi RIGHT ini adalah adanya tambahan karakter spasi pada akhir karakter, misal, kita memilki data seperti ini: +-----------------------------------------+------------+ | judul | tgl_terbit | +-----------------------------------------+------------+ | Pemrograman Database Menggunakan MySQL | 10/03/2017 | | PHP dan MySQL Langkah Demi Langkah + CD | 12/03/2017 | +-----------------------------------------+------------+



Namun, ketika kita jalankan query diatas, maka hasil yang kita peroleh:



194 BAB 12 Functions



+-----------------------------------------+-------+ | judul | tahun | +-----------------------------------------+-------+ | Pemrograman Database Menggunakan MySQL | 017 | | PHP dan MySQL Langkah Demi Langkah + CD | 2017 | +-----------------------------------------+-------+



Hal ini disebabkan karena baris pertama kolom tgl_terbit terdapat tambahan spasi, sehingga ketika kita mengambil 4 karakter dari kanan, pengambilan dihitung mulai dari karakter spasi, sehingga diperoleh hasil 071[spasi]. Sebagai solusinya, sebelum kita menjalankan fungsi RIGHT, kita jalankan fungsi TRIM yang akan kita bahas di bagian fungsi komposit.



12.2.3. Fungsi SUBSTRING, SUBSTR, dan MID Fungsi SUBSTRING digunakan untuk mengambil karakter (string) dari tengah, format penulisannya adalah: SUBSTRING(teks, posisi



awal, jumlah karakter)



Fungsi SUBSTRING menerima tiga argumen, yaitu (1) karakter/teks yang akan dimanipulasi, (2) posisi awal karakter yang akan diambil, dan (3) jumlah karakter yang akan diambil. Argumen pertama dan kedua wajib diisi sedangkan argumen ketiga bersifat opsional. Beberapa hal yang perlu diperhatikan ketika menggunakan fungsi SUBSTRING: 



Argumen kedua tidak boleh diisi angka nol (0), namun boleh diisi bilangan positif atau negatif. Jika positif, maka karakter dihitung dari depan (kiri), jika negatif, karakter dihitung mulai dari belakang (kanan)







Argumen ketiga boleh tidak diisi, jika diisi, harus menggunakan bilangan lebih dari 0. Jika tidak diisi maka akan diambil sisa karakter.



Contoh 1:



Panduan Lengkap Query MySQL 195



SELECT SUBSTRING('abcde', 3, 2) AS Hasil Hasil: +-------+ | Hasil | +-------+ | cd | +-------+



Pada contoh diatas, kita mengambil karakter mulai dari karakter ketiga, yaitu c dan diambil sebanyak 2 karakter, sehingga menghasilkan cd Contoh 2: SELECT SUBSTRING('abcde', 3) AS Hasil Hasil: +-------+ | Hasil | +-------+ | cde | +-------+



Karena argumen ketiga kita kosongkan, maka akan diambil semua karakter yang tersisa, sehingga menghasilkan cde. Contoh 3: SELECT SUBSTRING('abcde', -3, 2) AS Hasil Hasil: +-------+ | Hasil | +-------+ | cd | +-------+



Pada contoh diatas, karakter awal dihitung mulai dari karakter terakhir sebanyak 3 karakter (-3) yaitu huruf c, selanjutnya diambil sebanyak 2 196 BAB 12 Functions



karakter, sehingga menghasilkan cd. Perhatikan bahwa hasil yang kita peroleh sama seperti hasil pada Contoh 1 Contoh 5: SELECT SUBSTRING('abcde', -3) AS Hasil Hasil: +-------+ | Hasil | +-------+ | cde | +-------+



Karena argumen ketiga kosong, maka diambil semua karakter yang tersisa. Perhatikan bahwa hasil yang kita peroleh sama seperti pada Contoh 2 Setelah memahami bagaimana fungsi SUBSTRING bekerja, mari kita terapkan fungsi tersebut pada tabel database. Melanjutkan contoh sebelumnya, misal kita ingin menampilkan data judul buku beserta bulan terbit. Query yang kita jalanakan: 1. SELECT judul, SUBSTRING(tgl_terbit, 4, 2) AS bulan 2. FROM buku



Hasil yang kita peroleh: +-----------------------------------------+-------+ | judul | bulan | +-----------------------------------------+-------+ | Pemrograman Database Menggunakan MySQL | 01 | | PHP dan MySQL Langkah Demi Langkah + CD | 01 | | MySQL Untuk Pemula | 11 | | Kumpulan Aplikasi PHP untuk Pemula | 02 | | Mahir Dalam 7 Hari: Coreldraw X6 | 01 | +-----------------------------------------+-------+



Pada contoh diatas, karena format tanggal adalah dd/mm/yyyy, maka untuk mendapatkan data bulan, kita ambil karakter mulai dari karakter keempat sebanyak dua karakter.



Panduan Lengkap Query MySQL 197



Fungsi yang cara kerjanya sama persis dengan fungsi SUBSTRING adalah fungsi SUBSTR dan MID, kita bebas menggunakan ketiganya, jika Anda terbiasa dengan bahasa pemrograman tertentu seperti PHP, maka akan lebih familiar dengan fungsi SUBSTR, atau jika Anda terbiasa dengan bahasa pemrograman keluarga dari Microsoft, maka akan lebih familiar dengan fungsi MID. Penting diperhatikan bahwa untuk fungsi tertentu, tidak diperbolehkan adanya spasi antara nama fungsi dengan tanda kurung buka, salah satunya pada fungsi SUBSTRING, jika kita tambahkan spasi, misal SUBSTRING ('abcd', 1, 2), maka akan menghasilkan pesan error yaitu: error: SQL Error (1630): FUNCTION tutorial3.SUBSTRING does not exists



12.2.4. Fungsi TRIM, LTRIM, dan RTRIM Fungsi yang mengandung kata "trim" digunakan untuk menghilangkan spasi yang berada baik sebelum maupun sesudah karakter. Fungsi TRIM untuk menghilangkan spasi sebelum dan sesudah karakter, fungsi LTRIM menghilangkan spasi di bagian paling kiri karakter, dan RTRIM menghilangkan spasi di bagian paling kanan karakter. Format penulisan ketiga fungsi tersebut adalah: TRIM: TRIM(teks) LTRIM: LTRIM(teks) RTRIM: RTRIM(teks)



198 BAB 12 Functions



Ketiga fungsi diatas hanya menerima satu argumen yang wajib untuk diisi berupa teks. Beberapa contoh penggunaan: Contoh TRIM: SELECT TRIM(' Judul



Sebelum: +-----------+ | Judul | +-----------+ | Judul | +-----------+



') AS Hasil



Hasil query: +-------+ | Hasil | +-------+ | Judul | +-------+



Contoh LTRIM: SELECT LTRIM(' Judul



Sebelum: +-----------+ | Judul | +-----------+ | Judul | +-----------+



') AS Hasil



Hasil query: +----------+ | Hasil | +----------+ | Judul | +----------+



Contoh RTRIM: SELECT RTRIM(' Judul



Sebelum: +-----------+ | Hasil | +-----------+ | Judul | +-----------+



') AS Hasil



Hasil query: +--------+ | Hasil | +--------+ | Judul | +--------+



12.2.5. Fungsi UPPER dan LOWER Fungsi terakhir terkait string yang kita bahas adalah fungsi UPPER dan LOWER. Fungsi UPPER digunakan untuk mengubah teks menjadi huruf besar,



Panduan Lengkap Query MySQL 199



sedangkan fungsi LOWER untuk mengubah teks menjadi huruf kecil. Format penulisannya adalah: UPPER(teks)



Fungsi UPPER dan LOWER hanya menerima satu argumen teks yang wajib diisi. Misal, kita tampilkan judul buku dengan huruf besar semua. Query yang kita jalankan: 1. SELECT UPPER(judul) AS judul_uppper 2. FROM buku 3. LIMIT 3



Hasil: +-----------------------------------------+ | judul_uppper | +-----------------------------------------+ | PEMROGRAMAN DATABASE MENGGUNAKAN MYSQL | | PHP DAN MYSQL LANGKAH DEMI LANGKAH + CD | | MYSQL UNTUK PEMULA | +-----------------------------------------+



12.2.6. Fungsi CONCAT dan CONCAT_WS Fungsi CONCAT digunakan untuk menggabungkan dua atau lebih ekspresi menjadi satu menjadi sebuah string. Ekspresi yang digabungkan berupa argumen yang diletakkan di dalam fungsi. Kita dapat mengisikan argumen dengan jumlah yang tidak terbatas. Format penulisan kedua fungsi ini sama yaitu: CONCAT(Argumen1, Argumen2, Argumen2, dst…)



Jenis argumen umumnya berupa string, namun demikian, kita dapat mengisinya dengan selain string, seperti integer, fungsi, dll. Contoh: SELECT CONCAT('Nilai:



200 BAB 12 Functions



', 95)



Hasil: +------------------------+ | CONCAT('Nilai: ', 95) | +------------------------+ | Nilai: 95 | +------------------------+



Untuk penerapan pada tabel, misal kita gabungkan kolom judul dan harga, query yang kita jalankan: 1. SELECT id_buku, CONCAT('Judul: ', judul, ', Harga: ', harga) AS Buku 2. FROM buku



Hasil: +---------+--------------------------------------------------------------+ | id_buku | Buku | +---------+--------------------------------------------------------------+ | 1 | Judul: Pemrograman Database Menggunakan MySQL, Harga: 59000 | | 2 | Judul: PHP dan MySQL Langkah Demi Langkah + CD, Harga: 75000 | | 3 | Judul: MySQL Untuk Pemula, Harga: 34800 | | 4 | Judul: Kumpulan Aplikasi PHP untuk Pemula, Harga: 34800 | | 5 | Judul: Mahir Dalam 7 Hari: Coreldraw X6, Harga: 68000 | +---------+--------------------------------------------------------------+



Ketika menjalankan fungsi CONCAT, MySQL akan mengubah tipe data pada semua argumen menjadi string. Pada contoh diatas, kolom harga memiliki tipe data INT, oleh MySQL diubah menjadi string. Perhatikan bahwa pada tabel hasil, judul kolomnya adalah CONCAT('Judul: ', judul, ', Harga: ', harga) agar lebih rapi, kita perlu tambahkan alias, misal CONCAT('Judul: ', judul, ', Harga: ', harga) AS Buku. Jika salah satu argumen bernilai NULL, maka hasil penggabungan akan NULL, misal: 1. SELECT id_buku, CONCAT('Judul: ', judul, ', Harga: ', NULL) AS Buku 2. FROM buku



Hasil: Panduan Lengkap Query MySQL 201



+---------+------+ | id_buku | Buku | +---------+------+ | 1 | NULL | | 2 | NULL | | 3 | NULL | | 4 | NULL | | 5 | NULL | +---------+------+



Pada contoh diatas, karena argumen harga bernilai NULL, maka semua hasil menjadi NULL. Contoh lain: 1. SELECT id_buku, 2. CONCAT( 3. 'Judul: ', judul, 4. ', Harga: ', IF(harga > 50000, harga, NULL) 5. ) AS Buku 6. FROM buku



Hasil: +---------+--------------------------------------------------------------+ | id_buku | Buku | +---------+--------------------------------------------------------------+ | 1 | Judul: Pemrograman Database Menggunakan MySQL, Harga: 59000 | | 2 | Judul: PHP dan MySQL Langkah Demi Langkah + CD, Harga: 75000 | | 3 | NULL | | 4 | NULL | | 5 | Judul: Mahir Dalam 7 Hari: Coreldraw X6, Harga: 68000 | +---------+--------------------------------------------------------------+



Pada contoh diatas, jika harga buku dibawah 50.000, kita ubah harganya menjadi NULL, sehingga fungsi CONCAT pada buku dengan ID 3 dan 4 menghasilkan nilai NULL. Selain CONCAT(), MySQL juga menyediakan fungsi CONCAT_WS(), kegunaan fungsi ini mirip dengan fungsi CONCAT, bedanya, argumen pertama dari fungsi CONCAT_WS() akan digunakan sebagai separator (WS = With Separator), Misal: SELECT CONCAT_WS(': ', 'Nilai', 95)



Hasil: 202 BAB 12 Functions



+------------------------------+ | CONCAT_WS(': ', 'Nilai', 95) | +------------------------------+ | Nilai: 95 | +------------------------------+



Jika argumen separator (argumen pertama) bernilai NULL, maka hasilnya akan bernilai NULL, contoh: SELECT CONCAT_WS(NULL, 'Nilai', 95)



Hasil: +------------------------------+ | CONCAT_WS(NULL, 'Nilai', 95) | +------------------------------+ | NULL | +------------------------------+



Namun jika argumen kedua dan setelahnya ada yang bernilai NULL, maka MySQL akan tetap memprosesnya dan nilai NULL akan dilewati, contoh: SELECT CONCAT_WS(': ', 'Nilai', NULL, 95)



Hasil: +------------------------------------+ | CONCAT_WS(': ', 'Nilai', NULL, 95) | +------------------------------------+ | Nilai: 95 | +------------------------------------+



Untuk penerapan pada tabel, misal kita gabung semua kolom yang ada pada tabel buku dengan spasi sebagai separator: 1. SELECT CONCAT_WS(' ', 2. 'Judul:', judul, 3. ', Terbit:', 4. ', Harga:', harga 5. ) AS buku 6. FROM buku



tgl_terbit,



Hasil: Panduan Lengkap Query MySQL 203



+-------------------------------------------------------------------------------------+ | buku | +-------------------------------------------------------------------------------------+ | Judul: Pemrograman Database Menggunakan MySQL , Terbit: 16/01/2016 , Harga: 59000 | | Judul: PHP dan MySQL Langkah Demi Langkah + CD , Terbit: 16/01/2016 , Harga: 75000 | | Judul: MySQL Untuk Pemula , Terbit: 28/11/2014 , Harga: 34800 | | Judul: Kumpulan Aplikasi PHP untuk Pemula , Terbit: 25/02/2016 , Harga: 34800 | | Judul: Mahir Dalam 7 Hari: Coreldraw X6 , Terbit: 01/01/2013 , Harga: 68000 | +-------------------------------------------------------------------------------------+



Dalam praktek, salah satu penerapan fungsi ini adalah ketika kita ingin membuat file CSV, misal kita buat data CSV dengan separator koma, jalankan query berikut: 1. SELECT CONCAT_WS(',', judul, tgl_terbit,harga) AS buku 2. FROM buku



Hasil: +----------------------------------------------------------+ | buku | +----------------------------------------------------------+ | Pemrograman Database Menggunakan MySQL,16/01/2016,59000 | | PHP dan MySQL Langkah Demi Langkah + CD,16/01/2016,75000 | | MySQL Untuk Pemula,28/11/2014,34800 | | Kumpulan Aplikasi PHP untuk Pemula,25/02/2016,34800 | | Mahir Dalam 7 Hari: Coreldraw X6,01/01/2013,68000 | +----------------------------------------------------------+



12.3. Fungsi Komposit Karakteristik penting fungsi, baik fungsi karakter, numeric, date/time, atau fungsi yang lain adalah antara satu fungsi dengan fungsi yang lain dapat dilakukan penggabungan, hasil penggabungan ini disebut fungsi komposit (composite function), atau fungsi dari fungsi. Sebagai contoh, pada pembahasan fungsi RIGHT, tanggal terbit pada judul buku "Pemrograman Database Menggunakan MySQL" adalah "10/03/2017 " dimana terdapat tambahan spasi di belakang tanggal, sehingga ketika mengambil data tahun menggunakan fungsi RIGHT(tanggal, 4) akan diperoleh hasil "017 ". Untuk dapat menghasilkan 2017, maka sebelum kita jalankan fungsi RIGHT, kita



204 BAB 12 Functions



hilangkan terlebih dahulu spasi nya dengan fungsi RTRIM, query yang kita jalankan: 1. SELECT judul, 2. RIGHT(RTRIM(tgl_terbit), 4) AS tahun 3. FROM buku 4. WHERE id_buku = 1



Hasil yang kita peroleh: +----------------------------------------+-------+ | judul | tahun | +----------------------------------------+-------+ | Pemrograman Database Menggunakan MySQL | 2017 | +----------------------------------------+-------+



Pada query diatas, terdapat fungsi komposit RIGHT(RTRIM(tgl_terbit), 4) AS tahun. Fungsi tersebut melibatkan fungsi RTRIM dan RIGHT. Seperti telah beberapa kali kita bahas, bahwa ketika mendapati tanda kurung, maka MySQL terlebih dahulu akan mengeksekusi ekspresi yang ada di dalam tanda kurung tersebut. Sehingga pada contoh diatas, MySQL akan menjalankan fungsi RTRIM terlebih dahulu baru kemudian RIGHT. Fungsi RTRIM(tgl_terbit)akan menghilangkan spasi di belakang tanggal, sehingga menghasilkan "10/03/2017", selanjutnya fungsi RIGHT akan menghasilkan string "2017". Fungsi: RIGHT(RTRIM(tgl_terbit), 4) dapat diibaratkan RIGHT("10/03/2017", 4)



12.4. Fungsi Date/Time Fungsi terkait date/time memungkinkan kita untuk memanipulasi data tanggal dan atau waktu. MySQL menyediakan banyak fungsi terkait date/time, kita akan membahas beberapa diantaranya yang sering digunakan yaitu NOW(), DATEDIFF(), DATE_FORMAT(), DATE, YEAR(), MONTH, DAY(), dan STRTODATE(). Standar format tanggal pada database, termasuk MySQL adalah YYYY-MMDD HH:MM:SS misal: 2017-03-17 07:15:19 bentuk ini juga disebut



Panduan Lengkap Query MySQL 205



ISO8601. Ketika kita menggunakan fungsi date/time, maka bentuk tanggal harus sesuai dengan format tersebut.



12.4.1. Fungsi NOW() dan CURDATE() Fungsi NOW() digunakan untuk menghasilkan waktu sekarang ketika fungsi tersebut dieksekusi. Fungsi ini tidak memiliki argumen, contoh penggunaan: SELECT NOW();



Hasil yang kita peroleh adalah: +---------------------+ | NOW() | +---------------------+ | 2017-03-18 06:05:56 | +---------------------+



Karena fungsi ini tidak memiliki argumen, kita tidak dapat mengatur output dari tanggal yang dihasilkan. Pada contoh diatas, dihasilkan 201603-17 06:05:56 berarti tanggal (date) 17 Maret 2017 dan waktu (time) pukul 06 menit ke 05 dan detik ke 56. Perhatikan bahwa tanggal tersebut berformat YYYY-MM-DD HH:MM:SS yang merupakan format tanggal/waktu standar SQL. Selanjutnya, jika kita ingin menampilkan data tangal sekarang tanpa disertai waktu, kita gunakan fungsi CURDATE(), contoh: SELECT CURDATE();



Hasil: +------------+ | CURDATE() | +------------+ | 2017-04-06 | +------------+



206 BAB 12 Functions



12.4.2. Fungsi DATE_FORMAT() Fungsi DATE_FORMAT() digunakan untuk mengubah format tanggal menjadi bentuk tertentu. Bentuk format tanggal yang dihasilkan sangat fleksibel dan bisa bermacam macam, bisa bentuk tanggal dan waktu penuh, waktu saja, tanggal saja, bulan saja, atau tahun saja. Fungsi DATE_FORMAT() memiliki dua argumen yang wajib diisi yaitu (1) date yang berisi data tanggal yang ingin diolah, dan (2) format yang berisi format output yang diinginkan. Format penulisan fungsi ini adalah: DATE_FORMAT(tanggal, format_tanggal)



Untuk argumen format_tanggal, terdapat banyak karakter yang dapat digunakan. Berikut ini format yang sering digunakan: Format



Deskripsi



Hari %a



Nama hari dalam satu minggu dalam tiga huruf (Sun s.d Sat)



%W



Nama hari dalam satu minggu (Sunday s.d Saturday)



%w



Hari dalam satu minggu berbentuk angka (0 = Minggu, 6 = Sabtu)



%d



Hari dalam satu bulan dalam dua digit angka (00 s.d 31)



%e



Hari dalam satu bulan dalam satu-dua digit angka (0 s.d 31)



Bulan %b



Nama bulan dalam tiga huruf (Jan s.d Dec)



%M



Nama bulan penuh (January s.d December)



%c



Bulan dalam satu-dua digit angka (0 s.d 12)



%m



Bulan dalam dua digit angka (00 s.d 12)



Tahun %Y



Tahun dalam empat digit angka



%y



Tahun dalam dua digit angka Panduan Lengkap Query MySQL 207



Jam %H



Jam dalam 24 jam dalam dua digit (00 .d 23)



%k



Jam dalam 24 jam dalam satu-dua digit (0 s.d 23)



Menit %i



Menit dalam dua dua digit (00 s.d 59)



Detik %S



Detik dalam dua digit (00 s.d 59)



%s



Detik dalam satu digit (1s.d 59) Tabel 12.1 Karakter untuk fungsi datetime



Catatan: kita wajib menyertakan tanda persen (%). Tanda ini menandakan bahwa karakter tersebut adalah karakter format tanggal. Contoh 1: Format dasar 1. SELECT DATE_FORMAT( 2. NOW(),"Tanggal: %d-%m-%Y, Pukul: %H:%i:%s" 3. ) AS Waktu



Hasil yang kita peroleh: +--------------------------------------+ | Waktu | +--------------------------------------+ | Tanggal: 19-03-2017, Pukul: 10:33:25 | +--------------------------------------+



Contoh 2: Format tanggal dengan nama hari dan bulan 1. SELECT DATE_FORMAT( 2. NOW(),"Tanggal: %W, %e %M %Y, Pukul: %H:%i:%s" 3. ) AS Waktu



Hasil yang kita peroleh: +-------------------------------------------------+ | Waktu | +-------------------------------------------------+



208 BAB 12 Functions



| Tanggal: Sunday, 19 March 2017, Pukul: 10:34:21 | +-------------------------------------------------+



Pada contoh diatas, nama hari dan nama bulan masih dalam bahasa Inggris, hal ini dikarenakan secara default bahasa yang digunakan adalah bahasa Inggris, kita dapat mengubahnya dengan mendefinisikan bahasa yang ingin digunakan. Untuk bahasa Indonesia, kita gunakan id_ID, misal: 1. SET lc_time_names = "id_ID"; 2. SELECT DATE_FORMAT( 3. NOW(),"Tanggal: %W, %e %M %Y, Pukul: %H:%i:%s" 4. ) AS Waktu



Hasil yang kita peroleh: +-------------------------------------------------+ | Waktu | +-------------------------------------------------+ | Tanggal: Minggu, 19 Maret 2017, Pukul: 10:34:21 | +-------------------------------------------------+



Contoh 3: Kita juga dapat mengambil hanya data tanggal, bulan atau tahun aja 1. SELECT DATE_FORMAT( NOW(),"%e" ) AS tanggal, 2. DATE_FORMAT( NOW(),"%M" ) AS bulan, 3. DATE_FORMAT( NOW(),"%Y" ) AS tahun



Hasil yang kita peroleh: +---------+----------+-------+ | tanggal | bulan | tahun | +---------+----------+-------+ | 19 | Maret | 2017 | +---------+----------+-------+



Penggunaan fungsi DATE_FORMAT untuk mengambil hanya data bulan atau tahun saja tidaklah lazim, umumnya, untuk mengambil data tersebut digunakan fungsi MONTH() atau YEAR()



Panduan Lengkap Query MySQL 209



12.4.3. Fungsi STR_TO_DATE() Fungsi STR_TO_DATE() digunakan untuk mengubah string dengan format tanggal tertentu menjadi format standar SQL yaitu yyyy-mm-dd hh:mm:ss. Fungsi ini merupakan salah satu fungsi yang penting dan sering digunakan, untuk itu perlu masuk kedalam daftar fungsi yang harus dihafalkan Kenapa perlu mengubah format tanggal menjadi format standar SQL? Sering kita temui format tanggal yang disimpan dalam database banyak yang tidak standar, ada yang dd/mm/yyyy, dd-mm-yyyy, d,m,yyyy dll. Nah, untuk dapat mengolah data tersebut menggunakan fungsi terkait date seperti DATE_FORMAT(), YEAR(), MONTH(), dll, maka data tersebut harus diubah ke dalam bentuk standar SQL Fungsi STR_TO_DATE() memiliki dua argumen yaitu (1) tanggal berupa string, dan (2) format tanggal dari string tersebut. Adapun format penulisannya adalah: STR_TO_DATE(string_date, format)



Pada fungsi ini, argumen format memiliki nilai seperti argumen format pada fungsi DATE_FORMAT(), yaitu diawali dengan tanda % dan diikuti oleh karakter tertentu (tabel 12.1). Bentuk format tanggal ini juga harus sesuai dengan format tanggal yang ada pada argumen pertama, karena format pada argumen kedua akan digunakan MySQL untuk memetakan mana tanggal, bulan, tahun, dan waktu dari data yang ada di argumen pertama. Adapun karakter yang dapat digunakan sebagai format tanggal sama seperti yang digunakan pada fungsi DATE_FORMAT() Contoh 1: Mengubah data tanggal sederhana SELECT STR_TO_DATE ('05/03/2017', '%d/%m/%Y') AS tanggal



Hasil: 210 BAB 12 Functions



+------------+ | tanggal | +------------+ | 2017-03-05 | +------------+



Pada contoh diatas, MySQL akan men-scan tanggal satu per satu mulai dari kiri ke kanan kemudian mencocokkan dengan pola pada argumen 2. Format yang kita gunakan pada argumen ke 2 adalah %d/%m/%Y: 



%d, karena tanggal pada argumen pertama berbentuk dua digit yaitu 05







%m karena bulan juga berbentuk dua digit, yaitu 03







%Y karena tahun berbentuk 4 digit, yaitu 2017







Kita gunakan separator slash ( / ) karena antara tanggal, bulan, dan tahun dipisahkan dengan separator tersebut



Jika diilustrasikan dengan gambar, akan tampak seperti gambar berikut:



Gambar 6.1 Ilustrasi Fungsi STR_TO_DATE() Jika kita salah dalam mengidentifikasi format tanggal, maka hasil yang diperoleh tidak sesuai harapan, misal kita keliru menulis %Y menjadi %y: SELECT STR_TO_DATE ('05/03/2017', '%d/%m/%y') AS tanggal



Maka hasil yang kita peroleh: +------------+ | tanggal | +------------+ | 2020-03-05 | +------------+



Panduan Lengkap Query MySQL 211



Dari contoh diatas terlihat bahwa tahun yang seharusnya 2017 menjadi 2020, hal ini karena format %y membaca data tahun sebanyak dua digit, sehingga, tahun 2017 akan dibaca tahun 20 kemudian dikonversi ke format standar SQL menjadi 2020. Jika format pada argumen ke 2 tidak sesuai dengan format pada argumen pertama (meskipun hanya satu format), maka akan menghasilkan NULL, misal: SELECT STR_TO_DATE ('05-03-2017', '%d-%M-%y') AS tanggal



Hasil: +---------+ | tanggal | +---------+ | NULL | +---------+



Query diatas menghasilkan NULL karena: 



Pertama, MySQL akan mencari format %d dan ketemu di dua digit pertama (05)







Selanjutnya mencari tanda dash (-) dan ketemu yaitu setelah 05







MySQL melanjutkan dengan mencari format %M yang artinya nama bulan (Januay s.d December), namun tidak ketemu, karena karakter selanjutnya adalah 03, sehingga proses pencarian berhenti dan menghasilkan NULL



Agar dapat lebih memahami fungsi STR_TO_DATE(), mari kita coba dengan contoh lain Contoh 2: Format tanggal bervariasi Query berikut ini akan memperoleh hasil yang sama: SELECT STR_TO_DATE ("05-3,2017", "%d-%m,%Y") AS tanggal



Atau 212 BAB 12 Functions



SELECT STR_TO_DATE ("05032017", "%d%m%Y") AS tanggal



Atau 1. SELECT STR_TO_DATE ( 2. "Tanggal: 05-03-2017", "Tanggal: %d-%m-%Y" 3. ) AS tanggal



Hasil yang kita peroleh sama, yaitu: +------------+ | tanggal | +------------+ | 2017-03-05 | +------------+



Selanjutnya mari kita terapkan fungsi DATE_FORMAT() pada tabel buku yang telah kita gunakan pada contoh sebelumnya. Misal kita ingin menampilkan data judul buku beserta tanggal terbit dengan format: tanggal dua digit, bulan dengan nama, dan tahun empat digit. Query yang kita jalankan: 1. SET lc_time_names = "id_ID"; 2. SELECT judul, 3. DATE_FORMAT( 4. STR_TO_DATE(tgl_terbit, "%d/%m/%Y") 5. , "%d %M %Y" 6. ) AS tgl_terbit 7. FROM buku



Hasil yang kita peroleh: +-----------------------------------------+------------------+ | judul | tgl_terbit | +-----------------------------------------+------------------+ | Pemrograman Database Menggunakan MySQL | 16 Januari 2016 | | PHP dan MySQL Langkah Demi Langkah + CD | 16 Januari 2016 | | MySQL Untuk Pemula | 28 November 2014 | | Kumpulan Aplikasi PHP untuk Pemula | 25 Pebruari 2016 | | Mahir Dalam 7 Hari: Coreldraw X6 | 01 Januari 2013 | +-----------------------------------------+------------------+



Panduan Lengkap Query MySQL 213



Pada contoh diatas, kita mengubah format tanggal dari dd/mm/yyyy menjadi d M Y. Tanggal pada judul buku Pemrograman Database Menggunakan MySQL adalah "10/03/2017 " (dengan tambahan spasi), seperti yang telah kita bahas sebelumnya, MySQL akan mengabaikan string setelah tanggal sehingga ketika MySQL mencari format %Y dan setelah menemukan 2017 maka akan mengabaikan karakter di belakangnya termasuk spasi. Fungsi DATE_FORMAT() juga dapat digunakan untuk mengambil data tanggal, bulan, atau tahun saja, namun dengan syarat, format tanggal sudah sesuai dengan standar SQL yaitu yyyy-mm-dd atau sejenisnya (dengan tanda pemisah yang berbeda) Contoh: 1. SELECT "2017/03/15" AS date, 2. DATE_FORMAT ("2017-03-15", "%d") AS tanggal, 3. DATE_FORMAT ("2017/03/15", "%m") AS bulan, 4. DATE_FORMAT ("2017,03,15", "%Y") AS tahun



Hasil yang kita peroleh: +------------+---------+-------+-------+ | date | tanggal | bulan | tahun | +------------+---------+-------+-------+ | 2017/03/15 | 15 | 03 | 2017 | +------------+---------+-------+-------+



Meskipun mudah, cara ini jarang digunakan, lebih umum menggunakan fungsi DAY(), MONTH(), dan YEAR(), karena lebih simpel dan mudah dipahami.



12.4.4. Fungsi DAY(), MONTH(), dan YEAR() Fungsi selanjutnya adalah fungsi untuk mengambil data hari, bulan, dan tahun, yaitu fungsi DAY() untuk hari, MONTH() untuk bulan, dan YEAR() untuk tahun. Ketiga fungsi tersebut hanya menerima satu argumen, yaitu date yang ingin diambil data tanggal, bulan, atau tahunnya saja. Format penulisannya adalah: 214 BAB 12 Functions



DAY(date)



Catatan Penting untuk diketahui bahwa argumen date harus memiliki format standar SQL yaitu yyyy-mm-dd atau format sejenis dengan separator berbeda, misal: yyyy/mm/dd atau yyyy,mm,dd atau tanpa separator. Jika format belum sesuai maka harus diubah terlebih dahulu menggunakan fungsi STR_TO_DATE Contoh 1: 1. SELECT "2017/03/15" AS date, 2. DAY ("2017-03-15") AS tanggal, 3. MONTH ("2017/03/15") AS bulan, 4. YEAR ("2017,03,15") AS tahun



Hasil yang kita peroleh: +------------+---------+-------+-------+ | date | tanggal | bulan | tahun | +------------+---------+-------+-------+ | 2017/03/15 | 15 | 3 | 2017 | +------------+---------+-------+-------+



Pada contoh diatas, meskipun tanggal menggunakan separator yang berbeda beda, fungsi tetap dapat berjalan dengan baik. Selanjutnya mari kita coba untuk menampilkan data buku yang terbit hanya di tahun 2016, query yang kita jalankan: 1. SELECT judul, tgl_terbit, 2. YEAR( STR_TO_DATE(tgl_terbit, '%d/%m/%Y') ) AS 3. thn_terbit 4. FROM buku WHERE YEAR( STR_TO_DATE(tgl_terbit, '%d/%m/%Y') ) = 2016



Hasil yang kita peroleh:



Panduan Lengkap Query MySQL 215



+-----------------------------------------+------------+------------+ | judul | tgl_terbit | thn_terbit | +-----------------------------------------+------------+------------+ | Pemrograman Database Menggunakan MySQL | 16/01/2016 | 2016 | | PHP dan MySQL Langkah Demi Langkah + CD | 16/01/2016 | 2016 | | Kumpulan Aplikasi PHP untuk Pemula | 25/02/2016 | 2016 | +-----------------------------------------+------------+------------+



Pada contoh diatas, pada klausa SELECT dan WHERE terdapat fungsi komposit yaitu STR_TO_DATE() dan YEAR(). Karena format tanggal terbit masih dd/mm/yyyy, maka untuk mendapatkan data tahun menggunakan fungsi YEAR(), kita perlu untuk mengubah format tanggalnya menjadi yyyy-mm-dd menggunakan fungsi STR_TO_DATE() STR_TO_DATE(tgl_terbit, '%d/%m/%Y'), selanjutnya hasilnya akan digunakan oleh MySQL sebagai argumen fungsi YEAR().



12.5. Fungsi Perbedaan Waktu Selanjutnya kita bahas mengenai fungsi terkait perbedaan waktu, diantaranya fungsi DATEDIFF(), TIMEDIFF(), dan TIMESTAMPDIFF()



12.5.1. Fungsi DATEDIFF() Fungsi DATEDIFF() digunakan untuk mencari selisih tanggal dalam hari. Fungsi ini memiliki dua buah argumen yang wajib diisi, yaitu: (1) tanggal akhir dan (2) tanggal awal. Format penulisannya adalah: DATEDIFF (tanggal_akhir, tanggal_awal)



Contoh penggunaan: SELECT DATEDIFF("2017-01-12","2016-12-03") AS selisih



Hasil yang kita peroleh: +---------+ | selisih | +---------+ | 40 | +---------+



216 BAB 12 Functions



Penggunaan fungsi ini salah satunya untuk menghitung jumlah hari pada sistem persewaan buku. Misal kita punya tabel sebagai berikut: +---------+------------------------------------+-----------+------------+ | id_buku | judul | prioritas | tgl_sewa | +---------+------------------------------------+-----------+------------+ | 1 | Pemrograman Database MySQL | 3 | 28/03/2017 | | 2 | PHP dan MySQL Langkah Demi Langkah | 1 | 30/03/2017 | | 3 | MySQL Untuk Pemula | 2 | 01/04/2017 | | 4 | Kumpulan Aplikasi PHP untuk Pemula | 4 | 20/03/2017 | +---------+------------------------------------+-----------+------------+



Selanjutnya kita hitung berapa lama buku telah dipinjam: 1. SELECT judul, 2. tgl_sewa, 3. prioritas AS p, 4. CURDATE() AS tgl_sekarang, 5. DATEDIFF( 6. CURDATE(), 7. STR_TO_DATE(tgl_sewa, "%d/%m/%Y") 8. ) AS jml_hari 9. FROM persewaan_buku



Hasil: +------------------------------------+------------+---+--------------+----------+ | judul | tgl_sewa | p | tgl_sekarang | jml_hari | +------------------------------------+------------+---+--------------+----------+ | Pemrograman Database MySQL | 28/03/2017 | 3 | 2017-04-02 | 5 | | PHP dan MySQL Langkah Demi Langkah | 30/03/2017 | 1 | 2017-04-02 | 3 | | MySQL Untuk Pemula | 01/04/2017 | 2 | 2017-04-02 | 1 | | Kumpulan Aplikasi PHP untuk Pemula | 20/03/2017 | 4 | 2017-04-02 | 13 | +------------------------------------+------------+---+--------------+----------+



Pada contoh diatas, karena format tanggal tidak baku, kita ubah terlebih dahulu menjadi yyyy-mm-dd dengan fungsi STR_TO_DATE()



12.5.2.Fungsi TIMEDIFF() Fungsi TIMEDIFF() digunakan untuk menghitung perbedaan waktu. Fungsi ini memiliki dua argumen yang wajib diisi yaitu: (1) waktu awal, (2) waktu akhir. Contoh penggunaan:



Panduan Lengkap Query MySQL 217



1. SELECT TIMEDIFF("07:05:30", "07:05:01");



Hasil: +----------------------------------+ | TIMEDIFF('07:05:30', '07:05:01') | +----------------------------------+ | 00:00:29 | +----------------------------------+



Penggunaan fungsi ini salah satunya untuk menghitung waktu keterlambatan absensi. Misal kita memiliki tabel absen dengan data sebagai berikut: +------------+---------+-----------+ | id_pegawai | nama | jam_absen | +------------+---------+-----------+ | 1 | Alfa | 07:59:59 | | 2 | Beta | 08:00:00 | | 3 | Charlie | 07:30:59 | +------------+---------+-----------+



Selanjutnya kita hitung waktu keterlambatan dengan batas waktu absen 07:30, jika kurang dari 30 menit, masuk kategori 1, jika lebih, masuk kategori 2. Query yang kita jalankan: 1. SELECT nama, 2. jam_absen, 3. MINUTE( 4. TIMEDIFF(jam_absen, "07:30:00") 5. ) AS menit_terlambat, 6. CASE 7. WHEN MINUTE(TIMEDIFF(jam_absen, "07:30:00")) < 30 8. AND MINUTE(TIMEDIFF(jam_absen, "07:30:00")) > 0 9. THEN 1 10. WHEN MINUTE(TIMEDIFF(jam_absen, "07:30:00")) >= 30 11. THEN 2 12. ELSE 0 13. END AS status_terlambat 14. FROM absen



Hasil yang kita peroleh: +---------+-----------+-----------------+------------------+



218 BAB 12 Functions



| nama | jam_absen | menit_terlambat | status_terlambat | +---------+-----------+-----------------+------------------+ | Alfa | 07:59:59 | 29 | 1 | | Beta | 08:00:00 | 30 | 2 | | Charlie | 07:30:59 | 0 | 0 | +---------+-----------+-----------------+------------------+



Pada contoh diatas, kita menggunakan fungsi MINUTE() untuk mengubah detik menjadi menit, sehingga untuk pegawai dengan nama Charlie, meskipun terlambat 00:00:59 detik, tetap dianggap belum terlambat karena masih 0 menit.



12.5.3. Fungsi TIMESTAMPDIFF() Fungsi TIMESTAMPDIFF() digunakan untuk menghitung perbedaan waktu dalam unit tertentu, format penulisannya adalah: TIMESTAMPDIFF(unit, datetime_awal, datetime_akhir)



Ketiga argumen pada fungsi ini wajib diisi. Argumen unit dapat diisi: MICROSECOND, SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, atau YEAR. Argumen kedua dan ketiga berupa tanggal dan waktu atau tanggal saja (minimal harus memuat tanggal), disamping itu, keduanya juga harus memiliki format standar SQL. Contoh: 1. SELECT TIMESTAMPDIFF( 2. MINUTE, "2017-03-01 07:30:00", "2017-03-01 3. 07:45:25" ) AS menit;



Hasil: +-------+ | menit | +-------+ | 15 | +-------+



Panduan Lengkap Query MySQL 219



Contoh penerapan fungsi ini adalah untuk menghitung usia dari seseorang pada aplikasi penerimaan pegawai, misal terdapat tabel pendaftaran sebagai berikut: +--------------+---------+------------+ | id_pendaftar | nama | tgl_lahir | +--------------+---------+------------+ | 1 | Alfa | 1990-07-15 | | 2 | Beta | 1995-06-02 | | 3 | Charlie | 1993-03-01 | +--------------+---------+------------+



Selanjutnya kita hitung usia pendaftar, jika kurang dari 25 tahun, maka kita beri status “umur kurang”, jika lebih, “umur cukup”. Query yang kita jalankan: 1. SELECT nama, 2. TIMESTAMPDIFF(YEAR, tgl_lahir, CURDATE()) AS usia, 3. IF( TIMESTAMPDIFF(YEAR, tgl_lahir, CURDATE()) < 25 4. , "Umur kurang" 5. , "Umur cukup" 6. ) AS status 7. FROM pendaftaran



Hasil: +---------+------+-------------+ | nama | usia | status | +---------+------+-------------+ | Alfa | 26 | Umur cukup | | Beta | 21 | Umur kurang | | Charlie | 23 | Umur kurang | +---------+------+-------------+



12.6. Fungsi Numeric (Angka) MySQL juga memiliki banyak fungsi terkait angka/numeric. Pada bagian ini, kita bahas beberapa diantaranya yang sering digunakan, yaitu fungsi ROUND(), CEIL(), dan FLOOR().



220 BAB 12 Functions



12.6.1. Fungsi ROUND Fungsi ROUND digunakan untuk membulatkan pecahan (angka di belakang koma). Jika digit di belakang koma bernilai 5 atau lebih, maka akan dilakukan pembulatan ketas, jika kurang dari 5 maka akan dibulatkan ke bawah. Adapun format penulisannya adalah: ROUND(bilangan, jumlah_desimal)



Argumen jumlah desimal menunjukkan banyaknya angka di belakang koma. Argumen ini bersifat opsional, jika tidak diisi, maka akan bernilai 0. Contoh: SELECT ROUND(2.49), ROUND(2.50), ROUND(2.7159, 2), ROUND(2.50)



Hasil: +-------------+-------------+------------------+--------------+ | ROUND(2.49) | ROUND(2.50) | ROUND(2.7159, 2) | ROUND(-2.50) | +-------------+-------------+------------------+--------------+ | 2 | 3 | 2.72 | -3 | +-------------+-------------+------------------+--------------+



Fungsi ini banyak digunakan ketika menghitung persentase, misal kita memiliki tabel barang_harga dengan data sebagai berikut: +-----------+-------------+---------+------------+ | id_barang | nama_barang | harga | harga_jual | +-----------+-------------+---------+------------+ | 1 | Televisi | 3500000 | 3250000 | | 2 | AC | 3100000 | 3050000 | | 3 | Kulkas | 2750000 | 2275000 | +-----------+-------------+---------+------------+



Selanjutnya kita hitung persentase potongan harga dengan mengurangkan antara harga_jual dengan harga. Query yang kita jalankan:



Panduan Lengkap Query MySQL 221



1. SELECT nama_barang, harga, harga_jual, 2. CONCAT ( 3. ROUND ( 4. (harga-harga_jual) / harga * 100 5. , 2 6. ), "%" 7. ) AS persen 8. FROM barang_harga



Hasil: +-------------+---------+------------+--------+ | nama_barang | harga | harga_jual | persen | +-------------+---------+------------+--------+ | Televisi | 3500000 | 3250000 | 7.14% | | AC | 3100000 | 3050000 | 1.61% | | Kulkas | 2750000 | 2275000 | 17.27% | +-------------+---------+------------+--------+



Pada contoh diatas, dengan fungsi ROUND (baris 5 - 7) kita bulatkan persentase hingga dua digit di belakang koma, selanjutnya dengan fungsi CONCAT(), kita gabungkan hasilnya dengan tanda persen.



12.6.2. Fungsi FLOOR() Fungsi FLOOR() digunakan untuk melakukan pembulatan desimal ke bawah. Format penulisannya adalah: FLOOR(bilangan)



Contoh: SELECT FLOOR(2.9), FLOOR(-2.10), FLOOR(-2.90)



Hasil: +------------+--------------+--------------+ | FLOOR(2.9) | FLOOR(-2.10) | FLOOR(-2.90) | +------------+--------------+--------------+ | 2 | -3 | -3 | +------------+--------------+--------------+



222 BAB 12 Functions



Contoh penerapan fungsi ini adalah ketika kita mencari rata-rata nilai siswa, misal kita memiliki tabel nilai sebagai berikut: +----------+---------+-------+ | id_siswa | nama | nilai | +----------+---------+-------+ | 1 | Alfa | 83 | | 2 | Beta | 77 | | 3 | Charlie | 64 | | 4 | Delta | 73 | +----------+---------+-------+



Query yang kita jalankan: 1. SELECT AVG(nilai) AS rata_rata, 2. FLOOR( AVG(nilai) ) AS floor_rata_rata 3. FROM nilai



Hasil: +-----------+-----------------+ | rata_rata | floor_rata_rata | +-----------+-----------------+ | 74.25 | 74 | +-----------+-----------------+



Pada contoh diatas, pertama-tama MySQL akan menjalankan fungsi AVG() untuk menghitung rata-rata nilai, selanjutnya MySQL menjalankan fungsi FLOOR() untuk melakukan pembulatan ke bawah.



12.6.3. Fungsi CEIL Kebalikan dari fungsi FLOOR(), fungsi CEIL() digunakan untuk melakukan pembulatan ke atas, misal kita ingin mencari nilai-rata-rata dan membulatkannya ke atas, kita jalankan query berikut: 1. SELECT AVG(nilai) AS rata_rata, 2. FLOOR( AVG(nilai) ) AS floor_rata_rata, 3. CEIL( AVG(nilai) ) AS ceil_rata_rata 4. FROM nilai



Hasil yang kita peroleh: Panduan Lengkap Query MySQL 223



+-----------+-----------------+----------------+ | rata_rata | floor_rata_rata | ceil_rata_rata | +-----------+-----------------+----------------+ | 74.25 | 74 | 75 | +-----------+-----------------+----------------+



12.6.4. Fungsi RAND Fungsi RAND() digunakan untuk menghasilkan nilai random antara 0 dan 1 ( >= 0 dan < 1 ). Format penulisannya adalah: RAND(seed)



Argumen seed bersifat opsional, jika seed didefinisikan, maka nilai random yang dihasilkan akan sama setiap kali seed digunakan, jika argumen tidak diisi, maka setiap kali fungsi RAND() dijalankan, akan menghasilkan nilai yang berbeda beda, contoh: SELECT RAND(), RAND(2), RAND(2)



Hasil: +---------------------+--------------------+--------------------+ | RAND() | RAND(2) | RAND(2) | +---------------------+--------------------+--------------------+ | 0.11291463497366257 | 0.6555866465490187 | 0.6555866465490187 | +---------------------+--------------------+--------------------+



Pada contoh diatas, fungsi RAND() yang menggunakan seed yang sama akan menghasilkan nilai yang sama. Seperti yang telah kita bahas diawal, bahwa fungsi RAND() ini akan selalu menghasilkan nilai dibawah 1, untuk itu jika ingin membuat nilai random dalam batas tertentu, kita bisa menggunakan sedikit trik. Misal kita ingin membuat nilai random dibawah 100, maka kita tinggal mengalikan fungsi RAND() dengan 100, misal: SELECT RAND() * 100, FLOOR( RAND() * 100)



Hasil: 224 BAB 12 Functions



+------------------+----------------------+ | RAND() * 100 | FLOOR( RAND() * 100) | +------------------+----------------------+ | 98.0782223847492 | 41 | +------------------+----------------------+



Pada contoh diatas, kita menggunakan fungsi FLOOR() untuk melakukan pembulatan ke bawah. Selanjutnya, jika kita ingin membuat nilai random untuk range tertentu, gunakan formula berikut: SELECT FLOOR( RAND() * (B - A) ) + A



Contoh: SELECT FLOOR( RAND() * (100 - 80) ) + 80



Hasil: +-----------------------------------+ | FLOOR( RAND() * (100 - 80) ) + 80 | +-----------------------------------+ | 82 | +-----------------------------------+



Nila random akan berubah ubah setiap query dijalankan. Jika disederhanakan, fungsi diatas akan menjadi FLOOR( RAND() * 20 ) + 20, dimana MySQL akan membuat nilai random antara 0 s.d 20 kemudian ditambahkan dengan 80. Dalam praktek, fungsi ini dapat digunakan untuk mengambil data secara acak seperti menampilkan data artikel secara random. Untuk keperluan tersebut, kita letakkan fungsi RAND() pada klausa ORDER BY. Misal kita tampilkan data buku secara acak 1. SELECT id_buku, judul 2. FROM buku 3. ORDER BY RAND()



Hasil:



Panduan Lengkap Query MySQL 225



+---------+-----------------------------------------+ | id_buku | judul | +---------+-----------------------------------------+ | 2 | PHP dan MySQL Langkah Demi Langkah + CD | | 5 | Mahir Dalam 7 Hari: Coreldraw X6 | | 3 | MySQL Untuk Pemula | | 4 | Kumpulan Aplikasi PHP untuk Pemula | | 1 | Pemrograman Database Menggunakan MySQL | +---------+-----------------------------------------+



Query diatas akan menghasilkan output yang berbeda setiap kali dijalankan. Selan pada ORDER BY, fungsi RAND() juga sering digunakan pada klausa WHERE untuk mengambil data secara acak pada range tertentu, misal: 1. 2. 3. 4.



SELECT id_buku, judul FROM buku WHERE id_buku > FLOOR( RAND() * (5-2) ) + 2 LIMIT 1



Hasil: +---------+------------------------------------+ | id_buku | judul | +---------+------------------------------------+ | 4 | Kumpulan Aplikasi PHP untuk Pemula | +---------+------------------------------------+



Pada contoh diatas, kita mengambil 1 buku dengan id_buku antara 3 s.d 5. Output seperti ini juga dapat dihasilkan menggunakan cara lain: 1. 2. 3. 4. 5.



SELECT * FROM tabel_buku WHERE id_buku > 2 ORDER BY RAND() LIMIT 1



Pada query diatas, sebelum di urutkan secara acak, dengan klausa WHERE, kita membatasi buku yang akan ditampilkan, yaitu hanya yang id_buku nya lebih besar daripada 2.



226 BAB 12 Functions



12.6.5. Fungsi POW() dan POWER() Fungsi POW() dan POWER() digunakan untuk menghasilkan bilangan berpangkat, keduanya memiliki fungsi yang sama persis, fungsi POWER() merupakan alias dari fungsi POW(). Format penulisan kedua fungsi tersebut adalah: POW(value, exponent)



Fungsi ini memiliki dua argumen yang wajib diisi, yaitu value berupa angka numerik dan exponent merupakan angka yang digunakan sebagai pangkat, contoh: SELECT POW(2,3), POWER(2,3);



Hasil: +----------+------------+ | POW(2,3) | POWER(2,3) | +----------+------------+ | 8 | 8 | +----------+------------+



Pada contoh diatas, terlihat bahwa fungsi POW() dan POWER() menghasilkan output yang sama. Salah satu penggunaan fungsi ini adalah untuk membuat baris dan kolom dengan jumlah yang sama, misal lima baris dan lima kolom: SELECT POW(5,5);



Query diatas akan menghasilkan angka 25



12.6.6. Fungsi CAST() Ketika menjalankan statemen tertentu, jika diperlukan MySQL mengubah tipe data yang ada, seperti pada statemen yang mengandung operasi aritmetika (*, /, +, -, DIV, %). Misal ketika menjumlahkan string dengan numeric, MySQL akan mengubah string tersebut menjadi numeric, misal: Panduan Lengkap Query MySQL 227



SELECT "1.2" + 3;



Hasil: +-----------+ | '1.2' + 3 | +-----------+ | 4.2 | +-----------+



Pada contoh diatas, MySQL akan mengubah string "1.2" menjadi float 1.2, sehingga ketika dijumlahkan dengan 3, akan menghasilkan 4.2. Model konversi ini disebut type casting, dan karena tidak didefinisikan dengan jelas maka sering disebut implisit casting. Disamping implisit casting, MySQL juga menyediakan eksplisit casting. Eksplisit casting memungkinkan kita untuk mengubah tipe suatu data dari bentuk satu ke bentuk lain. Eksplisit casting ini dilakukan dengan menggunakan fungsi CAST(), adapun format penulisannya adalah: CAST(Expression AS DataType)



Fungsi diatas memiliki dua argumen yang wajib diisi, argumen tersebut agak berbeda dengan fungsi sebelumnya karena terdapat keyword AS yang memisahkan antara argumen satu dengan argumen kedua (biasanya antar argumen dipisah menggunakan koma). Contoh: SELECT CAST('1.2' AS DECIMAL(3,1)) + 3



Hasil: +---------------------------------+ | CAST('1.2' AS DECIMAL(3,1)) + 3 | +---------------------------------+ | 4.2 | +---------------------------------+



228 BAB 12 Functions



Pada contoh diatas, kita mengubah tipe data dari string ('1.2') menjadi tipe data decimal kemudian kita tambah dengan 3, sehingga hasilnya 4.2. Adapun tipe data yang dapat dilakukan konversi seperti pada tabel dibawah ini TIPE DATA



KETERANGAN



BINARY[(N)]



Menghasilkan string dengan tipe data BINARY. Jika opsi N digunakan, maka panjang data yang dihasilkan maksimal N byte



CHAR[(N)]



Menghasilkan string dengan tipe data CHAR. Jika opsi N digunakan, maka jumlah karakter yang dihasilkan sejumlah N



DATE



Menghasilkan tipe data DATE



DATETIME



Menghasilkan tipe data DATETIME



DECIMAL[(M[,D])]



Menghasilkan tipe data DECIMAL, opsi M untuk membatasi jumlah digit maksimal yang akan dihasilkan (termasuk desimal dan koma), sedangkan opsi D untuk membatasi jumlah digit di belakang koma.



JSON (Mulai versi 5.7.8)



Menghasilkan nilai berformat JSON



NCHAR[(N)]



Seperti CHAR, tetapi dengan National Character Set



SIGNED[INTEGER]



Menghasilkan tipe data INTEGER dengan jenis SIGNED yang artinya mencakup nilai positif dan negatif



UNSIGNED[INTEGER]



Menghasilkan tipe data INTEGER dengan jenis UNSIGNED yang artinya hanya mencakup nilai positif saja (termasuk 0 )



TIME



Menghasilkan tipe data TIME Tabel 12.2 Tipe Data yang dapat dilakukan konversi



Salah satu contoh penggunaan fungsi CAST() ini adalah ketika kita ingin mengurutkan kolom yang memiliki tipe data enum. Tipe data enum sering digunakan ketika sebuah kolom hanya memiliki nilai tertentu, misal P atau L. Misal kita memiliki tabel mahasiswa sebagai berikut: Panduan Lengkap Query MySQL 229



+------------+---------------+ | nama_siswa | jenis_kelamin | +------------+---------------+ | Alfa | L | | Beta | P | | Charlie | L | | Delta | P | +------------+---------------+



Dengan struktur:



Gambar 12.1 Struktur tabel mahasiswa Selanjutnya mari kita urutkan data berdasarkan kolom jenis_kelamin. Jalankan query berikut: 1. SELECT * 2. FROM mahasiswa 3. ORDER BY jenis_kelamin ASC



Hasil: +------------+---------------+ | nama_siswa | jenis_kelamin | +------------+---------------+ | Beta | P | | Delta | P | | Alfa | L | | Charlie | L | +------------+---------------+



Pada contoh diatas, seharusnya L berada diatas P, karena dalam urutan abjad, L lebih dulu daripada P. Kenapa hasilnya bisa seperti itu? Pada tipe data ENUM, MySQL akan mengurutkan data berdasarkan index. Pada contoh diatas, tipe data kolom adalah ENUM('P','L'), karena kita menempatkan P di depan, maka P memiliki index lebih kecil dari L, sehingga, ketika diurutkan, maka P akan berada sebelum L. 230 BAB 12 Functions



Untuk mengatasi hal tersebut, kita dapat mengubah urutan nilai pada ENUM, dimana P kita letakkan di belakang L. Cara lain adalah menggunakan fungsi CAST() yaitu dengan mengubah tipe data menjadi CHAR sehingga data dapat diurutkan berdasarkan urutan abjad. Misal kita ubah query menjadi berikut: 1. SELECT * 2. FROM mahasiswa 3. ORDER BY CAST(jenis_kelamin AS CHAR) ASC



Hasil yang kita peroleh adalah: +------------+---------------+ | nama_siswa | jenis_kelamin | +------------+---------------+ | Alfa | L | | Charlie | L | | Beta | P | | Delta | P | +------------+---------------+



Pada contoh diatas, kolom jenis_kelamin kita ubah tipe datanya menjadi CHAR, sehingga L dan P diurutkan berdasarkan urutan pada abjad dimana L lebih kecil daripada P. Contoh lain penggunaan CAST adalah ketika kita ingin mengurutkan data angka, namun tipe data angka tersebut bukan numeric, melainkan character, meskipun kondisi ini tidak ideal, tetapi dalam praktek sangat mungkin terjadi, misal kita memiliki tabel rumah sebagai berikut: +-------------+----------+ | jenis_rumah | no_rumah | +-------------+----------+ | Alfa | 8 | | Bravo | 9 | | Charlie | 12 | | Delta | 10 | | Echo | 11 | +-------------+----------+



Dengan struktur kolom sebagai berikut:



Panduan Lengkap Query MySQL 231



Gamber 12.2 Struktur Tabel Rumah Selanjutnya, kita ingin mengurutkan data rumah berdasarkan kolom no_rumah, jalankan query berikut: 1. SELECT * 2. FROM rumah 3. ORDER BY no_rumah



Hasil: +-------------+----------+ | jenis_rumah | no_rumah | +-------------+----------+ | D | 10 | | E | 11 | | C | 12 | | A | 8 | | B | 9 | +-------------+----------+



Pada tabel diatas, karena tipe data kolom no_rumah adalah VARCHAR, maka data pada kolom no_rumah diurutkan berdasar abjad, sehingga semua yang berawalan 1 berada di depan. Untuk mengubah urutan sesuai angka, maka kita perlu mengubah tipe datanya menjadi numeric (INTEGER), mari kita ubah querynya menjadi: 1. SELECT * 2. FROM rumah 3. ORDER BY CAST(no_rumah AS UNSIGNED)



Hasil:



232 BAB 12 Functions



+-------------+----------+ | jenis_rumah | no_rumah | +-------------+----------+ | Alfa | 8 | | Bravo | 9 | | Delta | 10 | | Echo | 11 | | Charlie | 12 | +-------------+----------+



Sekarang no_rumah diurutkan berdasarkan urutan angka sehingga sudah sesuai dengan yang kita harapkan.



Panduan Lengkap Query MySQL 233



Halaman ini sengaja dikosongkan Jagowebdev.com



234 BAB 12 Functions



BAB 13 Agregate Functions Seperti yang telah kita bahas, bahwa menurut jenisnya, fungsi dibagi menjadi dua, yaitu fungsi skalar (scalar function) dan fungsi agregasi (agregate function). Pada bab sebelumnya telah kita bahas tentang fungsi skalar, pada bab ini kita akan membahas fungsi agregasi. Fungsi agregasi (agregate function) merupakan fungsi yang dalam operasinya melibatkan banyak data. Dalam konteks tabel database, fungsi ini digunakan untuk melakukan perhitungan pada kolom yang berada di baris (row) yang berbeda untuk menghasilkan nilai tertentu. Fungsi ini umumnya didefinisikan pada klausa SELECT, namun demikian, kita dapat mendefinisikannya pada klausa lain seperti pada WHERE atau HAVING



13.1. Jenis Fungsi Agregasi MySQL sendiri telah mendukung banyak fungsi agregasi, namun agar pembahasan tidak terlalu panjang, dan terlebih banyak dari fungsi tersebut yang jarang digunakan, maka pada bab ini kita hanya akan membahas fungsi yang sering digunakan saja. Fungsi agregasi yang sering digunakan seperti tampak pada tabel berikut: No



Nama Fungsi



Keterangan



1



COUNT



Menghitung jumlah baris



2



SUM



Menjumlahkan nilai pada arguman



3



MIN



Mengambil nilai minimal dari argumen



4



MAX



Mengambil nilai maksimal dari argumen



5



AVG



Mengambil nilai rata-rata dari argumen Tabel 13.1 Daftar Fungsi Agregasi



Format umum penulisan fungsi adalah nama_fungsi(argumen) nilai argumen ini sangat fleksibel, bisa nama kolom, fungsi, query SQL, dll, Panduan Lengkap Query MySQL 235



namun pada umumnya, nilai argumen berupa nama kolom atau tanda asterik ( * ).



13.1.1. Fungsi COUNT Fungsi ini digunakan untuk menghitung jumlah row pada kolom tertentu yang tidak mengandung nilai NULL Contoh pada tabel penerbit, terdapat data sebagai berikut: mysql> select id_penerbit, nama, telp from penerbit; +-------------+---------------------------+----------------+ | id_penerbit | nama | telp | +-------------+---------------------------+----------------+ | 1 | Andi Publisher | 0274-561881 | | 2 | Informatika | 0813-2220-1946 | | 3 | PT. Elex Media Komputindo | NULL | | 4 | Jubilee | | | 5 | Lokomedia | 0274-9515000 | | 6 | Maxikom | 0711-7336565 | +-------------+---------------------------+----------------+ 6 rows in set (0.00 sec)



Selanjutnya hitung jumlah penerbit, perintah query yang kita jalankan: SELECT COUNT(*) FROM penerbit



Hasil yang kita peroleh adalah: +----------+ | COUNT(*) | +----------+ | 6 | +----------+



Selanjutnya mari kita hitung jumlah buku berdasarkan nomor telp nya, jalankan query berikut: SELECT COUNT(telp) FROM penerbit;



Hasil yang kita peroleh adalah +-------------+



236 BAB 13 Agregate Functions



| COUNT(telp) | +-------------+ | 5 | +-------------+



Seperti pada penjelasan sebelumnya bahwa yang dihitung adalah data yang tidak bernilai NULL, sehingga, karena pada kolom telp terdapat nilai NULL, maka jumlah yang dihasilkan lebih sedikit dari query sebelumnya. Perlu diingat kembali bahwa NULL tidak sama dengan kosong, NULL artinya tidak terdefinisi, sehingga pada contoh sebelumnya, string kosong pada kolom telp (id_penerbit 4) juga ikut dihitung. Penting juga diperhatikan bahwa NULL juga tidak sama dengan 0 (nol), jika data mengandung nilai 0 maka akan tetap dihitung. Pada query yang kompleks, terkadang secara tidak sengaja kita mendefinisikan nilai 0 pada temporary table sehingga menghasilkan output yang tidak sesuai yang diharapkan. Khusus pada tabel dengan engine MyISAM, penggunaan asterik pada fungsi count COUNT(*) pada statemen SELECT yang hanya melibatkan satu tabel dan tidak ada klausa WHERE, akan diproses MySQL dengan cepat. Hal ini dikarenakan jumlah banyaknya row sudah tersedia, sehingga MySQL tinggal mengambilnya saja.



13.1.2. Fungsi SUM Fungsi SUM() digunakan untuk menjumlahkan data pada ekspresi. Jika data tidak ada, maka fungsi SUM() akan menghasilkan nilai NULL Contoh kita akan menjumlahkan total stok buku, query yang kita jalankan: SELECT SUM(stok) FROM buku



Hasil yang kita peroleh: +-----------+ | SUM(stok) | +-----------+ | 45 |



Panduan Lengkap Query MySQL 237



+-----------+



Contoh lain kita ingin mendapatkan total nilai seluruh buku yang ada, untuk itu kita akan mengalikan jumlah stok dengan harga jual kemudian keseluruhan hasilnya kita jumlahkan. Query yang kita jalankan: SELECT SUM(stok * harga) FROM buku



Hasil yang kita peroleh: +-------------------+ | SUM(stok * harga) | +-------------------+ | 3769400 | +-------------------+



13.1.3. Fungsi MIN Fungsi MIN() digunakan untuk mengambil nilai terkecil dari ekspresi data pada ekspresi. Jika data tidak ditemukan, maka akan menghasilkan nilai NULL. Fungsi MIN() ini selain digunakan pada tipe data numeric ( INT dan FLOAT), juga dapat digunakan pada tipe data lain seperti DATE, TIME, dan string (CHAR dan VARCHAR) Contoh kita ambil data buku dengan stok terkecil, query yang kita jalankan: SELECT MIN(stok) FROM buku



Hasil yang kita peroleh: +-----------+ | MIN(stok) | +-----------+ | 0 | +-----------+



Contoh lain, kita cari data buku yang terbit paling lama, query yang kita jalankan: SELECT judul, MIN(tgl_terbit) AS tgl_terbit FROM buku



238 BAB 13 Agregate Functions



Hasil yang kita peroleh: +----------------------------------------+------------+ | judul | tgl_terbit | +----------------------------------------+------------+ | Pemrograman Database Menggunakan MySQL | 2013-00-00 | +----------------------------------------+------------+



13.1.4. Fungsi MAX Kebalikan dari fungsi MIN(), fungsi MAX() digunakan untuk mengambil nilai terbesar dari ekspresi. Jika data tidak ditemukan, maka akan menghasilkan nilai NULL. Seperti pada fungsi MIN(), fungsi MAX() ini selain dapat digunakan pada tipe data numeric ( INT dan FLOAT), juga dapat digunakan pada tipe data lain seperti DATE, TIME, dan string (CHAR dan VARCHAR) Contoh kita ambil data buku dengan stok terbanyak, query yang kita jalankan: SELECT MAX(stok) FROM buku



Hasil yang kita peroleh: +-----------+ | MAX(stok) | +-----------+ | 6 | +-----------+



Contoh lain, kita cari data buku terbaru, query yang kita jalankan: 1. SELECT judul, MAX(tgl_terbit) AS tgl_terbit 2. FROM buku



Hasil yang kita peroleh: +----------------------------------------+------------+ | judul | tgl_terbit | +----------------------------------------+------------+ | Pemrograman Database Menggunakan MySQL | 2016-08-29 | +----------------------------------------+------------+



Panduan Lengkap Query MySQL 239



13.1.5. Fungsi AVG Fungsi AVG() akan menghasilkan nilai rata-rata dari ekspresi. Jika data tidak ditemukan maka akan menghasilkan nilai NULL. Contoh kita hitung rata-rata harga buku, query yang kita jalankan: 1. SELECT FORMAT(AVG(harga),2) 2. FROM buku



Hasil yang kita peroleh: +----------------------+ | FORMAT(AVG(harga),2) | +----------------------+ | 71,866.67 | +----------------------+



13.2. Menggunakan klausa DISTINCT Pada fungsi agregasi, kita juga dapat menyertakan klausa DISTINCT. Seperti telah kita bahas pada bab sebelumnya, klausa ini akan mengambil data yang nilainya unik. Contoh kita ambil data jumlah penerbit yang menerbitkan buku, query yang kita jalankan: 1. SELECT COUNT(DISTINCT id_penerbit) 2. FROM buku



Hasil yang kita peroleh: +-----------------------------+ | COUNT(DISTINCT id_penerbit) | +-----------------------------+ | 5 | +-----------------------------+



13.3. Fungsi Agregasi Dengan GROUP BY Ketika kita mendefinisikan fungsi agregasi, maka MySQL akan mengelompokkan semua data yang ada (menjalankan klausa GROUB BY di 240 BAB 13 Agregate Functions



belakang layar). Kita dapat memodifikasi GROUP mendefinisikan sendiri klausa GROUP BY



BY ini dengan



Contoh kita tampilkan data penerbit beserta dengan (1) jumlah buku yang diterbitkannya, (2) tanggal terakhir buku diterbitkan, (3) jumlah harga jual, dan (4) total harga jualnya, yang dikelompokkan berdasarkan kolom id_penerbit, query yang kita jalankan: 1. 2. 3. 4. 5. 6. 7. 8. 9.



SELECT nama AS "Nama Penerbit", MAX(tgl_terbit) AS "Terbit Terakhir", COUNT(judul) AS "Jumlah Buku", SUM(harga) AS "Jumlah Harga", COUNT(harga) * SUM(harga) AS "Total Harga" FROM penerbit LEFT JOIN buku USING(id_penerbit) GROUP BY id_penerbit



Hasil yang kita peroleh adalah: +-------------------+-----------------+-------------+--------------+-------------+ | Nama Penerbit | Terbit Terakhir | Jumlah Buku | Jumlah Harga | Total Harga | +-------------------+-----------------+-------------+--------------+-------------+ | Andi Publisher | 2016-00-00 | 9 | 918000 | 8262000 | | Informatika | NULL | 0 | NULL | NULL | | PT. Elex Media ...| 2015-06-15 | 5 | 243000 | 1215000 | | Jubilee | 2016-08-29 | 4 | 156200 | 624800 | | Lokomedia | 2015-12-22 | 2 | 127000 | 254000 | | Maxikom | NULL | 0 | NULL | NULL | +-------------------+-----------------+-------------+--------------+-------------+



Pada query diatas, terdapat dua penerbit yang tidak ada data bukunya. Seperti yang telah kita bahas pada bab sebelumnya, kita dapat melakukan pengelompokan (GROUP BY) lebih dari satu kolom. Mari kita modifikasi query dengan mengubah tanggal terbit buku menjadi tahun terbit buku dan data kita kelompokkan berdasarkan kolom id_penerbit dan tahun terbit buku. Query yang kita jalankan: 1. SELECT nama AS "Nama Penerbit", 2. MAX(YEAR(tgl_terbit)) AS "Tahun Terbit", 3. SUM(stok) AS "Jumlah Buku", 4. SUM(harga) AS "Jumlah Harga",



Panduan Lengkap Query MySQL 241



5. SUM(stok) * SUM(harga) AS "Total Harga" 6. FROM buku 7. LEFT JOIN penerbit 8. USING(id_penerbit) 9. GROUP BY id_penerbit, YEAR(tgl_terbit)



Hasil yang kita peroleh: +-------------------+--------------+-------------+--------------+-------------+ | Nama Penerbit | Tahun Terbit | Jumlah Buku | Jumlah Harga | Total Harga | +-------------------+--------------+-------------+--------------+-------------+ | Andi Publisher | 2013 | 8 | 230000 | 1840000 | | Andi Publisher | 2014 | 3 | 139000 | 417000 | | Andi Publisher | 2015 | 8 | 346000 | 2768000 | | Andi Publisher | 2016 | 13 | 203000 | 2639000 | | PT. Elex Media ...| 2013 | 0 | 49800 | 0 | | PT. Elex Media ...| 2014 | 0 | 159400 | 0 | | PT. Elex Media ...| 2015 | 1 | 33800 | 33800 | | Jubilee | 2014 | 4 | 34800 | 139200 | | Jubilee | 2016 | 3 | 121400 | 364200 | | Lokomedia | 2015 | 0 | 127000 | 0 | | NULL | 2016 | 5 | 65000 | 325000 | +-------------------+--------------+-------------+--------------+-------------+



13.4. Fungsi Agregasi Dengan ORDER BY Ketika menggunakan fungsi agregat dan jumlah row yang dihasilkan lebih dari satu, maka kita dapat mengurutkan data tersebut menggunakan klausa ORDER BY. Melanjutkan contoh sebelumnya, mari kita ubah querynya dengan menambahkan klausa ORDER BY 1. 2. 3. 4. 5. 6. 7. 8. 9.



SELECT nama AS nama_penerbit, MAX(YEAR(tgl_terbit)) AS tahun_terbit, COUNT(judul) AS jumlah_buku, SUM(harga) AS jumlah_harga, COUNT(harga) * SUM(harga) AS total_harga FROM penerbit LEFT JOIN buku USING(id_penerbit) GROUP BY id_penerbit ORDER BY tahun_terbit DESC



Hasil yang kita peroleh: +-------------------+--------------+-------------+--------------+-------------+ | nama_penerbit | tahun_terbit | jumlah_buku | jumlah_harga | total_harga | +-------------------+--------------+-------------+--------------+-------------+



242 BAB 13 Agregate Functions



| Jubilee | 2016 | 4 | 156200 | 624800 | | Andi Publisher | 2016 | 9 | 918000 | 8262000 | | Lokomedia | 2015 | 2 | 127000 | 254000 | | PT. Elex Media... | 2015 | 5 | 243000 | 1215000 | | Maxikom | NULL | 0 | NULL | NULL | | Informatika | NULL | 0 | NULL | NULL | +-------------------+--------------+-------------+--------------+-------------+



Perhatikan bahwa pada contoh diatas, kita menggunakan alias tahun_terbit pada klausa MAX(YEAR(tgl_terbit)) AS tahun_terbit. Pada contoh sebelumnya kita menggunakan alias “Tahun Terbit”



13.5. Fungsi Agregasi Dengan Having Umumnya, kita memfilter output dari data menggunakan klausa WHERE. Seperti telah kita bahas pada BAB 4, bahwa klausa WHERE ini hanya berlaku untuk “real” table artinya tabel yang sudah terbentuk, baik tabel permanen yang berada pada database maupun temporary tabel yang dibuat oleh MySQL ketika menjalankan suatu query. Pada contoh sebelumnya kita sering menggunakan kolom alias, untuk memfilter data berdasarkan kolom alias ini, kita gunakan klausa HAVING. Klausa ini telah kita bahas pada BAB 4. Melanjutkan contoh sebelumnya, mari kita batasi data yang ditampilkan hanya pada data buku yang terbit setelah tahun 2014. Query yang kita jalankan: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.



SELECT nama AS nama_penerbit, MAX(YEAR(tgl_terbit)) AS tahun_terbit, COUNT(judul) AS jumlah_buku, SUM(harga) AS jumlah_harga, COUNT(harga) * SUM(harga) AS total_harga FROM penerbit LEFT JOIN buku USING(id_penerbit) GROUP BY id_penerbit HAVING tahun_terbit > 2014 ORDER BY tahun_terbit DESC



Hasil yang kita peroleh:



Panduan Lengkap Query MySQL 243



+-------------------+--------------+-------------+--------------+-------------+ | nama_penerbit | tahun_terbit | jumlah_buku | jumlah_harga | total_harga | +-------------------+--------------+-------------+--------------+-------------+ | Jubilee | 2016 | 4 | 156200 | 624800 | | Andi Publisher | 2016 | 9 | 918000 | 8262000 | | Lokomedia | 2015 | 2 | 127000 | 254000 | | PT. Elex Media... | 2015 | 5 | 243000 | 1215000 | +-------------------+--------------+-------------+--------------+-------------+



13.6. Fungsi Agregasi Dengan Limit Seperti pada SQL umumnya, kita juga dapat membatasi output dari fungsi agregasi dengan klausa LIMIT, misal dari Query sebelumnya, kita batasi jumlah yang ditampilkan sebanyak lima baris pertama, query yang kita jalankan: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.



SELECT nama AS nama_penerbit, MAX(YEAR(tgl_terbit)) AS tahun_terbit, COUNT(judul) AS jumlah_buku, SUM(harga) AS jumlah_harga, COUNT(harga) * SUM(harga) AS total_harga FROM penerbit LEFT JOIN buku USING(id_penerbit) GROUP BY id_penerbit HAVING tahun_terbit > 2014 ORDER BY tahun_terbit DESC LIMIT 3



Hasil yang kita peroleh: +----------------+--------------+-------------+--------------+-------------+ | nama_penerbit | tahun_terbit | jumlah_buku | jumlah_harga | total_harga | +----------------+--------------+-------------+--------------+-------------+ | Jubilee | 2016 | 4 | 156200 | 624800 | | Andi Publisher | 2016 | 9 | 918000 | 8262000 | | Lokomedia | 2015 | 2 | 127000 | 254000 | +----------------+--------------+-------------+--------------+-------------+



13.7. Fungsi Agregasi Dengan Hasil NULL Seperti yang telah kita bahas, jika tidak menemukan row yang dimaksud dalam query maka fungsi agregasi akan menghasilkan nilai NULL. Terkadang, hasil dari fungsi agregasi tersebut akan kita olah lebih lanjut 244 BAB 13 Agregate Functions



dengan operasi aritmetika sehingga jika nilainya NULL akan menimbulkan error. Untuk mengubah NULL menjadi nilai lain, kita menggunakan fungsi COALESCE. Misal kita ingin menghitung jumlah stok buku yang diterbitkan oleh Studio Press. Query yang kita jalankan: 1. 2. 3. 4.



SELECT COALESCE(SUM(stok), 0) AS jumlah_buku FROM penerbit LEFT JOIN buku USING(id_penerbit) WHERE nama LIKE "%Studio Press%";



Hasil yang kita peroleh: +-------------+ | jumlah_buku | +-------------+ | 0 | +-------------+



Pada contoh diatas, karena tidak ada buku yang diterbitkan oleh Studio Press, maka nilai yang dihasilkan adalah NULL, dengan fungsi COALESCE, MySQL akan mengambil argumen berikutnya yaitu angka 0, sehingga hasil yang kita peroleh bukan NULL melainkan 0. Fungsi COALESCE memiliki dua argumen atau lebih, jika argumen pertama bernilai NULL, maka akan di diambil argumen ke dua, jika argumen kedua juga NULL, diambil argumen ke tiga, dan seterusnya hingga menemukan nilai selain NULL.



Panduan Lengkap Query MySQL 245



Halaman ini sengaja dikosongkan http://jagowebdev.com



246 BAB 13 Agregate Functions



BAB 14 Ekspresi Logika Pada bab ini kita akan membahas tentang ekspresi logika. Seperti pada bahasa pemrograman umumya, ekspresi logika ini digunakan untuk menguji suatu nilai baik nilai pada suatu kolom maupun nilai berupa ekspresi. MySQL menyediakan dua jenis ekspresi logika yaitu ekspresi IF dan CASE, keduanya akan kita bahas pada bab ini.



14.1. Ekspresi Logika IF Ekspresi IF memungkinkan kita mengubah output yang disajikan kepada pengguna berdasarkan satu atau beberapa kondisi yang diterapkan pada nilai suatu kolom atau elemen data. Penulisan ekspresi IF diawali dengan keyword IF. Penulisan IF bersifat case insensitive yang artinya tidak membedakan huruf besar atau kecil, sehingga kita dapat menuliskan IF, If, atau IF, namun demikian, agar dapat dibedakan antara keyword SQL dengan klausa lain, sebaiknya ditulis menggunakan huruf besar semua. Ekspresi IF dapat digunakan di berbagai tempat baik pada klausa SELECT, GROUP BY, ORDER BY, WHERE, dan HAVING, beberapa diantaranya kita bahas pada bab ini. Pada MySQL, ekspresi IF dapat dibagi menjadi dua bentuk yaitu IF sebagai fungsi dan IF sebagai statemen. Perbedaan keduanya adalah jika pada bentuk statemen, kita dapat mengevaluasi beberapa kondisi, sedangkan jika menggunakan fungsi, kita hanya bisa mengevaluasi satu kondisi.



14.1.1. Fungsi IF Bentuk pertama ekspresi IF adalah fungsi. Seperti telah disinggung sebelumnya bahwa penggunaan bentuk fungsi hanya dapat digunakan untuk mengevaluasi satu kondisi, sehingga hanya gunakan bentuk ini jika



Panduan Lengkap Query MySQL 247



kondisi yang ingin diuji berbentuk tunggal. Format penulisan fungsi IF adalah: IF (ekspresi1, ekspresi2, ekspresi3)



Jika ekspresi1 bernilai true (tidak sama dengan 0 atau tidak sama dengan NULL) maka jalankan ekspresi2, jika tidak, jalankan ekspresi3. Contoh sederhana: SELECT IF (1-1, "True", "False") AS Hasil;



Hasil yang kita peroleh: +-------+ | Hasil | +-------+ | False | +-------+



Pada contoh diatas, karena 1 dikurangi 1 hasilnya 0, maka nilai ekspresi1 adalah false, sehingga output yang dihasilkan adalah False. Hasil tersebut akan sama jika kita menjalankan query berikut ini: SELECT IF (NULL, "True", "False") AS Hasil;



Berikutnya, mari kita gunakan fungsi ini untuk menguji kondisi nilai suatu tabel. Misal kita akan menampilkan data stok buku. Jika nilainya tidak sama dengan 0, maka kita ubah output menjadi “Stok Ada” jika tidak, maka akan menghasilkan output “Stok Kosong”. Mari kita jalankan query berikut: 1. SELECT judul, IF (stok = 0, "Stok Kosong", "Stok Ada") AS Stok 2. FROM buku 3. LIMIT 10;



Hasil yang kita peroleh: +-----------------------------------------+-------------+ | judul | Stok | +-----------------------------------------+-------------+ | Pemrograman Database Menggunakan MySQL | Stok Ada |



248 BAB 14 Ekspresi Logika



| PHP dan MySQL Langkah Demi Langkah + CD | Stok Ada | | MySQL Untuk Pemula | Stok Ada | | ... | ... | | Desain Grafis dengan Powerpoint | Stok Kosong | | Otodidak Membuat Blog dengan Blogger | Stok Kosong | +-----------------------------------------+-------------+



Selain bentuk string, kita juga dapat mengisi nilai ekspresi dengan bentuk lain, contoh kita ubah ekspresi2 dengan menampilkan jumlah stok, output yang akan kita tampilkan “Stok xx buah” , jalankan query berikut: 1. SELECT judul, IF (stok = 0, "Stok Kosong", CONCAT("Stok ",stok," buku")) AS Stok 2. FROM buku 3. LIMIT 10;



Hasil yang kita peroleh: +-----------------------------------------+-------------+ | judul | Stok | +-----------------------------------------+-------------+ | Pemrograman Database Menggunakan MySQL | Stok 5 buku | | PHP dan MySQL Langkah Demi Langkah + CD | Stok 6 buku | | MySQL Untuk Pemula | Stok 4 buku | | ... | ... | | Desain Grafis dengan Powerpoint | Stok Kosong | | Otodidak Membuat Blog dengan Blogger | Stok Kosong | +-----------------------------------------+-------------+



Pada contoh diatas, ekspresi2 kita isi dengan fungsi CONCAT(). Fungsi isi kita gunakan untuk menggabungkan string dengan nilai pada kolom stok, Anda dapat ber-eksperimen dengan nilai lain, misal jika stok kosong tampilkan “Stok Kosong", selain itu tampilkan jumlah stok, : IF(stok=0, "Stok Kosong", stok) Pada contoh diatas, kita menggunakan assignment operator ( = ) untuk menguji nilai stok. Tidak terbatas pada itu, kita juga dapat menggunakan berbagai operator lainnya seperti LIKE, AND, OR, dll misal kita tes apakah judul buku mengandung kata-kata SQL, jika ya kita tampilkan output YA, jika tidak kita hasilkan output TIDAK.



Panduan Lengkap Query MySQL 249



1. SELECT judul, IF (judul LIKE "%SQL%", "YA", "Tidak") AS "Buku SQL" 2. FROM buku 3. LIMIT 5;



Hasil yang kita peroleh: +-----------------------------------------+----------+ | judul | Buku SQL | +-----------------------------------------+----------+ | Pemrograman Database Menggunakan MySQL | YA | | PHP dan MySQL Langkah Demi Langkah + CD | YA | | MySQL Untuk Pemula | YA | | Kumpulan Aplikasi PHP untuk Pemula | Tidak | | Pemrograman PHP Dan MySQL Untuk Pemula | YA | +-----------------------------------------+----------+



Contoh lain, dengan operator AND kita uji apakah judul buku mengandung kata-kata PHP dan MySQL: 1. SELECT judul, IF (judul LIKE "%php%" AND judul LIKE "%MySQL%", 2. "YA", 3. "Tidak" 4. ) AS "Buku SQL" 5. FROM buku 6. LIMIT 10;



Hasil yang kita peroleh: +-----------------------------------------+----------+ | judul | Buku SQL | +-----------------------------------------+----------+ | Pemrograman Database Menggunakan MySQL | Tidak | | PHP dan MySQL Langkah Demi Langkah + CD | YA | | MySQL Untuk Pemula | Tidak | | Kumpulan Aplikasi PHP untuk Pemula | Tidak | | Pemrograman PHP Dan MySQL Untuk Pemula | YA | +-----------------------------------------+----------+



Contoh fungsi IF pada klausa WHERE 1. SELECT judul, stok



250 BAB 14 Ekspresi Logika



2. FROM buku 3. WHERE stok > IF(stok > 0, 0, 1) 4. LIMIT 5;



Hasil: +-----------------------------------------+------+ | judul | stok | +-----------------------------------------+------+ | Pemrograman Database Menggunakan MySQL | 5 | | PHP dan MySQL Langkah Demi Langkah + CD | 6 | | MySQL Untuk Pemula | 4 | | Kumpulan Aplikasi PHP untuk Pemula | 3 | | Pemrograman PHP Dan MySQL Untuk Pemula | 2 | +-----------------------------------------+------+



14.1.2. Nested IF Selain bentuk sederhana seperti yang kita bahas pada sub bab sebelumnya, fungsi IF juga dapat berbentuk nested, yang artinya IF di dalam IF. Bentuk IF ini sama seperti ketika kita membuat ternary operator pada bahasa pemrograman PHP, ASP, atau pada Microsoft EXCEL. Format penulisan nested IF adalah: IF(ekspresi1, nilai1, IF(ekspresi2, nilai2, IF(ekspresi3, nilai3, nilai_lain) ) )



Penjelasan: 



Jika ekspresi1 bernilai true, maka gunakan nilai1, jika tidak, maka jalankan ekspresi2







Jika ekspresi2 bernilai true, maka gunakan nilai2, jika tidak, maka jalankan ekspresi3







Jika ekpresi3 bernilai true, maka gunakan nilai3, jika tidak, gunakan nilai lain







Dan seterusnya Panduan Lengkap Query MySQL 251



Alur logika bentuk nested IF diatas sama seperti bentuk logika IF pada format umum seperti berikut ini:



IF (ekspresi1) { nilai1; } ELSE IF (ekspresi2) { nilai2; } ELSE IF (ekspresi3) { ilai3; } ELSE { nilai_lain; }



Contoh sederhana: 1. SELECT IF (1-1, "Nilai 1", 2. IF (2-2, "Nilai 2", 3. IF (3-3, "Nilai 3", "Nilai lain") 4. ) 5. ) AS hasil



Hasil: +------------+ | hasil | +------------+ | Nilai lain | +------------+



Pada contoh diatas, hasil yang kita peroleh adalah "Nilai lain", hal ini disebabkan karena 1-1, 2-2, dan 3-3 nilainya 0 yang artinya false Selanjutnya, mari kita tampilkan data stok buku dengan kata-kata yang mewakili kondisi jumlah stok. Adapun kriterianya adalah sebagai berikut: 



Jika jumlah stok = 0, maka tampilkan kata-kata Stok habis.







Jika jumlah stok 1 s.d 2, maka tampilkan kata-kata Stok tinggal sedikit.







Jika jumlah stok lebih 3 s.d 4, maka tampilkan kata-kata Stok cukup







Selain itu, tampilkan kata-kata Stok banyak



252 BAB 14 Ekspresi Logika



Query yang kita jalankan adalah: 1. SELECT JUDUL, 2. IF(stok = 0, "Stok habis", 3. IF(stok > 0 AND stok < 3, "Stok tinggal sedikit", 4. IF(stok > 2 AND stok < 5, "Stok cukup", "Stok banyak") 5. ) 6. ) AS jumlah_stok 7. FROM buku;



Hasil yang kita peroleh adalah: +-------------------------------------------------------+----------------------+ | JUDUL | jumlah_stok | +-------------------------------------------------------+----------------------+ | Pemrograman Database Menggunakan MySQL | Stok banyak | | PHP dan MySQL Langkah Demi Langkah + CD | Stok banyak | | MySQL Untuk Pemula | Stok cukup | | Kumpulan Aplikasi PHP untuk Pemula | Stok cukup | | Pemrograman PHP Dan MySQL Untuk Pemula | Stok tinggal sedikit | | Blogger untuk Pemula | Stok tinggal sedikit | | Ide Bisnis Bermodal Blog | Stok habis | | ... | ... | +-------------------------------------------------------+----------------------+



Dengan nested IF ini, ekspresi yang dapat kita evaluasi jumlahnya tidak terbatas, namun demikian bentuk ini akan menjadi sulit dipahami jika ekspresi yang kita evaluasi lebih dari dua, untuk itu, ada bentuk lain yang lebih mudah digunakan yaitu menggunakan ekspresi CASE



14.1.3. Statemen IF Pada MySQL, ekspresi IF juga dapat berbentuk statement, bentuk ini berupa control flow statement seperti statement IF pada bahas pemrograman umum, seperti PHP. Dengan bentuk control flow memudahkan kita untuk memahami alur logika yang ada. Namun demikian, bentuk ini tidak dapat digunakan pada statemen SELECT dan klausa yang mengikutinya, seperti klausa WHERE, melainkan hanya dapat digunakan pada stored routines, seperti stored procedure dan stored function.



Panduan Lengkap Query MySQL 253



Stored routines dibahas pada bab tersendiri termasuk penggunaan statemen IF, sebagai gambaran, berikut ini format penulisan statemen IF: IF ekspresi1 THEN nilai1 ELSEIF ekspresi2 THEN nilai2 ELSEIF ekspresi3 THEN nilai3 ELSE nilai_lain END IF



14.2. Ekspresi CASE Ekspresi CASE ini memiliki fungsi seperti fungsi IF, yaitu mengubah output data/nilai suatu kolom sesuai dengan kriteria yang telah ditetapkan. Ekspresi CASE juga dapat digunakan diberbagai klausa baik SELECT, GROUP BY, ORDER BY, HAVING, dan WHERE. Pada ekspresi CASE, kita mengenal dua macam istilah yaitu “Simple Case Expression” (Ekspresi CASE Sederhana) dan “Searched CASE Expression” (Ekspresi CASE Pencarian). Simple CASE Expression Bentuk pertama dari ekspresi CASE adalah Simple Case Expression. Pada ekspresi ini, kita hanya menguji satu nilai. Adapun format penulisannya adalah: SELECT CASE nama_kolom WHEN "Nilai1" THEN "Hasil1" WHEN "Nilai2" THEN "Hasil2" ... [ELSE "Nilai lain"] END FROM nama_tabel



Pada query diatas, MySQL akan menguji nilai pada kolom nama_kolom. Jika nilai pada nama_kolom = Nilai1, maka output yang dihasilkan Hasil1 jika nilai pada nama_kolom = Nilai2 maka output yang dihasilkan Hasil2 demikian seterusnya hingga tidak terbatas. Terakhir, jika semua kriteria



254 BAB 14 Ekspresi Logika



tidak terpenuhi, maka akan menghasilkan nilai yang ada pada klausa ELSE. Klausa ELSE bersifat optional, boleh tidak digunakan. Contoh penerapan pada tabel: 1. SELECT judul, 2. CASE stok 3. WHEN 0 THEN "Stok Habis" 4. END AS status_stok 5. FROM buku



Hasil yang kita peroleh: +-------------------------------------------------------+-------------+ | judul | status_stok | +-------------------------------------------------------+-------------+ | Pemrograman Database Menggunakan MySQL | NULL | | PHP dan MySQL Langkah Demi Langkah + CD | NULL | | MySQL Untuk Pemula | NULL | | Kumpulan Aplikasi PHP untuk Pemula | NULL | | Pemrograman PHP Dan MySQL Untuk Pemula | NULL | | Blogger untuk Pemula | NULL | | Ide Bisnis Bermodal Blog | Stok Habis | | Jago Wordpress | Stok Habis | | ... | ... | +-------------------------------------------------------+-------------+



Pada contoh diatas, stok yang nilainya lebih dari satu akan bernilai NULL, hal ini karena kita tidak mendefinisikan kriteria tersebut, mari kita ubah query diatas dengan menambahkan klausa ELSE. Jalankan query berikut: 1. SELECT judul, 2. CASE stok 3. WHEN 0 THEN "Stok Habis" 4. ELSE "Stok Tersedia" 5. END 6. FROM buku



Hasil yang kita peroleh adalah: +-------------------------------------------------------+---------------+ | judul | status_stok | +-------------------------------------------------------+---------------+ | Pemrograman Database Menggunakan MySQL | Stok Tersedia | | PHP dan MySQL Langkah Demi Langkah + CD | Stok Tersedia | | MySQL Untuk Pemula | Stok Tersedia | | Kumpulan Aplikasi PHP untuk Pemula | Stok Tersedia |



Panduan Lengkap Query MySQL 255



| Pemrograman PHP Dan MySQL Untuk Pemula | Stok Tersedia | | Blogger untuk Pemula | Stok Tersedia | | Ide Bisnis Bermodal Blog | Stok Habis | | Jago Wordpress | Stok Habis | | ... | ... | +-------------------------------------------------------+---------------+



Tidak hanya berupa string, output/hasil juga dapat kita isi dengan ekspresi tertentu, misal kita tampilkan harga diskon pada buku tertentu berdasarkan ID, jalankan query berikut: 1. SELECT id_buku, judul, harga, 2. CASE id_buku 3. WHEN 1 THEN harga - ROUND(harga * 0.25) 4. WHEN 2 THEN harga - ROUND(harga * 0.20) 5. ELSE harga 6. END AS harga_diskon 7. FROM buku 8. LIMIT 5;



Hasil yang kita peroleh: +---------+-----------------------------------------+-------+--------------+ | id_buku | judul | harga | harga_diskon | +---------+-----------------------------------------+-------+--------------+ | 1 | Pemrograman Database Menggunakan MySQL | 59000 | 44250 | | 2 | PHP dan MySQL Langkah Demi Langkah + CD | 75000 | 60000 | | 3 | MySQL Untuk Pemula | 34800 | 34800 | | 4 | Kumpulan Aplikasi PHP untuk Pemula | 34800 | 34800 | | 5 | Pemrograman PHP Dan MySQL Untuk Pemula | 69000 | 69000 | +---------+-----------------------------------------+-------+--------------+



Pada contoh diatas, karena kita mengalikan harga dengan bilangan desimal, maka hasilnya juga akan berbentuk desimal, untuk membulatkan bilangan desimal, kita gunakan fungsi ROUND() Searched CASE Expression Ekspresi CASE bentuk kedua adalah bentuk Searched Case Expression. Jika sebelumnya kita menguji suatu nilai, pada bentuk ini, kita menguji ekspresi. Adapun format penulisannya adalah:



256 BAB 14 Ekspresi Logika



SELECT CASE WHEN ekspresi1 THEN Hasil1 WHEN ekspresi1 THEN Hasil2 ... [ELSE Hasil_Lain] END FROM nama_tabel



Pada format diatas, pertama tama ekspresi1 dievaluasi, jika bernilai true, maka dihasilkan Hasil1, jika false, maka ekspresi2 akan dievaluasi, jika nilainya true, maka dihasilkan Hasil2, begitu seterusnya. Jika semua kondisi tidak terpenuhi, maka akan dihasilkan nilai pada ekspresi ELSE. Sama seperti sebelumnya, ekspresi ELSE bersifat opsional, boleh tidak digunakan. Contoh: 1. SELECT judul, 2. CASE 3. WHEN stok = 0 THEN "Stok Habis" 4. WHEN stok > 0 AND stok < 3 THEN "Stok Sedikit" 5. WHEN stok > 2 AND stok < 5 THEN "Stok Cukup" 6. ELSE "Stok Banyak" 7. END AS status_stok 8. FROM buku



Hasil: +-------------------------------------------------------+--------------+ | judul | status_stok | +-------------------------------------------------------+--------------+ | Pemrograman Database Menggunakan MySQL | Stok Banyak | | PHP dan MySQL Langkah Demi Langkah + CD | Stok Banyak | | MySQL Untuk Pemula | Stok Cukup | | Kumpulan Aplikasi PHP untuk Pemula | Stok Cukup | | Pemrograman PHP Dan MySQL Untuk Pemula | Stok Sedikit | | Blogger untuk Pemula | Stok Sedikit | | Ide Bisnis Bermodal Blog | Stok Habis | | ... | ... | +-------------------------------------------------------+--------------+



Jika diperhatikan, bentuk simple dan bentuk searched hampir sama, bedanya, pada bentuk simple, nama kolom ditulis setelah keyword CASE, sedangkan pada bentuk searched, nama kolom ditulis pada setiap klausa



Panduan Lengkap Query MySQL 257



WHEN. Selain itu, pada bentuk simpel kita hanya bisa mengevaluasi nilai pada satu kolom.



Selanjutnya, misal kita mempunyai tabel buku dengan data sebagai berikut: +---------+----------------------------------------+-----+-------+------+ | id_buku | judul | php | mysql | blog | +---------+----------------------------------------+-----+-------+------+ | 1 | Pemrograman Database Menggunakan MySQL | | X | | | 2 | MySQL Untuk Pemula | | X | | | 3 | Kumpulan Aplikasi PHP untuk Pemula | X | | | | 4 | Blogger untuk Pemula | | | X | | 5 | Jago Wordpress | | | X | +---------+----------------------------------------+-----+-------+------+



Pada tabel diatas, kategori buku dibuat menjadi beberapa kolom. Sebagai contoh, nilai X pada kolom php menandakan bahwa kategori buku tersebut adalah php. Dengan demikian, ketika menampilkan kategori buku dalam satu kolom, maka mustahil untuk menggunakan ekspresi CASE bentuk simpel, karena, seperti yang telah disampaikan, bentuk simpel hanya digunakan untuk mengevaluasi satu kolom, sebaliknya bentuk searched dapat digunakan untuk mengevaluasi beberapa kolom. Mari kita tampilkan data judul buku beserta kategorinya menggunakan query berikut: 1. SELECT judul, 2. CASE 3. WHEN php = "x" THEN "PHP" 4. WHEN mysql = "x" THEN "MySQL" 5. WHEN blog = "x" THEN "Blog" 6. END AS Kategori 7. FROM buku



Hasil yang kita peroleh: +----------------------------------------+----------+ | judul | Kategori | +----------------------------------------+----------+ | Pemrograman Database Menggunakan MySQL | MySQL | | MySQL Untuk Pemula | MySQL | | Kumpulan Aplikasi PHP untuk Pemula | PHP | | Blogger untuk Pemula | Blog |



258 BAB 14 Ekspresi Logika



| Jago Wordpress | Blog | +----------------------------------------+----------+



Ekspresi CASE banyak digunakan untuk berbagai keperluan, salah satunya digunakan ketika kita menggunakan operator pembagian dimana jika penyebutnya bernilai 0, maka akan muncul pesan error yang memperingatkan bahwa bilangan tidak bisa dibagi dengan 0. Dengan menggunakan ekspresi CASE, kita dapat melakukan pengujian apakah bilangan yang akan menjadi penyebut nilainya 0. Contoh: SELECT nama_barang, harga, harga_jual, CASE WHEN harga = 0 THEN 0 ELSE ROUND((harga - harga_jual) / harga, 2) END AS diskon FROM barang_harga



Pada contoh diatas, dengan ekspresi CASE kita uji apakah penyebutnya yaitu kolom harga bernilai 0, jika ya, maka hasilkan nilai 0, jika tidak maka hitung nilai diskon.



14.3. Ekspresi CASE Pada ORDER BY Seperti telah kita bahas pada awal bab ini bahwa kita dapat menggunakan ekspresi CASE di berbagai klausa yang salah satunya adalah klausa ORDER BY. Sebagai ilustrasi misal kita memiliki tabel buku beserta daftar harganya sebagai berikut: +---------+----------------------------------------+-------+ | id_buku | judul | harga | +---------+----------------------------------------+-------+ | 1 | Pemrograman Database Menggunakan MySQL | 0 | | 2 | MySQL Untuk Pemula | 45000 | | 3 | Kumpulan Aplikasi PHP untuk Pemula | 55000 | | 4 | Blogger untuk Pemula | 50000 | | 5 | Jago Wordpress | 0 | +---------+----------------------------------------+-------+



Panduan Lengkap Query MySQL 259



Selanjutnya kita akan mengurutkan harga dari yang paling murah ke yang paling mahal, namun untuk harga 0, kita tempatkan dibagian paling bawah. Query yang kita jalankan adalah: 1. SELECT * 2. FROM buku 3. ORDER BY 4. CASE 5. 6. 7. 8. END



WHEN harga = 0 THEN judul ELSE harga



Hasil yang kita peroleh adalah: +---------+----------------------------------------+-------+ | id_buku | judul | harga | +---------+----------------------------------------+-------+ | 2 | MySQL Untuk Pemula | 45000 | | 4 | Blogger untuk Pemula | 50000 | | 3 | Kumpulan Aplikasi PHP untuk Pemula | 55000 | | 5 | Jago Wordpress | 0 | | 1 | Pemrograman Database Menggunakan MySQL | 0 | +---------+----------------------------------------+-------+



Pada contoh diatas, jika harganya 0 maka urutkan data berdasarkan judul, jika tidak maka urutkan data berdasarkan harganya. Contoh lain misalkan kita memiliki tabel penjualan yang terdiri dari kolom judul_buku, tgl_order, status order. +------------------------------------+---------+------------+ | judul_buku | status | tgl_order | +------------------------------------+---------+------------+ | Blogger untuk Pemula | selesai | 2017-02-17 | | Ide Bisnis Bermodal Blog | proses | 2017-02-16 | | Jago Wordpress | proses | 2017-02-17 | | Kumpulan Aplikasi PHP untuk Pemula | selesai | 2017-02-15 | | MySQL Untuk Pemula | proses | 2017-02-11 | +------------------------------------+---------+------------+



Selanjutnya, kita akan menampilkan data yang diurutkan berdasarkan tgl_order dengan kriteria (1) jika statusnya proses, urutakan data secara



260 BAB 14 Ekspresi Logika



ascending sedangkan (2) jika statusnya selesai, urutkan data secara descending. Query yang kita jalankan: 1. SELECT * FROM buku_sales 2. ORDER BY 3. CASE 4. WHEN status = "selesai" THEN tgl_order 5. END ASC, 6. CASE 7. WHEN status = "proses" THEN tgl_order 8. END DESC



Hasil yang kita peroleh: +------------------------------------+---------+------------+ | judul_buku | status | tgl_order | +------------------------------------+---------+------------+ | Jago Wordpress | proses | 2017-02-17 | | Ide Bisnis Bermodal Blog | proses | 2017-02-16 | | MySQL Untuk Pemula | proses | 2017-02-11 | | Kumpulan Aplikasi PHP untuk Pemula | selesai | 2017-02-15 | | Blogger untuk Pemula | selesai | 2017-02-17 | +------------------------------------+---------+------------+



Dalam praktek, terdapat banyak kasus yang perlu diselesaikan dengan cara seperti diatas, intinya kita pahami terlebih alur logikanya selanjutnya terjemahkan ke dalam query SQL.



14.4. Ekspresi CASE Pada WHERE Sama seperti pada klausa ORDER BY, kita juga dapat menggunakan ekspresi CASE pada klausa WHERE. Misal melanjutkan contoh pada tabel sebelumnya, kita akan menampilkan semua data penjualan yang statusnya masih proses, namun untuk data yang statusnya sudah selesai, kita hanya menampilkan data pada bulan Februari saja. Query yang kita jalankan:



Panduan Lengkap Query MySQL 261



1. SELECT * FROM buku_sales 2. WHERE tgl_order > CASE 3. WHEN status = "selesai" THEN "2017-02-00" 4. WHEN status = "proses" THEN "0000-00-00" 5. END



Hasil yang kita peroleh: +--------------------------+---------+------------+ | judul_buku | status | tgl_order | +--------------------------+---------+------------+ | Blogger untuk Pemula | selesai | 2017-02-17 | | Ide Bisnis Bermodal Blog | proses | 2017-02-16 | | Jago Wordpress | proses | 2017-02-17 | | MySQL Untuk Pemula | proses | 2017-01-11 | +--------------------------+---------+------------+



Pada contoh diatas, data penjualan buku tanggal 2017-01-15 tidak ikut ditampilkan. Query diatas akan mengevaluasi setiap baris data apakah memenuhi kriteria yang ada pada klausa WHERE, jika ya, maka data ditampilkan. Secara sederhana, klausa WHERE pada contoh diatas dapat diibaratkan sebagai berikut: SELECT * FROM buku_sales WHERE tgl_order > Hasil dari ekspresi CASE



Ekspresi CASE akan menghasilkan nilai yang akan dibandingkan dengan tgl_order, hasilnya bisa tgl_order > 2017-02-00 atau tgl_order > 0000-0000



262 BAB 14 Ekspresi Logika



BAB 15 Subquery Subquery atau sering disebut subselect atau nested query adalah query yang berada di dalam query, lebih spesifik lagi, subquery merupakan statemen SELECT yang berada di dalam statemen SQL lain. Hasil dari subquery ini dapat berdiri sendiri atau digunakan oleh query utama. Meskipun dapat digantikan dengan klausa JOIN atau UNION (tergantung situasi yang ada), penggunaan subquery masih tetap menjadi favorit karena alur query menjadi lebih mudah dipahami, sehingga lebih modular dan mudah diperbaiki. Berikut ini contoh subquery: SELECT * FROM ( SELECT field1, field2 FROM tabel WHERE field1 = 100 ) AS tabel



Karena terdapat kemungkinan hasil subquery ini akan digunakan oleh query utama, maka subquery ini akan dieksekusi terlebih dahulu, baru kemudian query utama akan dijalankan dengan menyertakan nilai dari subquery tersebut. Subquery ini sama persis seperti query pada umumnya, sehingga kita dapat menuliskan subquery ini seperti query SQL pada umumnya (dapat menggunakan berbagai operator, fungsi, dll). Subquery dapat diterapkan di bagian mana saja dari SQL, disamping itu juga dapat digunakan pada statemen SELECT, INSERT, UPDATE, dan DELETE Pembahasan tentang sub query sangatlah luas karena mencakup berbagai kondisi yang berbeda beda. Oleh karena itu, pada bab ini kita akan persempit pembahasan dengan hanya membahas prinsip-prinsip dasar



Panduan Lengkap Query MySQL 263



subquery, dengan harapan, jika Anda menemukan kasus yang melibatkan subquery, Anda dapat dengan mudah mencari solusinya.



15.1. Pengelompokan Subquery Subquery umumnya digunakan pada statemen SELECT. Statemen SELECT sendiri memiliki bentuk umum seperti ini: SELECT FROM WHERE GROUP BY HAVING ORDER BY



kolom tabel kondisi kolom kondisi kolom



Subquery dapat digunakan pada setiap bagian statemen SELECT baik pada bagian kolom, tabel, dan kondisi. Berdasarkan posisi ini, subquery dapat dikelompokkan menjadi tiga macam, yaitu: 1. Subquery sebagai data. Ketika subquery berada dibagian tabel (di dalam klausa FROM) maka hasil subquery tersebut digunakan sebagai data. 2. Subquery sebagai kondisi. Ketika subquery berada di bagian kondisi (di bagian klausa WHERE atau HAVING), maka subquery ini menjadi bagian dari kriteria kondisi. 3. Subquery sebagai kolom. Ketika subquery berada di bagian list_kolom, maka subquery ini akan membentuk kolom. Hal ini terjadi ketika subquery berada pada bagian klausa SELECT, GROUP BY, dan ORDER BY. Disamping itu, berdasarkan dependensinya, subquery dibagi menjadi dua yaitu: 1. Independent Subquery, yang artinya subquery berdiri sendiri, tidak tergantung dari query utama. 2. Dependen Subquery. Kebalikan dari yang pertama, pada bentuk kedua ini, subquery bergantung dari query utama.



264 BAB 15 Subquery



Pada bab ini, kita akan bahas semua jenis query tersebut.



15.2. Subquery Sebagai Data Ketika subquery diletakkan pada klausa FROM maka hasil dari query tersebut akan menjadi data yang dapat digunakan oleh statement SELECT. Pada kondisi ini, subquery akan menghasilkan sebuah tabel (seperti tabel pada umumnya) yang bersifat sementara (temporary) yang di ciptakan dan digunakan hanya pada saat query di eksekusi. Model ini juga dapat diibaratkan seperti view, bedanya, view tersimpan permanen pada database sedangkan subquery hanya sementara. Contoh 1: Query pada satu tabel Sebagai contoh, misal kita memiliki tabel uas yang berisi data nama, nilai uas, dan tanggal sebagai berikut: +----+--------+-------+------------+ | id | nama | nilai | tanggal | +----+--------+-------+------------+ | 1 | Nama A | 7 | 2017-03-18 | | 2 | Nama B | 8 | 2017-03-18 | | 3 | Nama C | 9 | 2017-03-18 | | 4 | Nama D | 5 | 2017-03-18 | | 5 | Nama E | 6 | 2017-03-18 | | 6 | Nama F | 9 | 2017-03-18 | | 7 | Nama G | 7 | 2017-03-18 | | 8 | Nama H | 8 | 2017-03-18 | +----+--------+-------+------------+



Selanjutnya kita akan mengambil 5 nilai terbesar untuk kemudian diambil total nilainya, nilai maksimalnya, dan nilai minimalnya. Untuk keperluan tersebut, biasanya kita akan menggunakan query berikut: 1. SELECT SUM(nilai) AS "Total Nilai", 2. MAX(nilai) AS "Nilai Tertinggi", 3. MIN(nilai) AS "Nilai Terendah" 4. FROM uas 5. ORDER BY nilai DESC LIMIT 5



Hasil yang kita peroleh adalah: Panduan Lengkap Query MySQL 265



+-------------+-----------------+----------------+ | Total nilai | Nilai Tertinggi | Nilai Terendah | +-------------+-----------------+----------------+ | 59 | 9 | 5 | +-------------+-----------------+----------------+



Ternyata, hasilnya tidak sesuai dengan yang kita inginkan, salah satunya karena nilai terendah untuk peringkat 5 besar adalah 7 bukan 5. Hal ini dikarenakan pada query diatas, MySQL akan menggabungkan seluruh data dan menjalankan fungsi agregat ( SUM, MAX, dan AVG) baru kemudian menjalankan klausa ORDER BY dan LIMIT. Untuk itu, terlebih dahulu harus kita urutkan data menggunakan subquery, sehingga querynya menjadi berikut: 1. SELECT SUM(nilai) AS "Total Nilai", 2. MAX(nilai) AS "Nilai Tertinggi", 3. MIN(nilai) AS "Nilai Terendah" 4. FROM ( 5. SELECT nilai 6. FROM `uas` 7. ORDER BY nilai DESC 8. LIMIT 5 9. ) AS nilai_uas



Hasil yang kita peroleh: +-------------+-----------------+----------------+ | Total Nilai | Nilai Tertinggi | Nilai Terendah | +-------------+-----------------+----------------+ | 41 | 9 | 7 | +-------------+-----------------+----------------+



Penjelasan: Pada query diatas, pertama tama MySQL akan mengeksekusi subquery 1. 2. 3. 4.



SELECT nilai FROM `uas` ORDER BY nilai DESC LIMIT 5



Sehingga menghasilkan temporary tabel: 266 BAB 15 Subquery



+-------+ | nilai | +-------+ | 9 | | 9 | | 8 | | 8 | | 7 | +-------+



Selanjutnya, berdasarkan tabel ini, MySQL menjalankan fungsi agregasi SUM, MIN, dan MAX. Penting diperhatikan bahwa ketika subquery berada di dalam klausa FROM, kita harus memberi nama tabel hasil subquery, pada contoh diatas kita beri nama nilai_uas ( AS nilai_uas ) Jika tidak, maka akan muncul pesan yang memberitahu bahwa setiap tabel turunan harus diberi nama, sebagai contoh: #1248 - Every derived table must have its own alias



Contoh 2: Query dua tabel atau lebih Contoh selanjutnya kita akan menampilkan data yang melibatkan dua tabel. Dalam praktik, bentuk ini sering kita jumpai. Misal kita memiliki tabel dengan nama barang dengan field id_barang, nama_barang, dan harga sebagai berikut: +-----------+-------------+---------+ | id_barang | nama_barang | harga | +-----------+-------------+---------+ | 1 | RAM | 230000 | | 2 | Mainboard | 1250000 | | 3 | Pocessor | 1150000 | | 4 | Mouse | 85000 | | 5 | Keyboard | 80000 | +-----------+-------------+---------+



Terdapat tabel lain yang bernama penjualan yang terdiri dari field id_transaksi, id_barang, tgl_transaksi, dan harga dimana field id_barang pada tabel ini merupakan foreign key dari field id_barang



Panduan Lengkap Query MySQL 267



pada tabel barang. Kolom harga pada tabel ini merupakan harga yang dibayar oleh konsumen. +--------------+-----------+------------+---------+ | id_transaksi | id_barang | tanggal | harga | +--------------+-----------+------------+---------+ | 1 | 1 | 2017-03-10 | 3500000 | | 2 | 1 | 2017-03-12 | 3250000 | | 3 | 2 | 2017-03-15 | 3100000 | | 4 | 2 | 2017-02-17 | 3000000 | | 5 | 3 | 2017-03-13 | 2750000 | | 6 | 3 | 2017-02-16 | 2500000 | | 7 | 2 | 2017-03-12 | 3050000 | | 8 | 2 | 2017-02-19 | 3100000 | | 9 | 3 | 2017-03-11 | 2250000 | | 10 | 1 | 2017-02-09 | 3500000 | +--------------+-----------+------------+---------+



Selanjutnya kita akan menampilkan data penjualan khusus pada bulan Maret dengan menampilkan data nama_barang, harga, jumlah barang yang terjual, dan total penjualan. Sejauh yang telah kita pelajari, maka, untuk menampilkan data tersebut, kita akan menjalankan query sebagai berikut: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.



SELECT id_barang, nama_barang, penjualan.harga, COUNT(id_transaksi) AS jumlah, penjualan.harga * COUNT(id_transaksi) AS total, MAX(tanggal) AS transaksi_terakhir FROM barang LEFT JOIN penjualan AS penjualan USING(id_barang) WHERE MONTH(tanggal) = 3 GROUP BY id_barang



Hasil yang kita peroleh adalah: +-----------+-------------+---------+--------+---------+--------------------+ | id_barang | nama_barang | harga | jumlah | total | transaksi_terakhir | +-----------+-------------+---------+--------+---------+--------------------+ | 1 | RAM | 3250000 | 1 | 3250000 | 2017-03-12 | | 2 | Mainboard | 3100000 | 2 | 6200000 | 2017-03-15 | | 3 | Pocessor | 2750000 | 2 | 5500000 | 2017-03-13 | +-----------+-------------+---------+--------+---------+--------------------+



268 BAB 15 Subquery



Hasil diatas tidak sesuai dengan yang kita harapkan, karena seharusnya Mouse dan Keyboard ditampilkan pada hasil (kita ingin menampilkan semua barang, baik ada maupun tidak ada penjualan). Hal ini disebabkan karena MySQL pertama kali akan membuat temporary tabel dengan menggabungkan tabel barang dan penjualan yang menghasilkan tabel: +-----------+-------------+---------+--------------+------------+---------+ | id_barang | nama_barang | harga | id_transaksi | tanggal | harga | +-----------+-------------+---------+--------------+------------+---------+ | 1 | RAM | 230000 | 2 | 2017-03-12 | 3250000 | | 2 | Mainboard | 1250000 | 3 | 2017-03-15 | 3100000 | | 2 | Mainboard | 1250000 | 4 | 2017-02-17 | 3000000 | | 3 | Pocessor | 1150000 | 5 | 2017-03-13 | 2750000 | | 3 | Pocessor | 1150000 | 6 | 2017-02-16 | 2500000 | | 2 | Mainboard | 1250000 | 7 | 2017-03-12 | 3050000 | | 2 | Mainboard | 1250000 | 8 | 2017-02-19 | 3100000 | | 3 | Pocessor | 1150000 | 9 | 2017-03-11 | 2250000 | | 1 | RAM | 230000 | 10 | 2017-02-09 | 3500000 | | 4 | Mouse | 85000 | NULL | NULL | NULL | | 5 | Keyboard | 80000 | NULL | NULL | NULL | +-----------+-------------+---------+--------------+------------+---------+



Selanjutnya MySQL menjalankan semua perintah pada klausa SELECT yang hanya menampilkan data penjualan Maret 2017, alhasil, Mouse dan Keyboard tidak ditampilkan. Untuk memperbaikinya, kita perlu menggunakan subquery sedemikian rupa sehingga terbentuk tabel awal (temporary) yang benar. Query yang kita jalankan: 1. SELECT id_barang, 2. nama_barang, 3. penjualan.harga, 4. IFNULL(jumlah, 0) AS jumlah, 5. IFNULL(penjualan.harga * jumlah, 0) AS total, 6. IFNULL(tanggal, "-") AS "Transaksi Terakhir" 7. FROM barang 8. LEFT JOIN 9. ( 10. SELECT id_barang, harga, 11. COUNT(id_barang) AS jumlah, 12. MAX(tanggal) AS tanggal 13. FROM penjualan 14. WHERE YEAR(tanggal) = 2017 15. AND MONTH(tanggal) = 3 16. GROUP BY id_barang 17. ) AS penjualan



Panduan Lengkap Query MySQL 269



18. USING (id_barang) 19. GROUP BY id_barang



Hasil yang kita peroleh: +-----------+-------------+---------+--------+---------+--------------------+ | id_barang | nama_barang | harga | jumlah | total | Transaksi Terakhir | +-----------+-------------+---------+--------+---------+--------------------+ | 1 | RAM | 3250000 | 1 | 3250000 | 2017-03-12 | | 2 | Mainboard | 3100000 | 2 | 6200000 | 2017-03-15 | | 3 | Pocessor | 2750000 | 2 | 5500000 | 2017-03-13 | | 4 | Mouse | NULL | 0 | 0 | | | 5 | Keyboard | NULL | 0 | 0 | | +-----------+-------------+---------+--------+---------+--------------------+



Penjelasan: Query diatas terdiri dari dua bagian, yaitu query utama dan subquery. Adapun subquerynya adalah sebagai berikut: 1. 2. 3. 4. 5. 6.



SELECT id_barang, harga, COUNT(id_barang) AS jumlah, MAX(tanggal) AS tanggal FROM penjualan WHERE YEAR(tanggal) = 2017 AND MONTH(tanggal) = 3 GROUP BY id_barang



Sedangkan query utamanya adalah: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.



SELECT id_barang, nama_barang, penjualan.harga, IFNULL(jumlah, 0) AS jumlah, IFNULL(penjualan.harga * jumlah, 0) AS total, IFNULL(tanggal, "-") AS "Transaksi Terakhir" FROM tabel_barang LEFT JOIN (subquery) AS penjualan USING (id_barang) GROUP BY id_barang



Pertama-tama, MySQL akan menjalankan subquery dan menghasilkan temporary tabel dengan nama pj (AS pj) sebagai berikut: +-----------+---------+--------+------------+



270 BAB 15 Subquery



| id_barang | harga | jumlah | tanggal | +-----------+---------+--------+------------+ | 1 | 230000 | 1 | 2017-03-12 | | 2 | 1250000 | 2 | 2017-03-15 | | 3 | 1150000 | 2 | 2017-03-13 | +-----------+---------+--------+------------+



Selanjutnya, MySQL akan menggabungkan tabel tersebut dengan tabel_barang menggunakan klausa LEFT JOIN. Terakhir, MySQL mengeksekusi perintah yang ada pada statemen SELECT Perlu diperhatikan bahwa pada query diatas, kita memberi nama temporary tabel dengan nama penjualan, kita bebas memberi nama pada temporary tabel ini, dan kebetulan nama yang kita berikan sama dengan nama tabel aslinya. Selanjutnya, nama tabel ini kita gunakan untuk mendefinisikan kolom harga pada query SELECT (penjualan.harga). Seperti telah kita bahas pada bab sebelumnya, kita harus mendefinisikan nama tabel jika ada nama kolom yang sama. Pada contoh diatas, kita harus mendefinisikan nama tabel pada kolom harga karena nama kolom tersebut ada di tabel tabel_barang dan tabel_penjualan, dengan demikian MySQL tahu bahwa kita akan menggunakan kolom harga pada tabel penjualan (hasil dari subquery) Kapan Menggunakan Sub Query? Pertanyaan selanjutnya yang sering muncul adalah apakah ketika menggabungkan dua tabel dengan jumlah baris yang berbeda dengan menggunakan berbagai fungsi agregasi kita harus menggunakan subquery? Jawabnya tidak selalu. Mari kita lanjutkan contoh sebelumnya. Misal kita akan menampilkan semua data barang dan semua data penjualannya, dengan subquery mungkin kita akan menggunakan query berikut ini: 1. SELECT id_barang, 2. nama_barang, 3. IFNULL(penjualan.harga, 0) AS harga_trx, 4. IFNULL(jumlah, 0) AS jumlah, 5. IFNULL(penjualan.harga * jumlah, 0) AS total,



Panduan Lengkap Query MySQL 271



6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17.



IFNULL(tanggal, "-") AS trx_trakhir FROM barang LEFT JOIN ( SELECT id_barang, harga, COUNT(id_barang) AS jumlah, MAX(tanggal) AS tanggal FROM penjualan GROUP BY id_barang ) AS penjualan USING (id_barang) GROUP BY id_barang



Hasil yang kita peroleh: +-----------+-------------+-----------+--------+---------+-------------+ | id_barang | nama_barang | harga_trx | jumlah | total | trx_trakhir | +-----------+-------------+-----------+--------+---------+-------------+ | 1 | RAM | 230000 | 2 | 460000 | 2017-03-12 | | 2 | Mainboard | 1250000 | 4 | 5000000 | 2017-03-15 | | 3 | Pocessor | 1150000 | 3 | 3450000 | 2017-03-13 | | 4 | Mouse | 0 | 0 | 0 | | | 5 | Keyboard | 0 | 0 | 0 | | +-----------+-------------+-----------+--------+---------+-------------+



Hasil yang kita peroleh telah sesuai dengan yang kita harapkan, namun, pertimbangkan penggunaan query berikut: 1. SELECT id_barang, 2. nama_barang, 3. IFNULL(penjualan.harga, 0) AS harga_trx, 4. IFNULL(COUNT(id_transaksi), 0) AS jumlah, 5. IFNULL(penjualan.harga * COUNT(id_transaksi), 0) AS total, 6. IFNULL(tanggal, "-") AS trx_trakhir 7. FROM barang 8. LEFT JOIN penjualan USING (id_barang) 9. GROUP BY id_barang



Hasil yang kita peroleh sama, yaitu:



272 BAB 15 Subquery



+-----------+-------------+-----------+--------+---------+-------------+ | id_barang | nama_barang | harga_trx | jumlah | total | trx_trakhir | +-----------+-------------+-----------+--------+---------+-------------+ | 1 | RAM | 230000 | 2 | 460000 | 2017-03-12 | | 2 | Mainboard | 1250000 | 4 | 5000000 | 2017-03-15 | | 3 | Pocessor | 1150000 | 3 | 3450000 | 2017-03-13 | | 4 | Mouse | 0 | 0 | 0 | | | 5 | Keyboard | 0 | 0 | 0 | | +-----------+-------------+-----------+--------+---------+-------------+



Kenapa hasilnya sama? Pada contoh diatas, MySQL akan menggabungkan (LEFT JOIN) tabel barang dan tabel penjualan sehingga menghasilkan tabel sebagai berikut: mysql> SELECT * -> FROM barang -> LEFT JOIN penjualan USING (id_barang); +-----------+-------------+---------+--------------+------------+---------+ | id_barang | nama_barang | harga | id_transaksi | tanggal | harga | +-----------+-------------+---------+--------------+------------+---------+ | 1 | RAM | 230000 | 2 | 2017-03-12 | 230000 | | 2 | Mainboard | 1250000 | 3 | 2017-03-15 | 1250000 | | 2 | Mainboard | 1250000 | 4 | 2017-02-17 | 1250000 | | 3 | Pocessor | 1150000 | 5 | 2017-03-13 | 1150000 | | 3 | Pocessor | 1150000 | 6 | 2017-02-16 | 1150000 | | 2 | Mainboard | 1250000 | 7 | 2017-03-12 | 1250000 | | 2 | Mainboard | 1250000 | 8 | 2017-02-19 | 1250000 | | 3 | Pocessor | 1150000 | 9 | 2017-03-11 | 1150000 | | 1 | RAM | 230000 | 10 | 2017-02-09 | 230000 | | 4 | Mouse | 85000 | NULL | NULL | NULL | | 5 | Keyboard | 80000 | NULL | NULL | NULL | +-----------+-------------+---------+--------------+------------+---------+ 11 rows in set (0.00 sec)



Selanjutnya MySQL akan menjalankan statemen SELECT. Perlu diperhatikan bahwa kita menggunakan kolom id_transaksi untuk menghitung jumlah transaksi (COUNT(id_transaksi)) dengan kolom ini, Mouse dan Keyboard akan menghasilkan nilai 0 karena fungsi COUNT() tidak menghitung nilai NULL, hal ini berbeda jika yang kita hitung adalah kolom id_barang (COUNT(id_barang)), Mouse dan Keyboard akan bernilai 1. Hal ini juga berlaku pada kolom harga. Dari percobaan diatas dapat disimpulkan bahwa kita menggunakan subquery salah satunya jika kita menggabungkan dua buah tabel dengan jumlah baris berbeda dimana (1) data pada tabel pertama ditampilkan



Panduan Lengkap Query MySQL 273



semua (2) ada pembatasan jumlah row pada tabel kedua, pada contoh sebelumnya dibatasi hanya ditampilkan data transaksi bulan Maret 2017. Tips: kondisi yang memerlukan subquery adalah jika pada query terdapat tabel yang perlu diolah tersendiri sebelum digabungkan dengan query yang lain.



15.3. Subquery Sebagai Kriteria Tipe kedua dari subquery adalah subquery yang digunakan untuk melakukan seleksi data yang umumnya digunakan pada klausa WHERE. Pada bentuk ini, terdapat beberapa syarat yang harus dipenuhi: 



Subquery harus menghasilkan satu kolom.







Subquery harus menghasilkan satu baris jika operator yang digunakan mensyaratkan harus menggunakan satu nilai, seperti operator perbandingan ( =, !=, >, < )







Subquery dapat menghasilkan lebih dari satu baris jika operator yang digunakan dapat menerima lebih dari satu nilai, seperti operator IN, MIN, MAX, atau EXISTS



15.3.1. Subquery Dengan Hasil Satu Row Jika kita menggunakan operator perbandingan (comparison operator) pada klausa WHERE, maka subquery harus menghasilkan satu baris, jika tidak, maka akan error. Sebagai contoh, melanjutkan tabel barang yang telah kita gunakan sebelumnya, kita akan menampilkan data barang yang harganya lebih dari harga rata-rata semua produk. Query yang kita jalankan: 1. SELECT * FROM barang 2. WHERE harga > (SELECT AVG(harga) FROM barang)



Hasil yang kita peroleh adalah:



274 BAB 15 Subquery



+-----------+-------------+---------+ | id_barang | nama_barang | harga | +-----------+-------------+---------+ | 2 | Mainboard | 1250000 | | 3 | Pocessor | 1150000 | +-----------+-------------+---------+



Seperti sifat operator yang telah kita bahas pada bab sebelumnya, bahwa ketika membandingkan suatu nilai menggunakan operator pembanding, maka MySQL akan menyesuaikan tipe data kedua nilai tersebut. Pada contoh ini kebetulan hasil subquery berupa numeric sehingga dapat langsung dibandingkan dengan kolom harga, jika hasilnya bukan numeric, misal string, hasil yang kita peroleh juga sama. Contoh lainnya, kita akan mencari data penjualan Mainboard yang harganya dibawah harga list (list price). Jalankan query berikut: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.



SELECT id_barang, nama_barang, tanggal, penjualan.harga FROM penjualan LEFT JOIN barang USING (id_barang) WHERE id_barang = 2 AND penjualan.harga < ( SELECT harga FROM barang WHERE id_barang = 2 )



Hasil yang kita peroleh: +-----------+-------------+------------+---------+ | id_barang | nama_barang | tanggal | harga | +-----------+-------------+------------+---------+ | 2 | Mainboard | 2017-03-15 | 1150000 | | 2 | Mainboard | 2017-03-12 | 1050000 | +-----------+-------------+------------+---------+



Pada tabel barang kita ketahui bahwa id_barang dari Mainboard adalah 2, sehingga pada query diatas, kita menyeleksi barang berdasarkan id_barang yaitu 2. Pada klausa WHERE, subquery akan menghasilkan list price dari



Panduan Lengkap Query MySQL 275



Mainboard yang diambil dari tabel barang yaitu 1.250.000, sehingga klausa WHERE menjadi: WHERE id_barang = 2 AND t_trx.harga < 1.250.000



Pada operator yang mensyaratkan satu nilai, jika row yang dihasilkan lebih dari satu maka akan menghasilkan pesan error, misal: 1. SELECT * FROM tabel_barang 2. WHERE harga > (SELECT harga FROM tabel_barang)



Error yang dihasilkan: SQL Error (1242): Subquery returns more than 1 row



Demikian juga jika kolom yang dihasilkan lebih dari satu, misal: SELECT * FROM barang WHERE harga > (SELECT AVG(harga), id_barang FROM barang)



Error yang dihasilkan: ERROR 1241 (21000): Operand should contain 1 column(s)



15.3.2. Subquery Dengan Hasil Lebih Dari Satu Row Subquery yang menghasilkan nilai lebih dari satu row sering disebut multiple-row subquery. Pada bentuk ini kita tidak dapat menggunakan operator pembanding melainkan harus menggunakan operator yang dapat menerima beberapa nilai seperti operator IN. Pada bab 9, kita sudah belajar mengenai operator IN, contoh penggunaan operator ini adalah: WHERE id_barang IN(1,3,5)



276 BAB 15 Subquery



Pada contoh diatas terlihat bahwa operator IN menerima 3 nilai, yaitu 1,3, dan 5. Selain nilai tersebut, operator IN ini juga dapat menerima nilai berupa tabel hasil query statemen SELECT, sperti: WHERE id_barang IN (SELECT id_barang FROM penjualan WHERE YEAR(tanggal) = 2017 )



Pada contoh diatas, nilai pada operator IN bersifat dinamis, sesuai dengan banyaknya data transaksi.



15.3.2.1.



Subquery Dengan Operator IN, = ANY, dan = SOME



Operator IN sering digunakan ketika menggunakan subquery. Misal, masih menggunakan data tabel penjualan, kita akan tampilkan data id_barang dan nama_barang yang memiliki transaksi lebih dari satu kali. Query yang kita jalankan: 1. 2. 3. 4. 5. 6. 7. 8. 9.



SELECT id_barang, nama_barang FROM penjualan LEFT JOIN barang USING (id_barang) WHERE id_transaksi IN ( SELECT id_transaksi FROM penjualan GROUP BY id_barang HAVING count(*) > 2 )



Hasil yang kita peroleh adalah: +-----------+-------------+ | id_barang | nama_barang | +-----------+-------------+ | 2 | Mainboard | | 3 | Pocessor | +-----------+-------------+



Pada contoh diatas, terdapat subquery yaitu:



Panduan Lengkap Query MySQL 277



1. 2. 3. 4.



SELECT id_transaksi FROM penjualan GROUP BY id_barang HAVING count(*) > 2



Subquery tersebut akan mengambil data tabel penjualan yang kolom id_barang nya memiliki nilai yang sama lebih dari dua. Hasilnya: +--------+ | id_trx | +--------+ | 3 | | 5 | +--------+



Selanjutnya, data tersebut digunakan oleh operator IN yang ada pada query utama, sehingga querynya menjadi seperti berikut ini: 1. 2. 3. 4. 5.



SELECT id_barang, nama_barang FROM penjualan LEFT JOIN barang USING (id_barang) WHERE id_transaksi IN (3,5)



Selain menggunakan operator IN, kita juga dapat menggunakan operator = ANY atau = SOME, ketiganya memiliki fungsi yang sama persis, sehingga kita dapat mengganti IN(...) dengan = ANY(...) atau = SOME(...). Misal, query diatas kita ubah degan operator = ANY 1. 2. 3. 4. 5. 6. 7. 8. 9.



SELECT id_barang, nama_barang FROM penjualan LEFT JOIN barang USING (id_barang) WHERE id_transaksi = ANY (SELECT id_transaksi FROM penjualan GROUP BY id_barang HAVING count(*) > 2 )



278 BAB 15 Subquery



Pada query diatas, kita ganti WHERE id_trx IN menjadi WHERE id_trx = ANY, atau kita juga dapat menggantinya dengan SOME menjadi WHERE id_trx = SOME Selain menggunakan subquery, kita juga dapat menampilkan data yang sama tanpa subquery. Adapun querynya adalah sebagai berikut: 1. 2. 3. 4. 5.



SELECT id_barang, nama_barang FROM penjualan LEFT JOIN barang USING(id_barang) GROUP BY id_barang HAVING count(*) > 2



Hasil yang kita peroleh juga sama, yaitu: +-----------+-------------+ | id_barang | nama_barang | +-----------+-------------+ | 2 | Mainboard | | 3 | Pocessor | +-----------+-------------+



Perhatikan bahwa pada cara kedua ini kita menggunakan JOIN untuk menggabungkan tabel penjualan dan tabel barang



15.3.2.2. Subquery Dengan Operator NOT Selain operator IN, operator yang sering digunakan untuk subquery adalah operator NOT IN, yang artinya akan mengambil data yang nilainya tidak disebutkan pada operator tersebut. Contoh kita tampilkan data tabel penjualan yang tidak ada pada tabel retur Isi dari tabel return adalah sebagai berikut: +----------+--------------+------------+-------------+ | id_retur | id_transaksi | tgl_retur | nilai_retur | +----------+--------------+------------+-------------+ | 1 | 2 | 2017-01-12 | 175000 | | 2 | 7 | 2017-02-15 | 215000 | +----------+--------------+------------+-------------+



Query yang kita jalankan: Panduan Lengkap Query MySQL 279



1. SELECT * FROM penjualan 2. WHERE id_transaksi NOT IN ( SELECT id_transaksi 3. FROM retur 4. )



Hasil yang kita peroleh: +--------------+-----------+------------+---------+ | id_transaksi | id_barang | tanggal | harga | +--------------+-----------+------------+---------+ | 3 | 2 | 2017-03-15 | 1150000 | | 4 | 2 | 2017-02-17 | 1250000 | | 5 | 3 | 2017-03-13 | 1150000 | | 6 | 3 | 2017-02-16 | 1150000 | | 8 | 2 | 2017-02-19 | 1250000 | | 9 | 3 | 2017-03-11 | 1150000 | | 10 | 1 | 2017-02-09 | 230000 | +--------------+-----------+------------+---------+



15.3.3. Subquery Berkorelasi (Correlated Subquery) Subquery yang telah kita bahas sejauh ini merupakan subquery tidak berkorelasi (uncorrelated subquery), yang artinya tidak memiliki hubungan (korelasi) dengan query induk dimana subquery tersebut berada. Pada jenis ini, subquery dapat dijalankan secara tersendiri (independen) tidak terpengaruh dengan query induk. Kebalikan dari uncorrelated subquery, terdapat istilah subquery berkorelasi (correlated subquery) yang berarti bahwa suatu subquery memiliki hubungan dengan query induk, yang salah satunya adalah penggunaan kolom query induk, pada model ini subquery ini tidak dapat dieksekusi tersendiri karena terikat pada query induk. Sebagai contoh kita tampilkan data barang yang penjualannya diatas Rp. 1.000.000. Query yang kita jalankan: 1. SELECT nama_barang, harga 2. FROM barang 3. WHERE (SELECT SUM(harga)



280 BAB 15 Subquery



4. FROM penjualan 5. WHERE penjualan.id_barang = barang.id_barang 6. ) > 1000000



Hasil yang kita dapatkan: +-------------+---------+ | nama_barang | harga | +-------------+---------+ | Mainboard | 1250000 | | Pocessor | 1150000 | +-------------+---------+



Pada contoh diatas, terdapat subquery sebagai berikut: 1. SELECT SUM(harga) 2. FROM penjualan 3. WHERE penjualan.id_barang = barang.id_barang



Perhatikan bahwa pada bagian WHERE terdapat ekpresi barang.id_barang yang artinya kita mengambil data kolom id_barang dari tabel barang yang ada di query induk, inilah kenapa subquery ini disebut subquery berkorelasi. Jika kita jalankan query ini secara terpisah, maka akan muncul pesan error yang menyebutkan bahwa tabel barang tidak ditemukan. Untuk dapat memahami query diatas, kita lihat bentuk query secara global sebagai berikut: 1. SELECT nama_barang, harga 2. FROM barang 3. WHERE subquery > 10000000



Seperti yang telah kita bahas sebelumnya, ketika digunakan bersama operator perbandingan, dalam hal ini operator lebih besar ( > ), maka ekspresi yang dibandingkan harus memiliki satu nilai. Demikian juga dengan subquery, pada query diatas, subquery kita buat sedemikian rupa sehingga menghasilkan satu buah kolom dan satu buah baris, selanjutnya



Panduan Lengkap Query MySQL 281



setiap baris dari tabel barang akan dievaluasi apakah memenuhi kriteria pada klausa WHERE, jika ya maka data ditampilkan. Selain menggunakan subquery, kita dapat menggunakan query berikut untuk memperoleh hasil yang sama: 1. 2. 3. 4. 5.



SELECT nama_barang, barang.harga FROM barang LEFT JOIN penjualan USING (id_barang) GROUP BY barang.id_barang HAVING SUM(penjualan.harga) > 1000000



Perhatikan bahwa tanpa menggunakan subquery, kita perlu menggunakan klausa GROUP BY dan HAVING. Klausa GROUP BY akan mengelompokkan data berdasarkan id_barang dan klausa HAVING akan memfilter nilai kolom harga pada setiap group yang memiliki nilai diatas 1.000.0000



15.3.3.1. Subquery Dengan Operator EXISTS Operator terkait penggunaan subquery berkorelasi adalah operator EXISTS. Operator ini akan mengecek apakah subquery menghasilkan data tertentu, jika ya maka hasilnya true jika jika tidak, maka hasilnya false. Sebagai contoh kita ambil data barang yang ada transaksinya, query yang kita jalankan: 1. SELECT id_barang, 2. nama_barang 3. FROM barang AS tb 4. WHERE EXISTS( SELECT * 5. FROM penjualan AS tp 6. WHERE tb.id_barang = tp.id_barang 7. )



Hasil yang kita peroleh:



282 BAB 15 Subquery



+-----------+-------------+ | id_barang | nama_barang | +-----------+-------------+ | 1 | RAM | | 2 | Mainboard | | 3 | Pocessor | +-----------+-------------+



Pada query diatas, subquery tidak berdiri sendiri karena klausa WHERE menggunakan tabel yang ada pada query utama. Klausa EXISTS akan mengecek subquery apakah menghasilkan data, jika ya maka bernilai true dan data nama_barang ditampilkan. Perhatikan bahwa pada subquery tersebut kita menggunakan tanda asterik untuk menyeleksi semua kolom (SELECT *), kita bebas menyeleksi nama kolom tertentu, namun agar aman, kita menyeleksi semua kolom, intinya hanya mengecek apakah subquery menghasilkan data. Pada tabel diatas, Mouse dan Keyboard tidak ditampilkan karena tidak ada data transaksinya. Sama seperti sebelumnya, kita juga dapat menghasilkan output yang sama tanpa menggunakan subquery: 1. 2. 3. 4. 5.



SELECT id_barang, nama_barang FROM penjualan JOIN barang USING(id_barang) GROUP BY id_barang



Perhatikan bahwa pada query diatas kita menggunakan klausa GROUP BY untuk menggabungkan semua data pada tabel penjualan berdasarkan id_barang dan klausa JOIN untuk mendapatkan nama barang. Selain itu, subquery berikut ini juga menghasilkan output yang sama 1. SELECT id_barang, 2. nama_barang 3. FROM barang AS tb 4. WHERE id_barang IN ( SELECT id_barang FROM penjualan )



Panduan Lengkap Query MySQL 283



Anda bebas memilih yang menurut Anda mudah dipahami, namun jika data yang kita kelola banyak, hingga ratusan ribu, maka pertimbangkan untuk tidak menggunakan subquery karena akan menurunkan performa query



15.3.3.2. Subquery Dengan Operator NOT EXISTS Selanjutnya kita juga dapat menambahkan operator NOT pada operator EXISTS sehingga menjadi NOT EXISTS yang artinya kebalikan dari operator EXISTS, dimana jika data tidak ditemukan maka hasilnya true, jika tidak, hasilnya false. Misal kita ingin menampilkan data nama barang yang tidak ada penjualan, query yang kita jalankan: 1. SELECT id_barang, nama_barang 2. FROM barang AS tb 3. WHERE NOT EXISTS( SELECT * 4. FROM penjualan AS tp 5. WHERE tb.id_barang = tp.id_barang 6. )



Hasil yang kita peroleh adalah: +-----------+-------------+ | id_barang | nama_barang | +-----------+-------------+ | 4 | Mouse | | 5 | Keyboard | +-----------+-------------+



Query diatas adalah kebalikan dari query sebelumnya, yaitu menghasilkan Mouse dan Keyboard karena keduanya tidak ada penjualan. Seperti sebelumnya kita juga dapat menghasilkan output yang sama tanpa subquery. 1. 2. 3. 4.



SELECT id_barang, nama_barang FROM penjualan RIGHT JOIN barang USING (id_barang) WHERE id_transaksi IS NULL



284 BAB 15 Subquery



Pada query diatas, MySQL akan menggabungkan tabel penjualan dan barang kemudian mengambil baris yang id_transaksi nya NULL, Dari kedua query diatas, terlihat bahwa cara kedua lebih simpel daripada cara pertama.



15.4. Subquery Sebagai Calculated Column Bentuk terakhir dari subquery adalah subquery yang bertindak sebagai kolom. Subquery ini berada di daftar nama kolom pada bagian klausa SELECT. Misal kita tampilkan data nama barang beserta jumlah transaksinya, query yang kita jalankan: 1. SELECT nama_barang, 2. (SELECT COUNT(id_transaksi) 3. FROM penjualan 4. WHERE barang.id_barang = penjualan.id_barang 5. ) AS jml_transaksi 6. FROM barang 7. ORDER BY id_barang



Hasil yang kita peroleh adalah: +-------------+---------------+ | nama_barang | jml_transaksi | +-------------+---------------+ | RAM | 2 | | Mainboard | 4 | | Pocessor | 3 | | Mouse | 0 | | Keyboard | 0 | +-------------+---------------+



Perhatikan bahwa pada query diatas, jenis subquerynya adalah subquery berkorelasi, dimana pada bagian klausa WHERE, subquery menggunakan kolom barang.id_barang yang ada di query utama. Subquery ini menghasilkan sebuah nilai yaitu jumlah transaksi tiap-tiap id_barang. Gambaran Query secara umumnya adalah:



Panduan Lengkap Query MySQL 285



1. SELECT nama_barang, 2. subquery AS jml_transaksi 3. FROM barang 4. ORDER BY id_barang



Seperti pada tabel hasil query, subquery menghasilkan satu nilai yang akan diletakkan di kolom jml_transaksi Seperti biasa, kita juga dapat menghasilkan output yang sama tanpa subquery, query penggantinya adalah: 1. 2. 3. 4. 5. 6.



SELECT id_barang, nama_barang, COUNT(id_transaksi) AS jml_transaksi FROM barang LEFT JOIN penjualan USING (id_barang) GROUP BY barang.id_barang



Pada query diatas kita menggunakan outer join ( LEFT JOIN ) untuk menampilkan semua data nama_barang yang ada pada tabel barang. Hasil penggabungan tersebut seperti tampak pada tabel berikut: mysql> SELECT * FROM barang LEFT JOIN penjualan USING (id_barang); +-----------+-------------+---------+--------------+------------+---------+ | id_barang | nama_barang | harga | id_transaksi | tanggal | harga | +-----------+-------------+---------+--------------+------------+---------+ | 1 | RAM | 230000 | 2 | 2017-03-12 | 230000 | | 2 | Mainboard | 1250000 | 3 | 2017-03-15 | 1150000 | | 2 | Mainboard | 1250000 | 4 | 2017-02-17 | 1250000 | | 3 | Pocessor | 1150000 | 5 | 2017-03-13 | 1150000 | | 3 | Pocessor | 1150000 | 6 | 2017-02-16 | 1150000 | | 2 | Mainboard | 1250000 | 7 | 2017-03-12 | 1050000 | | 2 | Mainboard | 1250000 | 8 | 2017-02-19 | 1250000 | | 3 | Pocessor | 1150000 | 9 | 2017-03-11 | 1150000 | | 1 | RAM | 230000 | 10 | 2017-02-09 | 230000 | | 4 | Mouse | 85000 | NULL | NULL | NULL | | 5 | Keyboard | 80000 | NULL | NULL | NULL | +-----------+-------------+---------+--------------+------------+---------+ 11 rows in set (0.00 sec)



Selanjutnya, fungsi COUNT() akan menghitung jumlah transaksi dan klausa GROUP BY akan mengelompokkan data berdasarkan id_barang, sehingga penghitungan jumlah transaksi dilakukan per id_barang.



286 BAB 15 Subquery



Contoh lainya adalah ketika kita ingin menghitung kontribusi masing masing barang terhadap total penjualan, dengan cara membagi total penjualan per item barang dengan jumlah total penjualan. Query yang kita jalankan: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17.



SELECT id_barang, nama_barang, COUNT(id_transaksi) AS jml_transaksi, SUM(penjualan.harga) AS jml_penjualan, (SELECT SUM(harga) FROM penjualan) AS total, CONCAT( ROUND( SUM(penjualan.harga) / (SELECT SUM(harga) FROM penjualan) * 100 , 2 ) , "%" ) AS persen FROM barang LEFT JOIN penjualan USING (id_barang) GROUP BY barang.id_barang



Hasil yang kita peroleh: +-----------+-------------+---------------+---------------+---------+--------+ | id_barang | nama_barang | jml_transaksi | jml_penjualan | total | persen | +-----------+-------------+---------------+---------------+---------+--------+ | 1 | RAM | 2 | 460000 | 8610000 | 5.34% | | 2 | Mainboard | 4 | 4700000 | 8610000 | 54.59% | | 3 | Pocessor | 3 | 3450000 | 8610000 | 40.07% | | 4 | Mouse | 0 | NULL | 8610000 | NULL | | 5 | Keyboard | 0 | NULL | 8610000 | NULL | +-----------+-------------+---------------+---------------+---------+--------+



Pada query diatas, kita menggunakan subquery untuk menghitung total penjualan yang hasilnya ditampilkan pada kolom total (baris 5), sedangkan pada persentase, kita bagi harga (baris 8) dengan total penjualan (baris 9) kemudian dikalikan 100 (baris 10). Kita gunakan fungsi ROUND() untuk membatasi banyaknya angka di belakang koma sebanyak dua digit. Selanjutnya kita gunakan fungsi CONCAT() untuk menggabungkan persentase dengan tanda persen (%)



Panduan Lengkap Query MySQL 287



15.5. Peningkatan Performa Subquery dapat memudahkan kita untuk menampilkan berbagai model data yang diinginkan, namun, meskipun penulisannya sudah benar, jika penyusunannya tidak tepat, akan menimbulkan masalah performa (waktu eksekusi) query, hal ini terutama jika data yang kita kelola jumlahnya banyak, misal hingga ratusan ribu atau jutaan baris. Penurunan performa ini terutama jika kita meletakkan subquery pada operator IN. Umumnya, daripada menggunakan operator IN, lebih baik menggunakan kombinasi operator = dengan AND atau OR, misal WHERE id_barang IN(5,10) dapat diganti dengan WHERE id_barang = 5 OR id_barang = 10 Dari berbagai contoh kasus yang disajikan pada bab ini, banyak diantaranya yang menunjukkan bahwa subquery dapat digantikan dengan JOIN, sehingga, jika Anda mendapati performa subquery menurun, Anda dapat mempertimbangkan menggantinya dengan JOIN.



288 BAB 15 Subquery



BAB 16 UNION Pada bab sebelumnya, kita telah membahas tentang join dan subquery. Pada sebagian orang, subquery ini rancu dengan union. Meskipun sama sama dapat menambahkan data, pada join dan subquery, penambahan terjadi pada jumlah kolom (penggabungan secara horizontal), sedangkan pada UNION, penambahan tersebut terjadi pada baris (penggabungan secara vertikal). Perbedaan keduanya seperti tampak seperti gambar berikut ini.



Tabel 16.1 Ilustrasi Subquery dan UNION Pada gambar diatas, terlihat bahwa pada UNION, kita menggabungkan tabel dengan menempatkan tabel kedua dibawah tabel pertama (tabel yang dimaksud disini adalah tabel yang dihasilkan oleh query SELECT)



Panduan Lengkap Query MySQL 289



Dengan penjelasan singkat diatas, dapat kita simpulkan bahwa JOIN dan dan UNION adalah sesuatu yang berbeda sama sekali dan tidak dapat saling menggantikan. Pada MySQL, terdapat dua macam operator union yaitu UNION dan UNION ALL. UNION digunakan untuk menggabungkan tabel dimana baris yang memiliki data yang sama di semua kolomnya, akan digabungkan menjadi satu, sedangkan UNION ALL akan menggabungkan tabel apa adanya tanpa menggabungkan baris yang datanya sama. Untuk mempermudah memahami perbedaan UNION dan UNION ALL, misal kita memiliki tabel berikut: Tabel A +-----------+------------+-----------+ | id_retur | tgl_retur | jml_retur | +-----------+------------+-----------+ | 1 | 2017-03-10 | 3500000 | | 1 | 2017-03-12 | 3250000 | | 2 | 2017-02-15 | 3100000 | | 2 | 2017-02-15 | 3100000 | +-----------+------------+-----------+



Tabel B +-----------+------------+---------+ | id_barang | tgl_trx | harga | +-----------+------------+---------+ | 2 | 2017-02-15 | 3100000 | | 3 | 2017-03-12 | 3250000 | +-----------+------------+---------+



Jika digabungkan menggunakan UNION, tabel yang dihasilkan: +-----------+------------+-----------+ | id_retur | tgl_retur | jml_retur | +-----------+------------+-----------+ | 1 | 2017-03-10 | 3500000 | | 1 | 2017-03-12 | 3250000 | | 2 | 2017-02-15 | 3100000 | | 3 | 2017-03-12 | 3250000 | +-----------+------------+-----------+



Pada tabel diatas terlihat bahwa setelah tabel digabungkan, maka baris yang datanya sama (baris dengan id 2) akan digabungkan. Selanjutnya, jika kita menggunakan UNION ALL, maka, hasil yang kita peroleh: +-----------+------------+-----------+ | id_retur | tgl_retur | jml_retur | +-----------+------------+-----------+ | 1 | 2017-03-10 | 3500000 | | 1 | 2017-03-12 | 3250000 | | 2 | 2017-02-15 | 3100000 | | 2 | 2017-02-15 | 3100000 |



290 BAB 16 UNION



| 2 | 2017-02-15 | 3100000 | | 3 | 2017-03-12 | 3250000 | +-----------+------------+-----------+



Dari tabel diatas terlihat bahwa MySQL akan menggabungkan Tabel A dan Tabel B apa adanya dan baris yang datanya sama (baris dengan id 2) tidak digabung.



16.1. Query UNION dan UNION ALL Secara umum, bentuk penulisan UNION dan UNION ALL adalah sebagai berikut: 1. 2. 3. 4. 5. 6. 7. 8. 9.



SELECT kolom1, kolom2, kolom3 FROM tabel1 WHERE kondisi UNION atau UNION ALL SELECT kolom1, kolom2, kolom3 FROM tabel2 WHERE kondisi [statemen SELECT yang lain…] ORDER BY nama_kolom



Pada contoh diatas, terlihat bahwa UNION terdiri dari beberapa statemen SELECT. Untuk lebih mudah memahami penulisan statemen SELECT pada UNION, mari kita lihat lagi format penulisan statemen SELECT yang telah kita bahas pada BAB 8 SELECT nama_kolom FROM nama_tabel WHERE kondisi GROUP BY nama_kolom ORDER BY nama_kolom HAVING kriteria LIMIT jumlah



Dengan membandingkan statemen SELECT diatas dengan statemen SELECT yang ada pada UNION, maka dapat kita simpulkan bahwa penulisan klausa SELECT pada UNION hanya sampai pada klausa WHERE, sedangkan klausa dibawahnya yaitu GROUP BY, ORDER BY, HAVING, dan LIMIT digunakan Panduan Lengkap Query MySQL 291



untuk tabel hasil penggabungan, tidak bisa digunakan pada masing masing statemen SELECT. Hasil penggabungan tabel dengan union dapat kita urutkan menggunakan klausa ORDER BY, namun, seperti yang telah kita bahas sebelumnya, bahwa klausa ini harus berada di bagian bawah, tidak boleh mejadi bagian dari di statemen SELECT kecuali jika menggunakan subquery (akan kita bahas di bagian akhir bab ini). Ketika menggunakan UNION dan UNION ALL, terdapat beberapa hal penting yang perlu diperhatikan: 1. Pada setiap klausa SELECT, jumlah kolom kedua tabel harus sama, namun demikian, tipe data dari kolom yang akan digabungkan tidak harus sama, MySQL akan mengubahnya sesuai keperluan. Misal pada tabel pertama, tipe data pada kolom pertama berupa angka (INT) sedangkan pada tabel kedua, tipe data pada kolom pertama berupa character (CHAR) 2. Jika panjang data dari kolom masing masing tabel berbeda, maka ketika tabel digabungkan, MySQL akan menggunakan panjang data yang terpanjang, misal kolom ketiga pada tabel pertama menggunakan tipe data CHAR(5) sedangkan kolom ketiga pada tabel kedua menggunakan CHAR(10), maka ketika tabel digabungkan, tipe data yang digunakan adalah CHAR(10) 3. Nama kolom yang digunakan pada tabel hasil UNION adalah nama kolom pada statemen SELECT yang pertama. Agar lebih paham tentang UNION dan UNION ALL mari kita bahas beberapa contoh kasus. Contoh 1: Misal kita memiliki dua buah tabel dengan nama penjualan dan retur. Adapun isi dari kedua tabel adalah sebagai berikut: Tabel penjualan



292 BAB 16 UNION



+--------+--------------+------------+-----------+ | id_trx | id_pelanggan | tgl_trx | total_trx | +--------+--------------+------------+-----------+ | 2 | 3 | 2017-03-22 | 395000 | | 3 | 2 | 2017-01-01 | 360000 | | 4 | 1 | 2017-03-04 | 269000 | | 5 | 4 | 2017-02-15 | 110000 | | 6 | 3 | 2017-03-07 | 256000 | | 7 | 2 | 2017-03-05 | 215000 | | 8 | 3 | 2016-12-12 | 270000 | | 9 | 3 | 2016-12-12 | 325000 | +--------+--------------+------------+-----------+



Tabel retur +----------+--------+--------------+------------+-------------+ | id_retur | id_trx | id_pelanggan | tgl_retur | nilai_retur | +----------+--------+--------------+------------+-------------+ | 1 | 2 | 2 | 2017-03-29 | 175000 | | 2 | 7 | 4 | 2017-03-21 | 215000 | +----------+--------+--------------+------------+-------------+



Selanjutnya kita akan membuat laporan mengenai data penjualan dari suatu pelanggan, misal pelanggan dengan id_pelanggan 2. Query yang kita jalankan: 1. 2. 3. 4. 5. 6. 7. 8.



SELECT tgl_trx, total_trx, "order" AS jenis_trx FROM penjualan WHERE id_pelanggan = 2 UNION ALL SELECT tgl_retur, nilai_retur, "retur" AS jenis_trx FROM retur WHERE id_pelanggan = 2 ORDER BY tgl_trx



Hasil yang kita peroleh adalah: +------------+-----------+-----------+ | tgl_trx | total_trx | jenis_trx | +------------+-----------+-----------+ | 2017-01-01 | 360000 | order | | 2017-03-05 | 215000 | order | | 2017-03-29 | 175000 | retur | +------------+-----------+-----------+



Panduan Lengkap Query MySQL 293



Secara garis besar, query diatas tampak sebagai berikut: 1. 2. 3. 4.



statemen SELECT pertama UNION ALL statemen SELECT kedua ORDER BY nama_kolom



Perhatikan bahwa pada tabel yang dihasilkan, nama kolom yang digunakan adalah nama kolom pada tabel pertama. Disamping itu, kita juga menambahkan satu kolom yaitu jenis_trx yang berisi "order" untuk tabel pertama dan "retur" untuk tabel kedua. Hal ini untuk membedakan mana baris yang berasal dari tabel penjualan dan mana yang dari tabel retur. Klausa ORDER BY pada query diatas akan mengurutkan data berdasarkan kolom tgl_trx. MySQL akan menjalankan klausa ini setelah kedua tabel digabung, Perhatikan bahwa pada klausa ORDER BY, kita menggunakan nama kolom tgl_trx bukan tgl_retur, karena nama kolom yang dihasilkan adalah tgl_trx. Tips: Jika kita menggunakan klausa ORDER BY, gunakan selalu nama kolom yang ada pada statemen SELECT yang pertama. Perhatikan juga bahwa kita menggunakan operator UNION ALL bukan UNION, karena jika menggunakan UNION data yang ditampilkan tidak akurat, jika ada data yang sama baik pada order maupun retur, data tersebut akan dihilangkan.



16.2. Precedence Ketika kita menggabungkan banyak tabel menggunakan UNION dan UNION ALL, maka kita perlu memperhatikan urutan dari masing masing statemen SELECT. Misal kita gabungkan tabel pelanggan, tabel penjualan, dan tabel retur dengan query sebagai berikut: 1. SELECT id_pelanggan, nama, "transaksi" AS jenis 2. FROM penjualan 3. LEFT JOIN pelanggan USING(id_pelanggan)



294 BAB 16 UNION



4. 5. 6. 7. 8. 9. 10.



UNION SELECT id_pelanggan, nama, "transaksi" AS jenis FROM retur LEFT JOIN pelanggan USING(id_pelanggan) UNION ALL SELECT id_pelanggan, nama, "-" AS jenis FROM pelanggan



Hasil yang kita peroleh: +--------------+--------------------+-----------+ | id_pelanggan | nama | jenis | +--------------+--------------------+-----------+ | 1 | Anton | transaksi | | 2 | Braskie | transaksi | | 3 | Charlie | transaksi | | 4 | Deni | transaksi | | 1 | Anton | | | 2 | Braskie | | | 3 | Charlie | | | 4 | Deni | | | 5 | Erdhi | | | 6 | Ferry | | | 7 | PT. Manunggal Jaya | | | 8 | CV. Riang Gembira | | | 9 | Deni | | +--------------+--------------------+-----------+



Pada contoh diatas, pertama-tama tabel penjualan dan tabel retur digabungkan menggunakan UNION sehingga dihasilkan data yang unik (empat baris pertama), selanjutnya, data tersebut digabungkan dengan tabel pelanggan menggunakan UNION ALL. Dari alur tersebut dapat kita ketahui bahwa data digabungkan urut dari atas ke bawah, sehingga jika kita ubah urutan menjadi seperti ini: 1. 2. 3. 4. 5. 6. 7.



SELECT id_pelanggan, nama FROM pelanggan UNION ALL SELECT id_pelanggan, nama FROM penjualan LEFT JOIN pelanggan USING(id_pelanggan) UNION



Panduan Lengkap Query MySQL 295



8. SELECT id_pelanggan, nama 9. FROM retur 10. LEFT JOIN pelanggan USING(id_pelanggan)



Hasil yang kita peroleh: +--------------+--------------------+ | id_pelanggan | nama | +--------------+--------------------+ | 1 | Anton | | 2 | Braskie | | 3 | Charlie | | 4 | Deni | | 5 | Erdhi | | 6 | Ferry | | 7 | PT. Manunggal Jaya | | 8 | CV. Riang Gembira | | 9 | Deni | +--------------+--------------------+



Hasil tersebut berbeda dengan yang pertama karena pada query yang kedua ini, pertama tama tabel pelanggan akan digabungkan dengan tabel transaksi menggunakan UNION ALL baru kemudian hasilnya digabung menggunakan UNION. Karena yang terakhir digunakan adalah UNION maka semua baris yang sama akan dihilangkan. Tips: Dari contoh diatas, dapat kita simpulkan bahwa jika kita ingin menggunakan UNION dan UNION ALL dalam satu query maka selalu tempatkan UNION ALL setelah UNION



16.3. UNION Dengan Kolom Yang Berbeda Pada contoh sebelumnya, statemen SELECT yang kita gunakan memiliki jumlah kolom yang sama. Dalam praktek, terkadang kita perlu untuk menggabungkan beberapa tabel dimana jumlah kolom yang digabungkan berbeda sama sekali. Kondisi tersebut bisa kita misalkan seperti ini: pada tabel penjualan dan tabel retur, kita ingin menampilkan data id_retur, tgl_trx, nilai_trx dan jenis_trx, query yang kita jalankan:



296 BAB 16 UNION



1. 2. 3. 4. 5.



SELECT NULL AS id_retur, id_pelanggan, tgl_trx FROM penjualan UNION ALL SELECT id_retur, id_pelanggan, tgl_retur FROM retur



Hasil yang kita peroleh: +----------+--------------+------------+ | id_retur | id_pelanggan | tgl_trx | +----------+--------------+------------+ | NULL | 3 | 2017-03-22 | | NULL | 2 | 2017-01-01 | | NULL | 1 | 2017-03-04 | | NULL | 4 | 2017-02-15 | | NULL | 3 | 2017-03-07 | | NULL | 2 | 2017-03-05 | | NULL | 3 | 2016-12-12 | | NULL | 3 | 2016-12-12 | | 1 | 2 | 2017-03-29 | | 2 | 4 | 2017-03-21 | +----------+--------------+------------+



Perhatikan bahwa pada contoh diatas, kekurangan kolom pada tabel pertama kita siasati dengan menambahkan kolom baru yang bernama id_retur dengan nilai NULL (SELECT NULL AS id_retur), Anda bebas mengganti nilai NULL dengan nilai yang lain yang Anda inginkan, misal dengan tanda dash "-" menjadi SELECT "-" AS id_retur. Dengan memberi nilai NULL pada kolom id_retur, kita dapat membedakan baris yang berasal dari tabel penjualan dan baris yang berasal dari tabel retur. Dengan teknik ini, kita dapat dengan mudah menggabungkan berbagai jenis tabel dengan jumlah kolom yang berbeda beda.



16.4. Menggunakan ORDER BY Pada Statemen SELECT Pada awal bab ini telah kita bahas bahwa kita hanya bisa menggunakan klausa ORDER BY pada akhir statemen karena MySQL akan mengurutkan data setelah semua tabel digabungkan. Namun, terkadang kita ingin Panduan Lengkap Query MySQL 297



terlebih dahulu mengurutkan data pada tabel sebelum tabel tersebut digabungkan. Kondisi tersebut dapat dimisalkan seperti ini: misal kita ingin menggabungkan tabel transaksi dengan retur namun, terlebih dahulu ingin mengurutkan tabel transaksi berdasarkan tanggal transaksi terakhir. Untuk keperluan tersebut, querynya yang kita jalankan adalah: 1. 2. 3.



SELECT * FROM ( SELECT id_pelanggan, tgl_trx AS tanggal, "order" AS jenis_trx 4. FROM penjualan 5. ORDER BY tgl_trx DESC 6. LIMIT 5 7. ) AS transaksi 8. UNION ALL 9. SELECT id_pelanggan, tgl_retur, "retur" AS jenis_trx 10. FROM retur



Hasil yang kita peroleh adalah: +--------------+------------+-----------+ | id_pelanggan | tanggal | jenis_trx | +--------------+------------+-----------+ | 3 | 2017-03-22 | order | | 3 | 2017-03-07 | order | | 2 | 2017-03-05 | order | | 1 | 2017-03-04 | order | | 4 | 2017-02-15 | order | | 2 | 2017-03-29 | retur | | 4 | 2017-03-21 | retur | +--------------+------------+-----------+



Perhatikan bahwa pada query diatas, kita menggunakan subquery. Seperti telah kita bahas pada bab sebelumnya, bahwa jika dalam suatu query terdapat subquery, maka MySQL akan mengeksekusi query tersebut sebelum query utama. Sama seperti contoh diatas, pertama-tama MySQL akan mengeksekusi subquery yang ada di statemen pertama yaitu:



298 BAB 16 UNION



1. 2. 3. 4. 5.



SELECT id_pelanggan, tgl_trx AS tanggal, "order" AS jenis_trx FROM penjualan ORDER BY tgl_trx DESC LIMIT 5



Sebquery tersebut akan menghasilkan tabel sementara (temporary tabel) yang bernama transaksi (AS transaksi), dengan bentuk sebagai berikut: +--------------+------------+-----------+ | id_pelanggan | tanggal | jenis_trx | +--------------+------------+-----------+ | 3 | 2017-03-22 | order | | 3 | 2017-03-07 | order | | 2 | 2017-03-05 | order | | 1 | 2017-03-04 | order | | 4 | 2017-02-15 | order | +--------------+------------+-----------+



Pada tabel diatas, data transaksi diurutkan berdasarkan kolom tgl_trx secara menurun (descending), selanjutnya, pada query utama, yaitu SELECT * FROM, MySQL akan menggunakan tabel hasil subquery tersebut untuk digabungkan dengan tabel retur yang ada di statemen SELECT kedua dibawah klausa UNION Jika kita tetap menggunakan klausa ORDER BY pada statemen SELECT tanpa menggunakan subquery, maka kita akan mendapatkan pesan error sebagai berikut: SQL Error (1221): Incorrect usage of UNION and ORDER BY



Cara lain yang dapat digunakan untuk menghasilkan output yang sama yaitu dengan memberikan tanda kurung pada statemen SELECT. Seperti telah kita bahas pada bab sebelumnya, bahwa ekspresi yang berada di dalam tanda kurung akan didahulukan oleh MySQL. Contoh kita ubah query menjadi seperti ini: 1. ( SELECT id_pelanggan, tgl_trx AS tanggal, "order" AS 2. jenis_trx 3. FROM penjualan



Panduan Lengkap Query MySQL 299



4. ORDER BY tgl_trx DESC 5. LIMIT 5 6. ) 7. UNION ALL 8. (SELECT id_pelanggan, tgl_retur, "retur" AS jenis_trx 9. FROM retur 10. )



Hasil yang kita peroleh: +--------------+------------+-----------+ | id_pelanggan | tanggal | jenis_trx | +--------------+------------+-----------+ | 3 | 2017-03-22 | order | | 3 | 2017-03-07 | order | | 2 | 2017-03-05 | order | | 1 | 2017-03-04 | order | | 4 | 2017-02-15 | order | | 2 | 2017-03-29 | retur | | 4 | 2017-03-21 | retur | +--------------+------------+-----------+



Perhatikan bahwa kita menggunakan tanda kurung pada kedua statemen SELECT, jika tidak, maka akan menghasilkan error (khusus MySQL versi 5.6 dan sebelumnya)



16.5. Menggunakan LIMIT pada Statemen SELECT Pada UNION atau UNION ALL, kita dapat membatasi jumlah data hasil penggabungan menggunakan klausa LIMIT, seperti yang telah kita bahas sebelumnya, klausa ini hanya bisa digunakan pada akhir statemen, tidak bisa digunakan pada masing masing statemen SELECT, contoh: 1. 2. 3. 4. 5. 6.



SELECT id_pelanggan, tgl_trx AS tanggal, "order" AS jenis_trx FROM penjualan UNION ALL SELECT id_pelanggan, tgl_retur, "retur" AS jenis_trx FROM retur LIMIT 3



300 BAB 16 UNION



Hasil yang kita peroleh: +--------------+------------+-----------+ | id_pelanggan | tanggal | jenis_trx | +--------------+------------+-----------+ | 3 | 2017-03-22 | order | | 2 | 2017-01-01 | order | | 1 | 2017-03-04 | order | +--------------+------------+-----------+



Pada contoh diatas, setelah tabel digabungkan, MySQL akan mengambil tiga data teratas untuk ditampilkan. Jika kita ingin menggunakan klausa LIMIT pada salah satu statemen SELECT, maka kita perlu menggunakan tanda kurung, misal kita terapkan klausa LIMIT hanya pada statemen SELECT yang kedua 1. 2. 3. 4. 5. 6.



SELECT id_pelanggan, tgl_trx AS tanggal, "order" AS jenis_trx FROM penjualan UNION ALL (SELECT id_pelanggan, tgl_retur, "retur" AS jenis_trx FROM retur LIMIT 2)



Hasil yang kita peroleh: +--------------+------------+-----------+ | id_pelanggan | tanggal | jenis_trx | +--------------+------------+-----------+ | 3 | 2017-03-22 | order | | 2 | 2017-01-01 | order | | 1 | 2017-03-04 | order | | 4 | 2017-02-15 | order | | 3 | 2017-03-07 | order | | 2 | 2017-03-05 | order | | 3 | 2016-12-12 | order | | 3 | 2016-12-12 | order | | 2 | 2017-03-29 | retur | | 4 | 2017-03-21 | retur | +--------------+------------+-----------+



Karena berada di dalam tanda kurung, maka statemen kedua ini akan dieksekusi terlebih dahulu sehingga menghasilkan tabel dengan jumlah baris 2, selanjutnya tabel tersebut digabungkan dengan tabel pertama. Panduan Lengkap Query MySQL 301



16.6. Menggunakan JOIN Pada Statemen SELECT Seperti telah kita bahas pada awal bab ini, bahwa UNION digunakan untuk menggabungkan tabel secara vertikal, sedangkan JOIN digunakan untuk menggabungkan tabel secara horizontal. Pada kondisi tertentu, kita perlu untuk menggunakan UNION dan JOIN secara bersama-sama. Misal selain tabel penjualan dan tabel retur, kita memiliki tabel pelanggan yang berisi data pelanggan sebagai berikut: mysql> SELECT id_pelanggan, nama FROM pelanggan; +--------------+--------------------+ | id_pelanggan | nama | +--------------+--------------------+ | 1 | Anton | | 2 | Braskie | | 3 | Charlie | | 4 | Deni | | 5 | Erdhi | | 6 | Ferry | | 7 | PT. Manunggal Jaya | | 8 | CV. Riang Gembira | | 9 | Deni | +--------------+--------------------+ 9 rows in set (0.00 sec)



Selanjutnya, kita tampilkan data transaksi beserta nama pelanggan nya, jalankan query berikut: 1. SELECT id_pelanggan, nama, tgl_trx AS tanggal, "order" AS jenis_trx 2. FROM penjualan 3. LEFT JOIN pelanggan USING(id_pelanggan) 4. UNION ALL 5. SELECT id_pelanggan, nama, tgl_retur, "retur" AS 6. jenis_trx 7. FROM retur 8. LEFT JOIN pelanggan USING(id_pelanggan) 9. ORDER BY nama



302 BAB 16 UNION



Hasil yang kita peroleh: +--------------+---------+------------+-----------+ | id_pelanggan | nama | tanggal | jenis_trx | +--------------+---------+------------+-----------+ | 1 | Anton | 2017-03-04 | order | | 2 | Braskie | 2017-03-29 | retur | | 2 | Braskie | 2017-01-01 | order | | 2 | Braskie | 2017-03-05 | order | | 3 | Charlie | 2016-12-12 | order | | 3 | Charlie | 2017-03-22 | order | | 3 | Charlie | 2017-03-07 | order | | 3 | Charlie | 2016-12-12 | order | | 4 | Deni | 2017-02-15 | order | | 4 | Deni | 2017-03-21 | retur | +--------------+---------+------------+-----------+



Pada query diatas, terlebih dahulu kita gabungkan masing-masing tabel (tabel penjualan dan tabel retur) dengan tabel pelanggan, baru kemudian keduanya digabungkan dengan UNION, selain cara diatas, kita juga dapat menggunakan cara lain untuk memperoleh hasil yang sama, yaitu: 1. 2. 3. 4. 5. 6. 7. 8. 9.



SELECT id_pelanggan, nama, tanggal, jenis_trx FROM (SELECT id_pelanggan, tgl_trx AS tanggal, "order" AS jenis_trx FROM penjualan UNION ALL SELECT id_pelanggan, tgl_retur, "retur" AS jenis_trx FROM retur ) AS penjualan LEFT JOIN pelanggan USING (id_pelanggan)



Pada query diatas, terlebih dahulu kita gabungkan tabel penjualan dengan tabel retur menggunakan UNION ALL baru kemudian hasilnya digabungkan dengan tabel pelanggan.



Panduan Lengkap Query MySQL 303



Halaman ini sengaja dikosongkan Jagowebdev.com



304 BAB 16 UNION



BAB 17 Total dan Subtotal Ketika menampilkan data numeric yang berbentuk laporan atau report, seringnya kita akan menambahkan baris baru untuk menampilkan data total suatu kolom. Pada BAB ini, kita akan membahas berbagai teknik yang dapat digunakan untuk melakukan hal tersebut.



17.1. WITH ROLLUP Cara pertama untuk membuat baris subtotal dan grand total adalah menggunakan klausa WITH ROLLUP. Klausa ini hanya dapat digunakan jika ada klausa GROUP BY. Fungsi dari klausa WITH ROLLUP sendiri adalah membuat total dari fungsi agregasi yang ada pada suatu kolom. Sebagai contoh, kita memiliki tabel sales sebagai berikut: +--------+---------+---------+---------+-----------+ | id_trx | nama | bln_trx | thn_trx | nilai_trx | +--------+---------+---------+---------+-----------+ | 1 | Alfa | 3 | 2017 | 250000 | | 2 | Charlie | 12 | 2016 | 175000 | | 3 | Bravo | 3 | 2017 | 310000 | | 4 | Bravo | 11 | 2016 | 250000 | | 5 | Alfa | 3 | 2017 | 300000 | | 6 | Charlie | 11 | 2016 | 350000 | | 7 | Bravo | 3 | 2017 | 275000 | | 8 | Bravo | 12 | 2016 | 150000 | +--------+---------+---------+---------+-----------+



Selanjutnya, kita akan menampilkan data tabel tersebut beserta total nilai transaksinya, query yang kita jalankan: 1. 2. 3. 4.



SELECT id_trx, nama, bln_trx, thn_trx, SUM(nilai_trx) FROM sales GROUP BY id_trx WITH ROLLUP



Hasil: Panduan Lengkap Query MySQL 305



+--------+---------+---------+---------+----------------+ | id_trx | nama | bln_trx | thn_trx | SUM(nilai_trx) | +--------+---------+---------+---------+----------------+ | 1 | Alfa | 3 | 2017 | 250000 | | 2 | Charlie | 12 | 2016 | 175000 | | 3 | Bravo | 3 | 2017 | 310000 | | 4 | Bravo | 11 | 2016 | 250000 | | 5 | Alfa | 3 | 2017 | 300000 | | 6 | Charlie | 11 | 2016 | 350000 | | 7 | Bravo | 3 | 2017 | 275000 | | 8 | Bravo | 12 | 2016 | 150000 | | NULL | Bravo | 12 | 2016 | 2060000 | +--------+---------+---------+---------+----------------+



Pada contoh diatas, kita menggunakan klausa GROUP BY id_trx sebagai syarat untuk dapat menggunakan klausa WITH ROLLUP, meskipun sebenarnya tidak ada data yang kita kelompokkan karena tidak ada data yang sama pada kolom id_trx. Perhatikan bahwa terdapat tambahan baris pada baris paling bawah. Baris tersebut adalah hasil dari klausa WITH ROLLUP. Beberapa hal yang perlu diperhatikan terkait baris baru tersebut: 1. Karena data dikelompokkan berdasarkan id_trx (GROUP BY id_trx), maka pada baris baru yang hasilkan oleh klausa WITH ROLLUP, kolom tersebut bernilai NULL. 2. Kolom selain yang ada pada klausa GROUP BY dan kolom yang dihitung nilai totalnya (nilai_trx), yang pada contoh ini adalah kolom nama, bln_trx, thn_trx akan otomatis diisi oleh MySQL dengan nilai tertentu yang umumnya nilai pada baris sebelumnya, 3. Kita menggunakan fungsi SUM pada kolom nilai_trx padahal tidak ada data yang di jumlahkan, data yang ditampilkan sama persis dengan yang ada pada database. Kenapa perlu fungsi SUM()? Fungsi WITH ROLLUP akan membuat summary data yang ada fungsi agregasinya. Jika kita tidak menjalankan fungi apapun maka klausa WITH ROLLUP tidak akan menghasilkan apa-apa, misal: 1. SELECT id_trx, nama, bln_trx, thn_trx, nilai_trx



306 BAB 17 Total dan Subtotal



2. FROM sales 3. GROUP BY id_trx 4. WITH ROLLUP



Hasil: +--------+---------+---------+---------+-----------+ | id_trx | nama | bln_trx | thn_trx | nilai_trx | +--------+---------+---------+---------+-----------+ | 1 | Alfa | 3 | 2017 | 250000 | | 2 | Charlie | 12 | 2016 | 175000 | | 3 | Bravo | 3 | 2017 | 310000 | | 4 | Bravo | 11 | 2016 | 250000 | | 5 | Alfa | 3 | 2017 | 300000 | | 6 | Charlie | 11 | 2016 | 350000 | | 7 | Bravo | 3 | 2017 | 275000 | | 8 | Bravo | 12 | 2016 | 150000 | | NULL | Bravo | 12 | 2016 | 150000 | +--------+---------+---------+---------+-----------+



Perhatikan bahwa baris yang ditambahkan oleh klausa WITH ROLLUP, kolom nilai_trx isinya sama dengan baris sebelumnya yaitu 150000 Dari penjelasan diatas, kita sudah mulai paham bagaimana membuat baris total dengan klausa WITH ROLLUP, lebih lanjut, mari kita bahas cara membuat baris subtotal, kali ini kita buat total berdasarkan nama dan bulan transaksi, jalankan query berikut: 1. 2. 3. 4.



SELECT bln_trx, nama, COUNT(id_trx), SUM(nilai_trx) FROM sales GROUP BY bln_trx, nama WITH ROLLUP



Hasil: +---------+---------+---------------+----------------+ | bln_trx | nama | COUNT(id_trx) | SUM(nilai_trx) | +---------+---------+---------------+----------------+ | 3 | Alfa | 2 | 550000 | | 3 | Bravo | 2 | 585000 | | 3 | NULL | 4 | 1135000 | | 11 | Bravo | 1 | 250000 | | 11 | Charlie | 1 | 350000 |



Panduan Lengkap Query MySQL 307



| 11 | NULL | 2 | 600000 | | 12 | Bravo | 1 | 150000 | | 12 | Charlie | 1 | 175000 | | 12 | NULL | 2 | 325000 | | NULL | NULL | 8 | 2060000 | +---------+---------+---------------+----------------+



Perhatikan bahwa pada contoh diatas, terdapat beberapa baris tambahan yang dihasilkan dari klausa WITH ROLLUP (baris yang mengandung nilai NULL). Perhatikan juga bahwa WITH ROLLUP mengkalkulasi nilai pada kolom yang terdapat fungsi COUNT() dan SUM() Karena pada klausa GROUP BY kita mengelompokkan data urut berdasarkan bulan, baru kemudian nama, maka ketika MySQL membuat total untuk kelompok tersebut, MySQL akan memberikan nilai NULL pada kolom nama (untuk subtotal setiap bulan) dan nama + bulan untuk total semua data, perhatikan gambar berikut:



Gambar 17.1 Ilustrasi Klausa WITH ROLLUP Keterangan gambar: 



Angka 1 menunjukkan total per bulan, per nama







Angka 2 menunjukkan total keseluruhan data



308 BAB 17 Total dan Subtotal



Untuk lebih memahami cara kerja WITH ROLLUP, mari kita ubah query diatas dengan mengelompokkan data berdasarkan kolom thn_trx, bln_trx, dan nama, jalankan query berikut: 1. 2. 3. 4.



SELECT bln_trx, thn_trx, nama, COUNT(id_trx), SUM(nilai_trx) FROM sales GROUP BY bln_trx, thn_trx, nama WITH ROLLUP



Hasil: +---------+---------+---------+---------------+----------------+ | thn_trx | bln_trx | nama | COUNT(id_trx) | SUM(nilai_trx) | +---------+---------+---------+---------------+----------------+ | 2016 | 11 | Bravo | 1 | 250000 | | 2016 | 11 | Charlie | 1 | 350000 | | 2016 | 11 | NULL | 2 | 600000 | | 2016 | 12 | Bravo | 1 | 150000 | | 2016 | 12 | Charlie | 1 | 175000 | | 2016 | 12 | NULL | 2 | 325000 | | 2016 | NULL | NULL | 4 | 925000 | | 2017 | 3 | Alfa | 2 | 550000 | | 2017 | 3 | Bravo | 2 | 585000 | | 2017 | 3 | NULL | 4 | 1135000 | | 2017 | NULL | NULL | 4 | 1135000 | | NULL | NULL | NULL | 8 | 2060000 | +---------+---------+---------+---------------+----------------+



Pada contoh diatas, karena kita mengelompokkan data dengan urutan tahun, bulan, dan nama, maka sama seperti contoh sebelumnya, MySQL akan membuat baris total dengan memberikan nilai NULL urut dari belakang, yaitu dari kolom nama, kemudian bulan, dan terakhir tahun, perhatikan gambar berikut:



Panduan Lengkap Query MySQL 309



Gambar 17.2 Ilustrasi Klausa WITH ROLUP tiga kolom Keterangan gambar: 



Angka 1 menunjukkan total per tahun dan per bulan







Angka 2 menunjukkan total per thn_trx







Angka 3 menunjukkan total keseluruhan data



Dengan memperhatikan hasil pada dua contoh terakhir, dapat kita ketahui bahwa MySQL memberi nilai NULL pada setiap kolom hasil WITH ROLLUP. Agar hasil query lebih mudah dibaca, mari kita ganti nilai NULL menjadi nilai lain, misal TOTAL, kita ubah query menjadi berikut: 1. 2. 3. 4. 5. 6. 7. 8. 9.



SELECT IFNULL(thn_trx, "TOTAL") AS tahun, IFNULL(bln_trx, "TOTAL") AS bulan, IFNULL(nama, "TOTAL") AS nama_sales, COUNT(id_trx), SUM(nilai_trx) FROM sales GROUP BY thn_trx, bln_trx, nama WITH ROLLUP



310 BAB 17 Total dan Subtotal



Hasil: +-------+-------+------------+---------------+----------------+ | tahun | bulan | nama_sales | COUNT(id_trx) | SUM(nilai_trx) | +-------+-------+------------+---------------+----------------+ | 2016 | 11 | Bravo | 1 | 250000 | | 2016 | 11 | Charlie | 1 | 350000 | | 2016 | 11 | TOTAL | 2 | 600000 | | 2016 | 12 | Bravo | 1 | 150000 | | 2016 | 12 | Charlie | 1 | 175000 | | 2016 | 12 | TOTAL | 2 | 325000 | | 2016 | TOTAL | TOTAL | 4 | 925000 | | 2017 | 3 | Alfa | 2 | 550000 | | 2017 | 3 | Bravo | 2 | 585000 | | 2017 | 3 | TOTAL | 4 | 1135000 | | 2017 | TOTAL | TOTAL | 4 | 1135000 | | TOTAL | TOTAL | TOTAL | 8 | 2060000 | +-------+-------+------------+---------------+----------------+



Pada contoh diatas, kita gunakan fungsi IFNULL() untuk mengubah nilai NULL menjadi kata Total.



17.2. WITH ROLLUP - Mengganti Nilai NULL Sejauh ini, kita telah berhasil mengganti nilai NULL dengan kata TOTAL menggunakan fungsi IFNULL. Perlu diperhatikan bahwa jika kolom yang akan kita ganti nilai NULL nya memiliki nama alias, maka pada klausa GROUP BY, gunakan nama kolom tersebut bukan nama aliasnya. Misal kita memiliki tabel sales2 dengan data sebagai berikut: mysql> SELECT * FROM sales2; +--------+---------+------------+-----------+ | id_trx | nama | tgl_trx | nilai_trx | +--------+---------+------------+-----------+ | 1 | Alfa | 2017-03-20 | 250000 | | 2 | Charlie | 2017-03-10 | 175000 | | 3 | Bravo | 2017-02-22 | 310000 | | 4 | Bravo | 2017-02-11 | 250000 | | 5 | Alfa | 2017-03-15 | 300000 | +--------+---------+------------+-----------+ 5 rows in set (0.00 sec)



Selanjutnya kita gunakan fungsi IFNULL untuk mengubah nilai NULL menjadi string TOTAL, jalankan query berikut:



Panduan Lengkap Query MySQL 311



1. 2. 3. 4. 5. 6. 7.



SELECT IFNULL(nama, "TOTAL") AS nama_sales, COUNT(id_trx), SUM(nilai_trx) FROM sales2 GROUP BY nama_sales WITH ROLLUP



Hasil: +------------+---------------+----------------+ | nama_sales | COUNT(id_trx) | SUM(nilai_trx) | +------------+---------------+----------------+ | Alfa | 2 | 550000 | | Bravo | 2 | 560000 | | Charlie | 1 | 175000 | | NULL | 5 | 1285000 | +------------+---------------+----------------+



Pada contoh diatas, terlihat bahwa pada kolom nama_sales, nilai NULL tidak berubah menjadi TOTAL karena pada klausa GROUP BY, kita menggunakan nama kolom alias yaitu nama_sales, untuk memperbaikinya, gunakan nama kolom sehingga klausa GROUP BY menjadi GROUP BY nama Pada kondisi tertentu seperti ketika data dikelompokkan berdasarkan nilai kolom yang dimanipulasi, kita tidak dapat mengubah nilai NULL menjadi string TOTAL, perhatikan contoh berikut: 1. 2. 3. 4. 5. 6. 7. 8.



SELECT IFNULL(MONTH(tgl_trx), "TOTAL") as bln_trx, IFNULL(nama, "TOTAL") as nama_sales, COUNT(id_trx), SUM(nilai_trx) FROM sales2 GROUP BY MONTH(tgl_trx), nama WITH ROLLUP



Hasil: +---------+------------+---------------+----------------+ | bln_trx | nama_sales | COUNT(id_trx) | SUM(nilai_trx) | +---------+------------+---------------+----------------+ | 2 | Bravo | 2 | 560000 |



312 BAB 17 Total dan Subtotal



| 2 | TOTAL | 2 | 560000 | | 3 | Alfa | 2 | 550000 | | 3 | Charlie | 1 | 175000 | | 3 | TOTAL | 3 | 725000 | | 3 | TOTAL | 5 | 1285000 | +---------+------------+---------------+----------------+



Pada contoh diatas, terlihat bahwa nilai baris terakhir kolom bln_trx adalah 3, sejauh yang kita pelajari, baris ini seharusnya berisi string TOTAL, kenapa bisa seperti itu? hal ini disebabkan karena data dikelompokkan berdasarkan nilai output dari suatu fungsi, yang dalam hal ini fungsi YEAR() Contoh lain: kita kelompokkan data berdasarkan nama sales yang diubah hurufnya menjadi huruf kapital semua: 1. 2. 3. 4. 5. 6. 7.



SELECT IFNULL(UPPER(nama), "TOTAL") as nama_sales, COUNT(id_trx), SUM(nilai_trx) FROM sales2 GROUP BY UPPER(nama) WITH ROLLUP



Hasil: +------------+---------------+----------------+ | nama_sales | COUNT(id_trx) | SUM(nilai_trx) | +------------+---------------+----------------+ | ALFA | 2 | 550000 | | BRAVO | 2 | 560000 | | CHARLIE | 1 | 175000 | | CHARLIE | 5 | 1285000 | +------------+---------------+----------------+



Pada contoh diatas, terlihat bahwa meskipun kita menggunakan fungsi yang hanya sekedar mengubah bentuk huruf menjadi kapital (fungsi UPPER()), kita tetap tidak dapat mengubah nilai NULL menjadi string TOTAL. Untuk mengatasi berbagai permasalahan diatas, salah satu cara yang dapat kita gunakan adalah menggunakan subquery, contoh:



Panduan Lengkap Query MySQL 313



1. SELECT IFNULL(bln_trx, "TOTAL") AS bln_trx, nama_sales, jml_trx, total_trx 2. FROM ( 3. SELECT 4. MONTH(tgl_trx) as bln_trx, 5. IFNULL(nama, "TOTAL") AS nama_sales, 6. COUNT(id_trx) AS jml_trx, 7. SUM(nilai_trx) AS total_trx 8. FROM sales2 9. GROUP BY bln_trx, nama 10. WITH ROLLUP 11. ) AS temp



Hasil: +---------+------------+---------+-----------+ | bln_trx | nama_sales | jml_trx | total_trx | +---------+------------+---------+-----------+ | 2 | Bravo | 2 | 560000 | | 2 | TOTAL | 2 | 560000 | | 3 | Alfa | 2 | 550000 | | 3 | Charlie | 1 | 175000 | | 3 | TOTAL | 3 | 725000 | | TOTAL | TOTAL | 5 | 1285000 | +---------+------------+---------+-----------+



17.3. WITH ROLLUP dengan ORDER BY Ketika menggunakan klausa WITH ROLLUP, kita tidak bisa menggunakan klausa ORDER BY, karena keduanya bersifat mutually eksklusif yang artinya berdiri sendiri, untuk mengatasinya, kita dapat menggunakan implisit order dan subquery. Ketika menjalankan klausa GROUP BY, sebenarnya, di saat yang sama MYSQL juga akan mengurutkan data, karena pengurutan ini tidak dinyatakan secara jelas (eksplisit) maka sering disebut implisit order. Pada contoh sebelumnya, terlihat bahwa data tahun ditampilkan berurutan yaitu mulai dari 2016 kemudian 2017, begitu juga dengan bilangan bulan dan nama, semua diurutkan secara ascending (dari kecil ke besar) Pada implisit order, kita dapat mengubah bentuk urutan dengan cara menambahkan ASC atau DESC pada klausa GROUP BY, misal kita ingin 314 BAB 17 Total dan Subtotal



mengubah urutan tahun dan bulan menjadi descending (dari besar ke kecil), jalankan query berikut: 1. 2. 3. 4. 5. 6. 7. 8.



SELECT IFNULL(thn_trx, 'TOTAL') AS tahun, IFNULL(bln_trx, 'TOTAL') AS bulan, IFNULL(nama, 'TOTAL') AS nama_sales, COUNT(id_trx), SUM(nilai_trx) FROM sales GROUP BY thn_trx DESC, bln_trx DESC, nama WITH ROLLUP



Hasil: +-------+-------+------------+---------------+----------------+ | tahun | bulan | nama_sales | COUNT(id_trx) | SUM(nilai_trx) | +-------+-------+------------+---------------+----------------+ | 2017 | 3 | Alfa | 2 | 550000 | | 2017 | 3 | Bravo | 2 | 585000 | | 2017 | 3 | TOTAL | 4 | 1135000 | | 2017 | TOTAL | TOTAL | 4 | 1135000 | | 2016 | 12 | Bravo | 1 | 150000 | | 2016 | 12 | Charlie | 1 | 175000 | | 2016 | 12 | TOTAL | 2 | 325000 | | 2016 | 11 | Bravo | 1 | 250000 | | 2016 | 11 | Charlie | 1 | 350000 | | 2016 | 11 | TOTAL | 2 | 600000 | | 2016 | TOTAL | TOTAL | 4 | 925000 | | TOTAL | TOTAL | TOTAL | 8 | 2060000 | +-------+-------+------------+---------------+----------------+



Query diatas dapat berjalan dengan baik sesuai dengan yang diharapkan, namun sayangnya, pada MySQL versi 5.7, fitur ini sudah deprecated yang artinya sudah tidak disarankan lagi untuk digunakan karena pada versi berikutnya, fitur ini akan dihilangkan. Untuk itu disarankan untuk menggunakan eksplisit order dengan menggunakan klausa ORDER BY. Dengan eksplisit order, query diatas dapat kita ubah menjadi: 1. SELECT * FROM 2. ( 3. SELECT IFNULL(thn_trx, 'TOTAL') AS tahun, 4. IFNULL(bln_trx, 'TOTAL') AS bulan, 5. IFNULL(nama, 'TOTAL') AS nama_sales,



Panduan Lengkap Query MySQL 315



6. COUNT(id_trx), 7. SUM(nilai_trx) 8. FROM sales 9. GROUP BY thn_trx, bln_trx, nama 10. WITH ROLLUP 11. ) AS sales 12. ORDER BY tahun DESC, bulan DESC, nama_sales



Hasil: +-------+-------+------------+---------------+----------------+ | tahun | bulan | nama_sales | COUNT(id_trx) | SUM(nilai_trx) | +-------+-------+------------+---------------+----------------+ | TOTAL | TOTAL | TOTAL | 8 | 2060000 | | 2017 | TOTAL | TOTAL | 4 | 1135000 | | 2017 | 3 | Alfa | 2 | 550000 | | 2017 | 3 | Bravo | 2 | 585000 | | 2017 | 3 | TOTAL | 4 | 1135000 | | 2016 | TOTAL | TOTAL | 4 | 925000 | | 2016 | 12 | Bravo | 1 | 150000 | | 2016 | 12 | Charlie | 1 | 175000 | | 2016 | 12 | TOTAL | 2 | 325000 | | 2016 | 11 | Bravo | 1 | 250000 | | 2016 | 11 | Charlie | 1 | 350000 | | 2016 | 11 | TOTAL | 2 | 600000 | +-------+-------+------------+---------------+----------------+



Penjelasan: 



MySQL akan membuat tabel sementara hasil dari subquery dimana didalamnya sudah termasuk baris TOTAL,







Selanjutnya, data pada tabel tersebut diurutkan berdasarkan klausa ORDER BY yang ada pada query utama, dengan demikian, baris TOTAL juga ikut diurutkan, sehingga hasil yang diperoleh tidak sesuai harapan.



Bagaimana mengatasi hal tersebut? Sampai saat ini, tidak ada cara yang elegan untuk mengatasinya, kita hanya bisa mengakalinya dengan memberi nama pada baris TOTAL sedemikian rupa sehingga jika diurutkan, posisinya akan berada dibawah, misal kita ubah query menjadi berikut ini:



316 BAB 17 Total dan Subtotal



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



SELECT * FROM ( SELECT IFNULL(thn_trx, '1-TOTAL') AS tahun, IFNULL(bln_trx, '1-TOTAL') AS bulan, IFNULL(nama, 'TOTAL') AS nama_sales, COUNT(id_trx), SUM(nilai_trx) FROM sales GROUP BY thn_trx, bln_trx, nama WITH ROLLUP ) AS sales ORDER BY tahun DESC, bulan DESC, nama_sales



Hasil: +---------+---------+------------+---------------+----------------+ | tahun | bulan | nama_sales | COUNT(id_trx) | SUM(nilai_trx) | +---------+---------+------------+---------------+----------------+ | 2017 | 3 | Alfa | 2 | 550000 | | 2017 | 3 | Bravo | 2 | 585000 | | 2017 | 3 | TOTAL | 4 | 1135000 | | 2017 | 1-TOTAL | TOTAL | 4 | 1135000 | | 2016 | 12 | Bravo | 1 | 150000 | | 2016 | 12 | Charlie | 1 | 175000 | | 2016 | 12 | TOTAL | 2 | 325000 | | 2016 | 11 | Bravo | 1 | 250000 | | 2016 | 11 | Charlie | 1 | 350000 | | 2016 | 11 | TOTAL | 2 | 600000 | | 2016 | 1-TOTAL | TOTAL | 4 | 925000 | | 1-TOTAL | 1-TOTAL | TOTAL | 8 | 2060000 | +---------+---------+------------+---------------+----------------+



Pada contoh diatas, kita tambahkan awalan 1- pada TOTAL yang ada di kolom tahun dan bulan, karena jika diurutkan menurun, angka satu akan berada di paling bawah. Model penamaan ini sangat tergantung dengan jenis data yang ditampilkan.



17.4. WITH ROLLUP dengan LIMIT Klausa LIMIT juga dapat digunakan bersamaan dengan WITH ROLLUP. Klausa ini akan membatasi banyaknya baris yang akan dihasilkan. Penting untuk diperhatikan bahwa ketika menggunakan LIMIT, maka baris yang



Panduan Lengkap Query MySQL 317



ditambahkan oleh klausa WITH ROLLUP juga akan dihitung, misal kita jalankan query berikut: 1. 2. 3. 4. 5. 6. 7. 8. 9.



SELECT IFNULL(thn_trx, 'TOTAL') AS tahun, IFNULL(bln_trx, 'TOTAL') AS bulan, IFNULL(nama, 'TOTAL') AS nama_sales, COUNT(id_trx), SUM(nilai_trx) FROM sales GROUP BY thn_trx, bln_trx, nama WITH ROLLUP LIMIT 5



Hasil: +-------+-------+------------+---------------+----------------+ | tahun | bulan | nama_sales | COUNT(id_trx) | SUM(nilai_trx) | +-------+-------+------------+---------------+----------------+ | 2016 | 11 | Bravo | 1 | 250000 | | 2016 | 11 | Charlie | 1 | 350000 | | 2016 | 11 | TOTAL | 2 | 600000 | | 2016 | 12 | Bravo | 1 | 150000 | | 2016 | 12 | Charlie | 1 | 175000 | +-------+-------+------------+---------------+----------------+



Pada contoh diatas, MySQL mengambil 5 baris pertama termasuk baris TOTAL yang dihasilkan oleh klausa WITH ROLLUP.



318 BAB 17 Total dan Subtotal



BAB 18 Crosstab - Pivot Table Seperti telah kita ketahui, data pada database disimpan dalam bentuk tabel. Untuk menyajikan data tersebut, terkadang kita perlu mengolahnya terlebih dahulu sehingga bentuk data yang disajikan menjadi lebih informatif. Pada BAB ini, kita akan membahas salah satu bentuk penyajian data yang sering digunakan yaitu bentuk pivot table atau cross tab, bentuk ini sering kita jumpai pada Microsoft Excel. Secara sederhana, pivot table adalah proses mengubah data dari baris menjadi kolom, jika diperlukan, proses ini juga akan melakukan berbagai rekapitulasi data. Bentuk pivot table lebih informatif dibanding bentuk konvensional terutama ketika digunakan untuk membandingkan data secara horizontal.



18.1. Crosstab Sederhana Untuk mempermudah memahami cara membuat pivot table dengan SQL, kita akan mulai dengan beberapa contoh sederhana. Pada contoh kali ini, kita akan menggunakan data penjualan yang ada pada tabel sales3. Data pada tabel tersebut tampak seperti pada tabel berikut: +--------+---------+------------+-----+-----------+ | id_trx | nama | tgl_trx | tim | nilai_trx | +--------+---------+------------+-----+-----------+ | 1 | Alfa | 2017-01-10 | 1 | 250000 | | 2 | Charlie | 2017-01-02 | 2 | 175000 | | 3 | Bravo | 2017-01-01 | 1 | 310000 | | 4 | Bravo | 2017-02-04 | 1 | 250000 | | 5 | Alfa | 2017-01-15 | 1 | 125000 | | 6 | Bravo | 2017-02-07 | 1 | 275000 | | 7 | Alfa | 2017-02-05 | 1 | 215000 | | 8 | Alfa | 2017-02-22 | 1 | 350000 | | 9 | Alfa | 2017-02-02 | 1 | 250000 | | 10 | Charlie | 2017-01-23 | 2 | 350000 | | 11 | Charlie | 2017-02-22 | 2 | 300000 | | 12 | Delta | 2017-02-11 | 2 | 450000 | | 13 | Delta | 2017-02-17 | 2 | 550000 | +--------+---------+------------+-----+-----------+



Panduan Lengkap Query MySQL 319



Selanjutnya kita tampilkan data penjualan per bulan, per sales. Query yang kita jalankan: 1. 2. 3. 4. 5. 6. 7.



SELECT IFNULL(nama, "TOTAL") AS NAMA_SALES, SUM( IF(MONTH(tgl_trx) = 1, nilai_trx, 0) ) AS januari, SUM( IF(MONTH(tgl_trx) = 2, nilai_trx, 0) ) AS februari, SUM( nilai_trx ) AS total FROM sales3 GROUP BY nama WITH ROLLUP



Hasil: +------------+---------+----------+---------+ | NAMA_SALES | januari | februari | total | +------------+---------+----------+---------+ | Alfa | 375000 | 815000 | 1190000 | | Bravo | 310000 | 525000 | 835000 | | Charlie | 525000 | 300000 | 825000 | | Delta | 0 | 1000000 | 1000000 | | TOTAL | 1210000 | 2640000 | 3850000 | +------------+---------+----------+---------+



Pada query diatas, kita menggunakan klaua WITH ROLLUP untuk menampilkan total nilai transaksi, penggunaan klausa ini telah kita bahas pada bab sebelumnya. Selain itu, kita juga menggunakan fungsi IFNULL untuk mengganti nilai NULL yang dihasilkan kalusa WITH ROLLUP dengan string TOTAL. Kita juga menggunakan fungsi MONTH() untuk mengambil data bulan dari data tgl_trx, Pada query diatas, kita menggunakan fungsi IF untuk melakukan pengujian pada hasil fungsi MONTH(), jika fungsi tersebut menghasilkan nilai 1 (baris 2), maka jumlahkan nilai pada kolom nilai_trx, jika tidak, maka hasilkan nilai 0, selanjutnya simpan hasil tersebut pada kolom januari, dengan demikian, pada query: SUM( IF(MONTH(tgl_trx) = 1, nilai_trx, 0) ) AS januari



jika fungsi MONTH() menghasilkan nilai 1, maka query akan berbentuk: SUM(nilai_trx) AS januari



320 BAB 18 Crosstab - Pivot Table



Proses ini juga terjadi pada fungsi IF yang digunakan untuk menguji bulan 2 (baris 3) dan bulan 3 (baris 4) . Pada baris berikutnya (baris 5), kita jumlahkan semua baris pada kolom nilai_trx ( SUM(nilai_trx) ) untuk mendapatkan nila total transaksi yang dikelompokkan per nama sales ( GROUP BY nama ). Terakhir, kita gunakan klausa WITH ROLLUP untuk menambahkan baris total. Selanjutnya mari kita lengkapi tabel hasil query dengan menambahkan data jumlah transaksi setiap bulan untuk masing-masing sales. Untuk keperluan tersebut, kita gunakan fungsi COUNT(). Adapun query yang kita jalankan adalah: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.



SELECT IFNULL(nama, "TOTAL") AS nama_sales, COUNT( IF(MONTH(tgl_trx) = 1, nilai_trx, NULL) SUM( IF(MONTH(tgl_trx) = 1, nilai_trx, 0) ) AS COUNT( IF(MONTH(tgl_trx) = 2, nilai_trx, NULL) SUM( IF(MONTH(tgl_trx) = 2, nilai_trx, 0) ) AS COUNT( nilai_trx ) AS jml_trx, SUM( nilai_trx ) AS total FROM sales3 GROUP BY nama WITH ROLLUP



) AS trx_1, bln_1, ) AS trx_2, bln_2,



Hasil: +------------+-------+---------+-------+---------+---------+---------+ | nama_sales | trx_1 | bln_1 | trx_2 | bln_2 | jml_trx | total | +------------+-------+---------+-------+---------+---------+---------+ | Alfa | 2 | 375000 | 3 | 815000 | 5 | 1190000 | | Bravo | 1 | 310000 | 2 | 525000 | 3 | 835000 | | Charlie | 2 | 525000 | 1 | 300000 | 3 | 825000 | | Delta | 0 | 0 | 2 | 1000000 | 2 | 1000000 | | TOTAL | 5 | 1210000 | 8 | 2640000 | 13 | 3850000 | +------------+-------+---------+-------+---------+---------+---------+



Pada query diatas, untuk menghitung banyaknya transaksi, kita hitung banyaknya baris pada kolom tgl_trx. Perhatikan bahwa pada fungsi COUNT(), seperti pada COUNT(IF(MONTH(tgl_trx)=1, nilai_trx, NULL)) AS trx_1, kita menggunakan nilai NULL, bukan angka 0 seperti yang kita gunakan pada fungsi SUM(). Hal ini dikarenakan fungsi COUNT() akan tetap menghitung baris yang bernilai 0, sehingga hasil yang kita peroleh menjadi lebih akurat.



Panduan Lengkap Query MySQL 321



18.2. Menambahkan Baris Subtotal Pada kondisi tertentu, kita ingin menambahkan baris yang berisi nilai total dari sekelompok nilai tertentu. Baris ini sering disebut dengan subtotal, pembahasan tetang subtotal dapat diikuti pada pada BAB 17. Melanjutkan contoh sebelumnya, mari kita buat nilai subtotal untuk masing-masing tim. Query yang kita jalankan: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.



SELECT IFNULL(nama, "SUB TOTAL") AS nama_sales, IFNULL(tim, "TOTAL") as sales_tim, COUNT( IF(MONTH(tgl_trx) = 1, nilai_trx, NULL) SUM( IF(MONTH(tgl_trx) = 1, nilai_trx, 0) ) AS COUNT( IF(MONTH(tgl_trx) = 2, nilai_trx, NULL) SUM( IF(MONTH(tgl_trx) = 2, nilai_trx, 0) ) AS COUNT( nilai_trx ) AS jml_tx, SUM( nilai_trx ) AS total FROM sales3 GROUP BY tim, nama WITH ROLLUP



) AS tx_1, bln_1, ) AS tx_2, bln_2,



Hasil: +------------+-----------+------+---------+------+---------+--------+---------+ | nama_sales | sales_tim | tx_1 | bln_1 | tx_2 | bln_2 | jml_tx | total | +------------+-----------+------+---------+------+---------+--------+---------+ | Alfa | 1 | 2 | 375000 | 3 | 815000 | 5 | 1190000 | | Bravo | 1 | 1 | 310000 | 2 | 525000 | 3 | 835000 | | SUB TOTAL | 1 | 3 | 685000 | 5 | 1340000 | 8 | 2025000 | | Charlie | 2 | 2 | 525000 | 1 | 300000 | 3 | 825000 | | Delta | 2 | 0 | 0 | 2 | 1000000 | 2 | 1000000 | | SUB TOTAL | 2 | 2 | 525000 | 3 | 1300000 | 5 | 1825000 | | SUB TOTAL | TOTAL | 5 | 1210000 | 8 | 2640000 | 13 | 3850000 | +------------+-----------+------+---------+------+---------+--------+---------+



Perhatikan bahwa sekarang muncul baris baru dengan nilai SUB TOTAL, baris ini muncul karena kita menambahkan kolom tim pada klausa GROUP BY, sehingga ketika klausa WITH ROLLUP dijalankan, MySQL akan menghitung subtotal berdasarkan nilai yang sama yang ada pada kolom tim.



322 BAB 18 Crosstab - Pivot Table



18.3. Mengubah Urutan Data Pivot Table Jika kita perhatikan contoh sebelumnya, ketika kita menggunakan klausa GROUP BY, selain data dikelompokkan, data tersebut juga akan ditampilkan secara urut mulai dari nilai terkecil ke nilai terbesar, misal data pada kolom nama_sales ditampilkan secara urut dari abjad terkecil ke terbesar, demikian juga dengan kolom sales_tim. Kenapa bisa demikian? Seperti yang telah kita bahas pada bab 17, ketika menjalankan klausa GROUP BY, MySQL akan sekaligus mengurutkan data berdasarkan kolom yang ada pada klausa tersebut secara ascending (urut dari terkecil ke terbesar), model ini sering disebut implisit order. Kita dapat mengubah pola pengurutan ini dengan menambahkan ASC atau DESC pada klausa GROUP BY, misal kita ubah urutan data pada kolom nama_sales dan sales_tim menjadi descending. Jalankan query berikut: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.



SELECT IFNULL(nama, 'SUB TOTAL') AS nama_sales, IFNULL(tim, 'TOTAL') as sales_tim, COUNT( IF(MONTH(tgl_trx) = 1, nilai_trx, NULL) SUM( IF(MONTH(tgl_trx) = 1, nilai_trx, 0) ) AS COUNT( IF(MONTH(tgl_trx) = 2, nilai_trx, NULL) SUM( IF(MONTH(tgl_trx) = 2, nilai_trx, 0) ) AS COUNT( nilai_trx ) AS jml_tx, SUM( nilai_trx ) AS total FROM sales3 GROUP BY tim DESC, nama DESC WITH ROLLUP



) AS tx_1, bln_1, ) AS tx_2, bln_2,



Hasil yang kita peroleh: +------------+-----------+------+---------+------+---------+--------+---------+ | nama_sales | sales_tim | tx_1 | bln_1 | tx_2 | bln_2 | jml_tx | total | +------------+-----------+------+---------+------+---------+--------+---------+ | Delta | 2 | 0 | 0 | 2 | 1000000 | 2 | 1000000 | | Charlie | 2 | 2 | 525000 | 1 | 300000 | 3 | 825000 | | SUB TOTAL | 2 | 2 | 525000 | 3 | 1300000 | 5 | 1825000 | | Bravo | 1 | 1 | 310000 | 2 | 525000 | 3 | 835000 | | Alfa | 1 | 2 | 375000 | 3 | 815000 | 5 | 1190000 | | SUB TOTAL | 1 | 3 | 685000 | 5 | 1340000 | 8 | 2025000 | | SUB TOTAL | TOTAL | 5 | 1210000 | 8 | 2640000 | 13 | 3850000 | +------------+-----------+------+---------+------+---------+--------+---------+



Panduan Lengkap Query MySQL 323



Perhatikan bahwa pada contoh diatas, data diurutkan berdasarkan nama_sales dan sales_tim secara descending. Seperti yang telah kita bahas pada bab 17, cara ini merupakan cara yang paling mudah untuk mengubah urutan data pada klausa GROUP BY, namun, pada MySQL versi 5.7, fitur ini sudah deprecated, artinya tidak disarankan untuk digunakan, karena ke depan fitur ini akan dihapus, untuk itu, disarankan untuk menggunakan eksplisit order dengan menggunakan klausa ORDER BY. Selanjutnya mari kita jalankan query berikut: 1. SELECT * FROM ( 2. SELECT IFNULL(nama, '1 - SUB TOTAL') AS nama_sales, 3. IFNULL(tim, '0 - TOTAL') as sales_tim, 4. COUNT(IF(MONTH(tgl_trx) = 1, nilai_trx, NULL)) AS trx_1, 5. SUM(IF(MONTH(tgl_trx) = 1, nilai_trx, 0)) AS bln_1, 6. COUNT(IF(MONTH(tgl_trx) = 2, nilai_trx, NULL)) AS trx_2, 7. SUM(IF(MONTH(tgl_trx) = 2, nilai_trx, 0)) AS bln_2, 8. COUNT(nilai_trx) AS jml_trx, 9. SUM(nilai_trx) AS total 10. FROM sales3 11. GROUP BY tim, nama 12. WITH ROLLUP 13. ) AS sales 14. ORDER BY sales_tim DESC, nama_sales DESC



Hasil: +---------------+-----------+-------+---------+-------+---------+---------+---------+ | nama_sales | sales_tim | trx_1 | bln_1 | trx_2 | bln_2 | jml_trx | total | +---------------+-----------+-------+---------+-------+---------+---------+---------+ | Delta | 2 | 0 | 0 | 2 | 1000000 | 2 | 1000000 | | Charlie | 2 | 2 | 525000 | 1 | 300000 | 3 | 825000 | | 1 - SUB TOTAL | 2 | 2 | 525000 | 3 | 1300000 | 5 | 1825000 | | Bravo | 1 | 1 | 310000 | 2 | 525000 | 3 | 835000 | | Alfa | 1 | 2 | 375000 | 3 | 815000 | 5 | 1190000 | | 1 - SUB TOTAL | 1 | 3 | 685000 | 5 | 1340000 | 8 | 2025000 | | 1 - SUB TOTAL | 0 - TOTAL | 5 | 1210000 | 8 | 2640000 | 13 | 3850000 | +---------------+-----------+-------+---------+-------+---------+---------+---------+



Pada query diatas, pertama tama MySQL akan mengeksekusi subquery, hasilnya disimpan dalam temporary table, selanjutnya, data temporary table tersebut oleh query utama diurutkan berdasarkan kolom nama_sales dan sales_tim Jika memperhatikan contoh diatas, agak repot ketika menggunakan klausa ORDER BY bersama dengan klausa WITH ROLLUP, hal ini dikarenakan kita 324 BAB 18 Crosstab - Pivot Table



harus mengatur nilai pada kolom hasil klausa WITH ROLLUP sedemikian rupa sehingga berada di urutan paling bawah, permasalahan ini telah kita bahas pada bab 17.



18.4. Menambah Baris Total Dengan Query Tersendiri Pada bagian sebelumnya, kita dapat dengan mudah menambahkan baris total dan subtotal dengan klausa WITH ROLLUP, pada kondisi tertentu, kita tidak dapat mengandalkan klausa tersebut, misal ketika kita ingin menampilkan data berdasarkan kolom nilai_trx yang diurutkan secara descending Jika kita menggunakan klausa WITH ROLLUP, maka baris total akan selalu berada diatas karena pasti jumlahnya paling besar, untuk mengatasi hal tersebut, kita dapat menambahkan baris TOTAL dengan query tersendiri. Jalankan query berikut: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22.



SELECT * FROM ( SELECT nama, tim, SUM(IF(MONTH(tgl_trx) = 1, nilai_trx, 0)) AS bln_1, COUNT(IF(MONTH(tgl_trx) = 1, id_trx, NULL)) AS trx_1, SUM(IF(MONTH(tgl_trx) = 2, nilai_trx, 0)) AS bln_2, COUNT(IF(MONTH(tgl_trx) = 2, nilai_trx, NULL)) AS trx_2, COUNT(id_trx) AS jml_trx, SUM(nilai_trx) AS total_trx FROM sales3 GROUP BY tim, nama ORDER BY total_trx DESC ) AS tabel_sales UNION ALL SELECT 'TOTAL' AS nama, '' AS tim, SUM(IF(MONTH(tgl_trx) = 1, nilai_trx, 0)) AS bln_1, COUNT(IF(MONTH(tgl_trx) = 1, id_trx, NULL)) AS trx_1, SUM(IF(MONTH(tgl_trx) = 2, nilai_trx, 0)) AS bln_2, COUNT(IF(MONTH(tgl_trx) = 2, nilai_trx, NULL)) AS trx_2, COUNT(id_trx) AS jml_trx, SUM(nilai_trx) AS total_trx FROM tabel_sales



Hasil: Panduan Lengkap Query MySQL 325



+---------+-----+---------+-------+---------+-------+---------+-----------+ | nama | tim | bln_1 | trx_1 | bln_2 | trx_2 | jml_trx | total_trx | +---------+-----+---------+-------+---------+-------+---------+-----------+ | Alfa | 1 | 375000 | 2 | 815000 | 3 | 5 | 1190000 | | Delta | 2 | 0 | 0 | 1000000 | 2 | 2 | 1000000 | | Bravo | 1 | 310000 | 1 | 525000 | 2 | 3 | 835000 | | Charlie | 2 | 525000 | 2 | 300000 | 1 | 3 | 825000 | | TOTAL | | 1210000 | 5 | 2640000 | 8 | 13 | 3850000 | +---------+-----+---------+-------+---------+-------+---------+-----------+



Pada contoh diatas, pertama tama kita buat subquery yang berisi rekap data penjualan yang telah diurutkan berdasarkan kolom total_trx, selanjutnya, dengan klausa UNION ALL, kita tambahan baris baru yang berisi TOTAL dari transaksi. Penggunaan klausa UNION ini telah kita bahas pada BAB 16



18.5. Pivot Table Dinamis Pada bagian sebelumnya, kita telah membahas bagaimana cara membuat pivot table dengan MySQL. Pada pembahasan tersebut, jumlah kolom hasil pivot table sudah kita tentukan pada statemen SELECT (bentuknya statis). Pada banyak kondisi, cara ini sudah cukup memadahi, namun, pada kondisi tertentu, jumlah kolom pada hasil pivot table dapat berubah ubah sesuai dengan jumlah baris yang ada. Pada kondisi dimana jumlah kolom hasil pivot table berubah ubah, maka query SQL nya juga ikut berubah, sehingga penggunaan model statis sudah tidak dapat digunakan lagi, untuk itu, kita perlu menggunakan cara lain yaitu dengan pivot table dinamis dynamic cross tab. Untuk membuat pivot table dinamis, kita harus membuat statemen SQL secara dinamis. Karena SQL merupakan bahasa deklaratif bukan bahasa prosedural, maka kita tidak bisa membuat perintah SQL secara dinamis begitu saja, untuk itu, kita perlu “mengakalinya”, caranya, kita buat perintah SQL menggunakan perintah SQL yang seolah-olah mengambil data. Sebagai contoh, mari kita ubah SQL statis yang telah kita bahas pada bagian sebelumnya menjadi model SQL dinamis, jalankan query berikut:



326 BAB 18 Crosstab - Pivot Table



1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21.



SET @sql_dinamis = ( SELECT GROUP_CONCAT( DISTINCT CONCAT('SUM( IF(MONTH(tgl_trx) = ' , MONTH(tgl_trx) , ',nilai_trx,0) ) AS bln_' , MONTH(tgl_trx) ) ) FROM sales3 ); SET @SQL = CONCAT('SELECT IFNULL(nama, "TOTAL") AS nama_sales, ', @sql_dinamis, ' FROM sales3 GROUP BY nama WITH ROLLUP' ); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;



Hasil: +------------+---------+---------+ | nama_sales | bln_1 | bln_2 | +------------+---------+---------+ | Alfa | 375000 | 815000 | | Bravo | 310000 | 525000 | | Charlie | 525000 | 300000 | | Delta | 0 | 1000000 | | TOTAL | 1210000 | 2640000 | +------------+---------+---------+



Pada query diatas, jumlah kolom akan terus bertambah jika ada transaksi di bulan Maret, April, Mei, dst… Jika digambarkan dalam bentuk query statis, maka query dinamis diatas akan sama seperti query berikut ini: 1. 2. 3. 4. 5. 6.



SELECT



IFNULL(nama, "TOTAL") AS nama_sales, SUM( IF(MONTH(tgl_trx) = 1, nilai_trx,0) ) AS bln_1, SUM( IF(MONTH(tgl_trx) = 2, nilai_trx,0) ) AS bln_2 FROM sales3 GROUP BY nama WITH ROLLUP



Panduan Lengkap Query MySQL 327



Dari contoh diatas dapat disimpulkan bahwa inti dari query dinamis adalah kita sedang menulis/membuat query dengan bentuk yang berbeda beda sesuai dengan jumlah baris yang ada. Berikut ini langkah langkah yang perlu diperhatikan ketika membuat query dinamis: 1. Tentukan bagian query yang bersifat dinamis Untuk dapat menentukan bagian query yang berubah ubah/dinamis, maka kita perlu untuk menulis query statisnya terlebih dahulu. Pada query diatas, bagian query dinamis adalah baris ke dua dan ke 4: 2. SUM( IF(MONTH(tgl_trx) = 1, nilai_trx,0) ) AS bln_1, 3. SUM( IF(MONTH(tgl_trx) = 2, nilai_trx,0) ) AS bln_2



Selanjutnya, kita susun query sedemikian rupa sehingga menghasilkan query seperti pada query diatas, kemudian simpan hasilnya pada sebuah variabel, contoh: 1. SET @sql_dinamis = ( 2. SELECT 3. GROUP_CONCAT( DISTINCT 4. CONCAT('SUM( IF(MONTH(tgl_trx) = ' 5. , MONTH(tgl_trx) 6. , ',nilai_trx,0) ) AS bln_' 7. , MONTH(tgl_trx) 8. ) 9. ) 10. FROM sales3 11. );



Pada contoh diatas, kita menyimpan query kedalam variabel yang bernama @sql_dinamis. Perhatikan juga bahwa kita menggunakan klausa DISTINCT. Klausa ini digunakan untuk menggabungkan baris yang dobel, sedangkan GROUP_CONCAT akan menggabungkan baris dengan tanda koma. SQL utama dari query diatas adalah:



328 BAB 18 Crosstab - Pivot Table



1. CONCAT('SUM( IF(MONTH(tgl_trx) = ' 2. , MONTH(tgl_trx) 3. , ',nilai_trx,0) ) AS bln_' 4. , MONTH(tgl_trx) 5. )



Query tersebut akan menghasilkan: +----------------------------------------------------+ | query | +----------------------------------------------------+ | SUM( IF(MONTH(tgl_trx) = 1,nilai_trx,0) ) AS bln_1 | | SUM( IF(MONTH(tgl_trx) = 1,nilai_trx,0) ) AS bln_1 | | SUM( IF(MONTH(tgl_trx) = 1,nilai_trx,0) ) AS bln_1 | | SUM( IF(MONTH(tgl_trx) = 2,nilai_trx,0) ) AS bln_2 | | SUM( IF(MONTH(tgl_trx) = 1,nilai_trx,0) ) AS bln_1 | | SUM( IF(MONTH(tgl_trx) = 2,nilai_trx,0) ) AS bln_2 | | SUM( IF(MONTH(tgl_trx) = 2,nilai_trx,0) ) AS bln_2 | | SUM( IF(MONTH(tgl_trx) = 2,nilai_trx,0) ) AS bln_2 | | SUM( IF(MONTH(tgl_trx) = 2,nilai_trx,0) ) AS bln_2 | | SUM( IF(MONTH(tgl_trx) = 1,nilai_trx,0) ) AS bln_1 | | SUM( IF(MONTH(tgl_trx) = 2,nilai_trx,0) ) AS bln_2 | | SUM( IF(MONTH(tgl_trx) = 2,nilai_trx,0) ) AS bln_2 | | SUM( IF(MONTH(tgl_trx) = 2,nilai_trx,0) ) AS bln_2 | +----------------------------------------------------+



Penambahan klausa DISTINCT pada CONCAT akan menggabungkan baris yang sama, sehingga diperoleh hasil +----------------------------------------------------+ | query | +----------------------------------------------------+ | SUM( IF(MONTH(tgl_trx) = 1,nilai_trx,0) ) AS bln_1 | | SUM( IF(MONTH(tgl_trx) = 2,nilai_trx,0) ) AS bln_2 | +----------------------------------------------------+ Selanjutnya, dengan fungsi GROUP_CONCAT, kita gabung semua baris menjadi sebuah string dengan pemisah tanda koma (,), hasil yang kita peroleh: +--------------------------------------------------------------------+ | SUM( IF(MONTH(tgl_trx) = 1,nilai_trx,0) ) AS bln_1,SUM( IF(MONTH(tgl_trx) = 2,nilai_trx,0) ) AS bln_2 | +--------------------------------------------------------------------+



Panduan Lengkap Query MySQL 329



2. Gabungan query dinamis dengan query lainnya. Setelah kita buat query dinamis, selanjutnya kita gabungkan query tersebut dengan query lainnya, sehingga menghasilkan query yang utuh, hasilnya kita simpan pada sebuah variable: 1. SET @sql = CONCAT('SELECT nama, ', 2. @sql_dinamis, ' 3. FROM tabel_sales 4. GROUP BY nama WITH ROLLUP' 5. );



Pada contoh diatas, kita simpan query ke dalam variable @sql. Pastikan isi dari variable tersebut telah sesuai dengan yang kita harapkan. Jalankan perintah berikut: SELECT @sql;



Hasil yang kita peroleh: SELECT IFNULL(nama, "TOTAL") AS nama_sales, SUM( IF(MONTH(tgl_trx) = 1,nilai_trx,0) ) AS bln_1,SUM( IF(MONTH(tgl_trx) = 2,nilai_trx,0) ) AS bln_2 FROM tabel_sales GROUP BY nama WITH ROLLUP



hasil tersebut telah sesuai dengan yang kita harapkan. 3. Eksekusi Query Setelah query kita susun dengan lengkap, terakhir kita eksekusi query tersebut. Karena query kita simpan dalam variable, maka kita tidak bisa langsung mengeksekusinya, melainkan harus kita jalankan melalui statemen PREPARE kemudian dieksekusi dengan statemen EXECUTE 1. PREPARE stmt FROM @sql; 2. EXECUTE stmt; 3. DEALLOCATE PREPARE stmt;



330 BAB 18 Crosstab - Pivot Table



Statemen PREPARE digunakan untuk menyimpan query agar dapat dieksekusi di lain waktu, pada contoh diatas, dengan klausa FROM, query pada variable @sql kita simpan pada statemen PREPARE, statemen tersebut kita beri nama stmt (kependekan dari statemen), Anda bebas memberi nama lain. Selanjutnya, kita jalankan statemen EXECUTE untuk menjalankan query telah kita simpan pada statemen PREPARE. Pada tahap ini, MySQL akan menampilkan hasil query. Sebagai tambahan, kita dapat menjalankan statemen DEALLOCATE PREPARE stmt Statemen ini akan melepas/merelease/menghapus statemen PREPARE yang bernama stmt. Hal ini bertujuan untuk mengurangi jumlah statemen PREPARE yang tersimpan agar tidak melampaui batas maksimum yang diperbolehkan. Pada contoh query dinamis sebelumnya, kita pisahkan antara query dinamis dengan query utama, masing masing disimpan pada variabel tersendiri (@sql_dinamis dan @sql) hal tersebut bertujuan agar kode yang kita buat lebih mudah dipahami dan dipelajari. Kita dapat menyederhanakan query tersebut menjadi satu sebagai berikut: 1. SET @sql = CONCAT('SELECT IFNULL(nama, "TOTAL") AS nama_sales, ', 2. ( SELECT 3. GROUP_CONCAT( DISTINCT 4. CONCAT('SUM( IF(MONTH(tgl_trx) = ' 5. , MONTH(tgl_trx) 6. , ',nilai_trx,0) ) AS bln_' 7. , MONTH(tgl_trx) 8. ) 9. ) 10. FROM tabel_sales 11. ), 12. ' FROM tabel_sales 13. GROUP BY nama WITH ROLLUP' 14. ); 15. 16. PREPARE stmt FROM @sql; 17. EXECUTE stmt; 18. DEALLOCATE PREPARE stmt;



Panduan Lengkap Query MySQL 331



Setelah paham bagaimana membuat pivot table dinamis dengan MySQL, selanjutnya mari kita buat variasi dengan: 1. Menambahkan kolom jumlah transaksi yang berisi banyaknya transaksi per bulan, per nama petugas. 2. Menambahkan kolom TOTAL yang berisi nilai total penjualan dari masing-masing petugas. Query yang kita perlukan adalah sebagai berikut: 1. SET @sql_dinamis = ( 2. SELECT 3. GROUP_CONCAT( DISTINCT 4. CONCAT('COUNT( IF(MONTH(tgl_trx) = ' 5. , MONTH(tgl_trx) 6. , ', nilai_trx, NULL) ) AS trx_' 7. , MONTH(tgl_trx) 8. , ', SUM( IF(MONTH(tgl_trx) = ' 9. , MONTH(tgl_trx) 10. , ', nilai_trx, 0) ) AS bln_' 11. , MONTH(tgl_trx) 12. ) 13. ) 14. FROM tabel_sales 15. ); 16. 17. SET @SQL = CONCAT('SELECT IFNULL(nama, "TOTAL") AS nama_sales, ', 18. @sql_dinamis, ', 19. COUNT(tgl_trx) AS JML_TRX, 20. SUM(nilai_trx) AS TOTAL 21. FROM sales3 22. GROUP BY nama 23. WITH ROLLUP' 24. ); 25. 26. PREPARE stmt FROM @sql; 27. EXECUTE stmt; 28. DEALLOCATE PREPARE stmt;



Hasil yang kita peroleh:



332 BAB 18 Crosstab - Pivot Table



+------------+-------+---------+-------+---------+---------+---------+ | nama_sales | trx_1 | bln_1 | trx_2 | bln_2 | JML_TRX | TOTAL | +------------+-------+---------+-------+---------+---------+---------+ | Alfa | 2 | 375000 | 3 | 815000 | 5 | 1190000 | | Bravo | 1 | 310000 | 2 | 525000 | 3 | 835000 | | Charlie | 2 | 525000 | 1 | 300000 | 3 | 825000 | | Delta | 0 | 0 | 2 | 1000000 | 2 | 1000000 | | TOTAL | 5 | 1210000 | 8 | 2640000 | 13 | 3850000 | +------------+-------+---------+-------+---------+---------+---------+



Pada tabel diatas, dengan fungsi COUNT() kita tambahkan kolom trx_1, trx_2, dan trx_3. Fungsi ini akan menghitung jumlah baris pada kolom tgl_trx berdasarkan bulan (baris 4-11). Selain itu, kita juga menambahkan kolom JML_TRX yang berisi total jumlah transaksi, kolom tersebut dihasilkan oleh fungsi COUNT(tgl_trx) yang ada pada baris 19. Terakhir, dengan fungsi SUM(nilai_trx) AS TOTAL (baris 20) kita tambahkan kolom TOTAL Jika digambarkan dalam query yang utuh, query diatas akan berbentuk seperti query berikut: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.



SELECT IFNULL(nama, "TOTAL") AS nama_sales, COUNT( IF(MONTH(tgl_trx) = 1, nilai_trx, NULL) SUM( IF(MONTH(tgl_trx) = 1, nilai_trx, 0) ) AS COUNT( IF(MONTH(tgl_trx) = 2, nilai_trx, NULL) SUM( IF(MONTH(tgl_trx) = 2, nilai_trx, 0) ) AS COUNT(tgl_trx) AS JML_TRX, SUM(nilai_trx) AS TOTAL FROM sales3 GROUP BY nama WITH ROLLUP



) AS trx_1, bln_1, ) AS trx_2, bln_2,



Panduan Lengkap Query MySQL 333



Halaman ini sengaja dikosongkan Jagowebdev.com



334 BAB 18 Crosstab - Pivot Table



BAB 19 FULL TEXT Search Pada bab 9, kita telah membahas bagaimana melalukan pencarian data dengan keyword LIKE. Dengan menggunakan wildcard % kita dapat mencari baris pada suatu tabel yang mengandung kata kata tertentu. Penggunaan keyword ini sangat fleksibel, namun pada kondisi tertentu, memiliki beberapa keterbatasan, yaitu: 



Penggunaan wildcard dalam keyword LIKE pada umumnya akan membuat MySQL melakukan pencarian pada setiap baris yang ada pada suatu tabel (index pada tabel jarang sekali digunakan), akibatnya proses pencarian memakan waktu lama terutama jika tabel tersebut terdiri dari banyak baris.







Pada kondisi tertentu, dengan keyword LIKE kita akan sulit mendefinisikan kolom yang mengandung dan tidak mengandung kata tertentu (kita akan berkutat dengan banyak keyword LIKE dan NOT LIKE)







Hasil pencarian menggunakan keyword LIKE akan memiliki bobot yang sama, tidak membedakan jumlah kata yang cocok. Pada FULL TEXT search, hal ini akan dibedakan dan ditambah kriteria tertentu sehingga menghasilkan ranking pencarian.



Semua kelemahan ini dapat diatasi dengan menggunakan full-text search. Ketika menggunakan full-text search, MySQL tidak perlu melakukan pencarian pada setiap baris yang ada pada tabel, MySQL akan menggunakan index yang telah dibuat, sehingga secara efisien dan efektif dapat menentukan baris mana yang cocok dan yang tidak cocok, berapa tingkat kecocokannya, dll.



Panduan Lengkap Query MySQL 335



19.1. Engine dan Tipe Data Fitur full-text search ini sebelumnya hanya dapat digunakan pada tabel yang menggunakan engine MyISAM, namun, mulai MySQL versi 5.6, fitur ini dapat digunakan pada engine InnoDB. Sebagai tambahan, full-text search hanya dapat digunakan pada tipe data berjenis karakter yaitu: CHAR, VARCHAR, dan TEXT



19.2. Membuat Index Untuk dapat menggunakan fitur full-text search pada suatu kolom, maka kolom tersebut harus dijadikan index, dan harus dilakukan re-index jika ada perubahan data. Setelah index didefinisikan, proses re-index ini akan otomatis dijalankan MySQL ketika terjadi perubahan data. Untuk membuat index full-text pada kolom, kita gunakan klausa FULLTEXT ketika membuat tabel, pendefinisian index dilakukan pada level tabel, contoh kita buat tabel buku dengan index FULLTEXT pada kolom deskripsi dan primary key pada kolom id_buku: 1. CREATE TABLE `buku` ( 2. `id_buku` INT(11) NOT NULL AUTO_INCREMENT, 3. `isbn` CHAR(13) NOT NULL, 4. `judul` VARCHAR(255) NOT NULL, 5. `id_pengarang` TINYINT(4) NOT NULL, 6. `id_penerbit` TINYINT(4) NOT NULL, 7. `tgl_terbit` DATE NOT NULL, 8. `harga` INT(11) NOT NULL, 9. `status` TINYINT(1) NOT NULL, 10. `stok` TINYINT(4) NOT NULL, 11. `kategori` VARCHAR(50) NOT NULL, 12. `url` VARCHAR(255) NULL DEFAULT NULL, 13. PRIMARY KEY (`id_buku`), 14. FULLTEXT INDEX `judul_fulltext` (`judul`) 15. )



Pada query diatas, perintah FULLTEXT INDEX `judul_fulltext` (`judul`) akan membuat index full-text pada kolom judul dengan nama index 336 BAB 19 FULL TEXT Search



judul_fulltext, index tersebut hanya terdiri dari satu kolom, namun demikian, kita dapat membuat index full-text untuk beberapa kolom.



Jika kita ingin melakukan full-text search pada kolom judul saja atau kolom deskripsi saja, maka kita dapat membuat index pada masing masing kolom tersebut, namun jika kita ingin melakukan pencarian full-text pada kedua kolom tersebut secara bersamaan, kita harus membuat index yang terdiri dari kedua kolom tersebut, jika tidak, maka akan muncul error ketika menjalankan query full-text. Jika kita menerapkan ketiganya, maka kita akan memiliki tiga index, yaitu index untuk kolom judul, kolom deskripsi, dan kolom judul dan deskripsi. Setelah index full-text didefinisikan, MySQL akan otomatis mengelola index tersebut, ketika data ditambahkan, diubah, maupun dihapus, MySQL otomatis akan memperbarui data pada index. Untuk membuat index full-text pada tabel yang sudah ada, kita dapat menggunakan perintah ALTER, misal kita akan menambahkan index fulltext pada kolom (1) judul, (2) kolom deskripsi dan (3) kolom judul dan deskripsi yang ada pada tabel buku: (1) Menambahkan index full-text pada kolom judul: ALTER TABLE `buku` ADD FULLTEXT INDEX `judul_fulltext` (`judul`);



(2) Menambahkan index full-text pada kolom deskripsi mysql> ALTER TABLE `buku` ADD FULLTEXT INDEX `deskripsi_fulltext` (`deskripsi`); Query OK, 0 rows affected (1.48 sec)



(3) Menambahkan index full-text pada kolom judul dan deskripsi mysql> ALTER TABLE `buku` ADD FULLTEXT INDEX `judul_deskripsi_fulltext` (`judul`, `deskripsi`); Query OK, 0 rows affected (1.45 sec)



Cara lain menambahkan index adalah menggunakan statement CREATE INDEX Panduan Lengkap Query MySQL 337



CREATE FULLTEXT INDEX `judul_fulltext` ON `buku` (`judul`);



Jika ingin menghapus index full-text kita gunakan perintah DROP INDEX, misal: ALTER TABLE `buku` DROP INDEX `judul_fulltext`;



Penting diperhatikan bahwa karena MySQL akan memperbarui index ketika ada perubahan data, maka ketika kita memasukkan (impor) data dalam jumlah besar, agar proses tidak terlalu lama, sebaiknya dihapus dulu index tersebut baru kemudian dibuat lagi setelah impor data selesai.



19.3. Menjalankan Full-Text Search Full-text search dijalankan dengan menggunakan dua fungsi yaitu (1) fungsi MATCH(nama_kolom) yang digunakan untuk menentukan kolom mana yang akan kita cari datanya dan (2) fungsi AGAINTS(ekspresi) yang digunakan untuk mendefinisikan ekspresi. Format penulisannya adalah sebagai berikut: MATCH (col1,col2,...) AGAINST (ekspresi [modifier])



Terdapat tiga jenis mode pada full-text search, yaitu: 1. Natural Language Mode. Mode ini merupakan mode default, dimana full-text search akan mencari data sesuai dengan kata yang telah ditentukan. Model ini mirip seperti ketika kita melakukan pencarian dengan klausa LIKE 2. Boolean mode. Mode ini memungkinkan kita untuk mendefinisikan query yang kompleks, seperti menentukan kata apa yang ingin di cari sekaligus kata apa yang ingin dikecualikan dari pencarian, atau pencarian dengan kalimat tertentu yang sama persis. Mode ini dijalankan dengan menambahkan karakter modifier pada string pencarian. 338 BAB 19 FULL TEXT Search



3. Query expansion search. Ketika mode ini dijalankan, MySQL sekaligus menjalankan dua proses, yaitu: (1) Menjalankan natural language mode, (2) hasil dari proses pertama yang memiliki relevansi paling tinggi akan digunakan lagi untuk melakukan pencarian data. Ketika menjalankan full-text search, terdapat beberapa hal yang perlu diperhatikan: 



Terdapat kata-kata tertentu yang akan diabaikan ketika melakukan pencarian, kata-kata tersebut disebut stopwords. Beberapa kata yang termasuk stopwords adalah the, because, after, dll. Daftar stopwords ini dapat dilihat di website MySQL: https://dev.mysql.com/doc/refman/5.7/en/fulltext-stopwords.html







Kata yang pendek (kurang dari 4 karakter) akan diabaikan, kita dapat menentukan jumlah minimum karakter tersebutdengan mendefinisikan opsi ft_min_word_len sebagai berikut: [mysqld] ft_min_word_len = 3



Ketika mengubah pengaturan, kita harus meng-index ulang semua tabel yang memiliki index full-text, proses ini dapat dilakukan dengan menghapus index full-text kemudian membuatnya lagi, atau menjalankan statemen repair table: REPAIR TABLE nama_tabel QUICK;







Pencarian akan dilakukan pada kata yang mengandung huruf, angka, apostrophes (' ), dan underscores ( _ ). Misal, pada kriteria pencarian "php-mysql" atau "php mysql", maka full-text akan melakukan pencarian pada kata php dan mysql, bukan pada kata php-mysql, hal ini karena tanda spasi dan dash (-) tidak masuk dalam kriteria pencarian full-text yang telah disebutkan tadi. Pada Boolean mode, kita dapat mengatur agar full-text melakukan pencarian pada semua karakter yang ada pada string pencarian, termasuk karakter spasi dan dash. Panduan Lengkap Query MySQL 339



19.4. Natural Language Mode Selanjutnya, mari kita bahas mode yang pertama, yaitu Natural language mode. Karena mode ini merupakan mode default, maka pada bagian fungsi AGAINST(), kita tidak perlu mendefinisikan klausa IN. Misal kita mencari buku yang memiliki judul yang mengandung kata mysql, jalankan perintah berikut: 1. 2. 3. 4.



SELECT judul FROM buku WHERE MATCH(judul) AGAINST('mysql') LIMIT 3;



Jika kita ingin secara eksplisit mendefinisikan nama mode, kita dapat menambahkannya pada argumen fungsi AGAINST(): 1. 2. 3. 4.



SELECT judul FROM buku WHERE MATCH(judul) AGAINST('mysql IN NATURAL LANGUAGE MODE') LIMIT 3;



Jika query diatas dijalankan, maka hasil yang kita peroleh adalah sebagai berikut: +----------------------------------------------+ | judul | +----------------------------------------------+ | Pemrograman Database Menggunakan MySQL | | PHP dan MySQL Langkah Demi Langkah + CD | | MySQL Untuk Pemula | +----------------------------------------------+



Hasil tersebut akan sama ketika kita menggunakan operator LIKE 1. 2. 3. 4.



SELECT judul FROM buku WHERE judul LIKE '%mysql%' LIMIT 3;



Seperti telah disampaikan sebelumnya, bahwa full-text menggunakan score relevansi untuk mengurutkan data hasil pencarian, untuk melihat score tersebut, jalankan query berikut: 340 BAB 19 FULL TEXT Search



1. 2. 3. 4.



SELECT judul, MATCH(judul) AGAINST('mysql') AS score FROM buku WHERE MATCH(judul) AGAINST('mysql') LIMIT 3;



Hasil: +----------------------------------------------+--------------------+ | judul | score | +----------------------------------------------+--------------------+ | Pemrograman Database Menggunakan MySQL | 0.3184022605419159 | | PHP dan MySQL Langkah Demi Langkah + CD | 0.3184022605419159 | | MySQL Untuk Pemula | 0.3184022605419159 | +----------------------------------------------+--------------------+



Pada contoh diatas, terlihat bahwa score untuk tiap-tiap baris adalah sama, sehingga baris yang ditampilkan diurutkan apa adanya, sesuai urutan pada tabel database, hal ini yang membuat hasil pencarian dengan full-text sama dengan ketika menggunakan operator LIKE. Nilai score ini ditentukan oleh beberapa kriteria, diantaranya kecocokan data dengan kata dalam pencarian, banyaknya kata yang cocok, dll. Misal, kita cari judul buku yang mengandung kata PHP dan/atau MySQL, jalankan query berikut: 1. SELECT judul, MATCH(judul) AGAINST('php mysql') AS score 2. FROM buku 3. WHERE MATCH(judul) AGAINST('php mysql')



Hasil: +----------------------------------------------+---------------------+ | judul | score | +----------------------------------------------+---------------------+ | PHP dan MySQL Langkah Demi Langkah + CD | 0.7324336171150208 | | Pemrograman PHP Dan MySQL Untuk Pemula | 0.7324336171150208 | | Trik Kolaborasi ANDROID dengan PHP dan MySQL | 0.7324336171150208 | | Kumpulan Aplikasi PHP untuk Pemula | 0.41403135657310486 | | Framework PHP Yii 2 | 0.41403135657310486 | | Pemrograman Database Menggunakan MySQL | 0.3184022605419159 | | MySQL Untuk Pemula | 0.3184022605419159 | | Pemrograman Stored Procedure Pada MySQL + cd | 0.3184022605419159 | +----------------------------------------------+---------------------+



Pada contoh diatas, terlihat bahwa baris dengan score tertinggi akan ditempatkan di urutan paling atas, score tertinggi diperoleh baris yang Panduan Lengkap Query MySQL 341



mengandung kata PHP dan MySQL, peringkat selanjutnya diperoleh baris yang hanya mengandung kata PHP (kata yang ada di depan pada kriteria pencarian) dan yang terakhir adalah yang mengandung MySQL. Hasil ini berbeda jika kita menggunakan operator LIKE: 1. SELECT judul, MATCH(judul) AGAINST('php mysql') AS score 2. FROM buku 3. WHERE judul LIKE '%php%' OR judul LIKE '%mysql%';



Hasil: +----------------------------------------------+---------------------+ | judul | score | +----------------------------------------------+---------------------+ | Pemrograman Database Menggunakan MySQL | 0.3184022605419159 | | PHP dan MySQL Langkah Demi Langkah + CD | 0.7324336171150208 | | MySQL Untuk Pemula | 0.3184022605419159 | | Kumpulan Aplikasi PHP untuk Pemula | 0.41403135657310486 | | Pemrograman PHP Dan MySQL Untuk Pemula | 0.7324336171150208 | | Trik Kolaborasi ANDROID dengan PHP dan MySQL | 0.7324336171150208 | | Pemrograman Stored Procedure Pada MySQL + cd | 0.3184022605419159 | | Framework PHP Yii 2 | 0.41403135657310486 | +----------------------------------------------+---------------------+



Data diatas diurutkan apa adanya sesuai dengan urutan baris pada tabel dalam database. Jika data tidak memenuhi kriteria pada pencarian, maka akan memiliki score 0, misal: mysql> SELECT judul, MATCH(judul) AGAINST('php mysql') AS score FROM buku LIMIT 15; +----------------------------------------------+---------------------+ | judul | score | +----------------------------------------------+---------------------+ | Pemrograman Database Menggunakan MySQL | 0.3184022605419159 | | PHP dan MySQL Langkah Demi Langkah + CD | 0.7324336171150208 | | MySQL Untuk Pemula | 0.3184022605419159 | | Kumpulan Aplikasi PHP untuk Pemula | 0.41403135657310486 | | Pemrograman PHP Dan MySQL Untuk Pemula | 0.7324336171150208 | | Blogger untuk Pemula | 0 | | Ide Bisnis Bermodal Blog | 0 | | Jago Wordpress | 0 | | Desain Grafis dengan Powerpoint | 0 | | Otodidak Membuat Blog dengan Blogger | 0 |



342 BAB 19 FULL TEXT Search



| Buku Sakti Wordpress | 0 | | Database Systems + CD | 0 | | Trik Kolaborasi ANDROID dengan PHP dan MySQL | 0.7324336171150208 | | Cara Efektif Belajar Framework Laravel | 0 | | Pemrograman Stored Procedure Pada MySQL + cd | 0.3184022605419159 | +----------------------------------------------+---------------------+ 15 rows in set (0.00 sec)



19.5. Boolean Mode Mode kedua adalah Boolean mode. Untuk menggunakan mode ini, kita tambahkan klausa IN BOOLEAN MODE pada fungsi AGAINST(). Boolean mode memungkinkan kita untuk melakukan pencarian dengan kriteria yang kompleks, kriteria ini diterapkan dengan menggunakan operator tertentu. Operator + dan – Pada boolean mode, operator + digunakan untuk mencari data yang mengandung kata tertentu, sedangkan operator – digunakan untuk mengecualikan kata tertentu dari hasil pencarian, misal jalankan query berikut: 1. SELECT judul, deskripsi 2. FROM buku 3. WHERE MATCH(judul, deskripsi) AGAINST('+mysql -php' IN BOOLEAN MODE);



Hasil: judul Pemrograman Stored Procedure Pada MySQL + cd



deskripsi Kemampuan yang disediakan oleh MySQL berupa stored procedure, function dan trigger tidak mudah dipelajari dan digunakan oleh para pengembang program aplikasi berbasis MySQL. Buku ini akan membantu Anda bagaimana menggunakan stored program MySQL dengan benar.



Panduan Lengkap Query MySQL 343



Pemrograman Database Menggunakan MySQL



MySQL adalah database yang sangat populer. Buku ini dirancang sebagai referensi cepat untuk mencari solusi-solusi atau teknik-teknik untuk menjawab banyak pertanyaan spesifik ketika menggunakan MySQL.



MySQL Untuk Pemula



Buku ini membahas langkah demi langkah menggunakan MySQL, lengkap dengan contohcontoh scripting-nya.



Pada contoh diatas, full-text search akan mencari data pada tabel buku yang judul atau deskripsinya mengandung kata mysql, namun tidak mengandung kata php. Operator asterik ( * ) Pada Boolean mode, operator asterik digunakan untuk mencari semua karakter setelah kata tertentu, misal jalankan query berikut: 1. SELECT judul 2. FROM buku 3. WHERE MATCH(judul) AGAINST('blog*' IN BOOLEAN MODE);



Hasil: +--------------------------------------+ | judul | +--------------------------------------+ | Blogger untuk Pemula | | Ide Bisnis Bermodal Blog | | Otodidak Membuat Blog dengan Blogger | +--------------------------------------+



Pada contoh diatas, kita menggunakan operator asterik (*) untuk mencari semua karakter setelah kata blog, dengan demikian, kata blogger memenuhi kriteria pencarian. Operator asterik ini hanya bisa ditambahkan di akhir kata, full-text search akan mengabaikannya jika kita meletakkannya di depan kata, misal: *sql



344 BAB 19 FULL TEXT Search



Operator tanda kutip ganda ( " ) Pada boolean mode, operator tanda kutip ganda digunakan untuk mencari data yang mengandung karakter yang sama persis dengan yang ada di dalam tanda kutip ganda tersebut, misal, jalankan query berikut: 1. SELECT judul 2. FROM buku 3. WHERE MATCH(judul) AGAINST('"php dan mysql"' IN BOOLEAN MODE);



Hasil: +----------------------------------------------+ | judul | +----------------------------------------------+ | PHP dan MySQL Langkah Demi Langkah + CD | | Pemrograman PHP Dan MySQL Untuk Pemula | | Trik Kolaborasi ANDROID dengan PHP dan MySQL | +----------------------------------------------+



Pada contoh diatas, full-text akan mencari data yang mengandung kata "php dan mysql" Melalui berbagai contoh diatas, kita telah belajar bagaimana menggunakan operator pada full-text search. Daftar semua operator yang didukung oleh full-text search adalah sebagai berikut: Operator



Keterangan



+



Kata harus ada dalam hasil pencarian. Pada engine InnoDB, operator ini hanya bisa di letakkan di depan kata.



-



Hasil pencarian tidak mengandung kata tertentu. Pada engine InnoDB, operator ini hanya bisa di letakkan di depan kata.



(tanpa operator)



Pencarian dilakukan seperti pada mode natural language



>



Kata yang mengikuti operator ini memiliki score yang lebih tinggi dibanding kata yang lain.



Panduan Lengkap Query MySQL 345




SELECT * FROM penjualan_view; ERROR 1356 (HY000): View toko_buku.penjualan_view' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them



21.8. Mengubah Nama View dan Statemen SELECT Setelah view dibuat, kita dapat mengubah baik nama maupun statemen SELECT yang ada didalam view tersebut. Untuk mengubah hanya nama view, kita bisa menggunakan perintah RENAME TABLE. Seperti telah kita bahas sebelumnya bahwa MySQL memperlakukan view seperti layaknya tabel, sehingga kita bisa menggunakan statemen yang berlaku untuk tabel pada umumnya seperti RENAME TABLE. Misal pada view penjualan_view kita ubah namanya menjadi penjualan_retur, query yang kita jalankan: RENAME TABLE penjualan_view TO pelanggan_order



Setelah query diatas kita jalankan, kita tidak dapat lagi mengakses view penjualan_view (akan muncul pesan error bahwa tabel tidak ditemukan) SQL Error (1146): Table 'toko_buku.penjualan_view' doesn't exist Panduan Lengkap Query MySQL 373



Jika kita ingin mengubah query yang ada pada view, kita dapat menggunakan perintah ALTER VIEW. Perintah ini sama seperti ketika kita membuat view, dimana kita mendefinisikan nama view dan statemen SELECT. Bedanya, kita ubah perintah CREATE menjadi ALTER. Format umum ALTER VIEW adalah: ALTER VIEW nama_view AS statemen_select nama_view merupakan nama view yang akan diubah isinya, statemen_select merupakan query yang ingin kita terapkan pada view tersebut. Misal kita ubah query yang ada pada view pelanggan_order 1. ALTER 2. VIEW pelanggan_order 3. AS SELECT pelanggan.id_pelanggan, nama, id_trx, tgl_trx, total_trx 4. FROM penjualan 5. LEFT JOIN pelanggan USING(id_pelanggan)



Setelah query diatas dijalankan, maka ketika kita memanggil view pelanggan_order dengan perintah: SELECT * FROM pelanggan_order



Hasil yang kita peroleh: +--------------+---------+--------+------------+-----------+ | id_pelanggan | nama | id_trx | tgl_trx | total_trx | +--------------+---------+--------+------------+-----------+ | 3 | Charlie | 2 | 2017-03-22 | 395000 | | 2 | Braskie | 3 | 2017-01-10 | 360000 | | 1 | Anton | 4 | 2017-03-04 | 269000 | | 4 | Deni | 5 | 2017-02-15 | 110000 | | 3 | Charlie | 6 | 2017-03-07 | 256000 | | 2 | Braskie | 7 | 2017-03-05 | 215000 | | 3 | Charlie | 8 | 2016-12-12 | 270000 | | 3 | Charlie | 9 | 2016-12-12 | 325000 | +--------------+---------+--------+------------+-----------+



374 BAB 21 Views



21.9. Menghapus View Untuk menghapus view, kita dapat menggunakan statemen DROP. Misal kita ingin menghapus view pelanggan_order yang telah kita buat sebelumnya. Jalankan perintah berikut: mysql> DROP VIEW pelanggan_order; Query OK, 0 rows affected (0.06 sec)



Kita juga dapat menghapus beberapa view sekaligus dengan memberikan pemisah tanda koma pada tiap tiap nama view, misal kita akan menghapus view dengan nama penjualan_view dan pelanggan_order: mysql> DROP VIEW penjualan_view, pelanggan_order; Query OK, 0 rows affected (0.06 sec)



Jika view tidak ditemukan, maka akan muncul pesan error yang menandakan bahwa tabel (view) tidak ditemukan. Misal kita akan menghapus view pelanggan_retur dan pelanggan_order, dimana view pelanggan_retur sebenarnya tidak ada. mysql> DROP VIEW penjualan_retur, pelanggan_order; ERROR 1051 (42S02): Unknown table 'toko_buku. pelanggan_retur '



Pada contoh diatas, view pelanggan_order berhasil dihapus, sedangkan view penjualan_retur tidak dapat dihapus karena tidak ditemukan. Kita dapat menggunakan klausa IF EXISTS untuk menguji terlebih dahulu apakah view yang ingin kita hapus ada, jika tidak ada, MySQL akan menghasilkan pesan warning bukan error. Misal: mysql> DROP VIEW IF EXISTS pelanggan_retur, pelanggan_order; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> SHOW WARNINGS; +-------+------+-----------------------------------------------+ | Level | Code | Message |



Panduan Lengkap Query MySQL 375



+-------+------+-----------------------------------------------+ | Note | 1051 | Unknown table 'toko_buku.pelanggan_retur' | +-------+------+-----------------------------------------------+ 1 row in set (0.00 sec)



Pada contoh diatas, MySQL memunculkan pesan peringatan bahwa tabel pelanggan_retur tidak ditemukan. Perbedaan ERROR dan WARNING adalah, jika error, maka script akan berhenti, proses eksekusi tidak diteruskan ke script berikutnya, jika warning, maka proses eksekusi akan tetap diteruskan ke script berikutnnya.



21.10. Menampilkan Struktur View Pada kondisi tertentu kita ingin mengetahui semua view yang telah kita buat. Untuk keperluan tersebut, kita dapat menggunakan perintah SHOW FULL TABLES sebagai berikut: 1. SHOW FULL TABLES 2. WHERE table_type = 'view';



Hasil: +---------------------+------------+ | Tables_in_toko_buku | Table_type | +---------------------+------------+ | pelanggan_order | VIEW | +---------------------+------------+



Tabel terdiri dari dua jenis/tipe yaitu BASE TABLE dan VIEW. Pada query diatas, penulis menambahkan WHERE table_type = 'view' untuk menampilkan tabel yang berjenis VIEW. Terkadang kita juga ingin mengetahui query apa yang ada pada suatu view. Untuk keperluan tersebut, kita dapat menggunakan perintah SHOW CREATE VIEW. Misal kita ingin menampilkan view pelanggan_order



376 BAB 21 Views



1. SET sql_mode = 'ANSI'; 2. SHOW CREATE VIEW pelanggan_order\G;



Hasil yang kita peroleh: *************************** 1. row *************************** View: pelanggan_order Create View: CREATE VIEW "pelanggan_order" AS select "pelanggan"."id_pelanggan" AS "id_pelanggan","pelanggan"."nama" AS "nama","penjualan"."id_trx" AS "id_trx","penjualan"."tgl_trx" AS "tgl_trx","penjualan"."total_trx" AS "total_trx" from ("penjualan" left join "pelanggan" on(("penjualan"."id_pelanggan" = "pelanggan"."id_pelanggan"))) character_set_client: utf8mb4 collation_connection: utf8mb4_general_ci 1 row in set (0.00 sec)



Perhatikan bahwa pada query diatas, penulis mengubah sql_mode menjadi ANSI sehingga dapat menampilkan data menggunakan opsi \G dimana tampilan tabel hasil query menjadi lebih mudah dibaca. Disamping itu, kita juga dapat melihat struktur dari view melalui database information_schema dengan query sebagai berikut: 1. SELECT VIEW_DEFINITION 2. FROM INFORMATION_SCHEMA.VIEWS 3. WHERE TABLE_SCHEMA = 'toko_buku' AND TABLE_NAME = 'pelanggan_order';



Hasil: select `toko_buku`.`pelanggan`.`id_pelanggan` AS `id_pelanggan`,`toko_buku`.`pelanggan`.`nama` AS `nama`,`toko_buku`.`penjualan`.`id_trx` AS `id_trx`,`toko_buku`.`penjualan`.`tgl_trx` AS `tgl_trx`,`toko_buku`.`penjualan`.`total_trx` AS `total_trx` from (`toko_buku`.`penjualan` left join



Panduan Lengkap Query MySQL 377



`toko_buku`.`pelanggan` on((`toko_buku`.`penjualan`.`id_pelanggan` = `toko_buku`.`pelanggan`.`id_pelanggan`)))



Pada query diatas, TABLE_SCHEMA adalah nama database sedangkan TABLE_NAME adalah nama dari view. Tabel views pada database information_schema memiliki informasi detail tentang view, Anda dapat melihat info lebih jauh tentang view dengan menjalankan perintah SELECT * FROM INFORMATION_SCHEMA.VIEWS



21.11. Updatable dan Insertable View Selain mengubah nama dan query pada view, kita juga dapat mengubah data pada view seperti pada tabel riil yaitu menggunakan statemen INSERT, UPDATE, dan DELETE. Meski melalui view, data yang berubah tetap data pada base table. Mengubah data melalui view tidaklah mudah, terdapat berbagai syarat yang harus dipenuhi, yang terpenting adalah hubungan antara baris pada tabel view dengan baris pada base table harus satu ke satu (one to one relationship). Beberapa kondisi berikut membuat data pada view tidak updateable: 1. Statemen SELECT mengandung fungsi agregat (seperti SUM, AVG, COUNT, dll), 2. Terdapat klausa DISTINCT, GROUP BY, HAVING, UNION, UNION ALL 3. Mengandung subquery (pada kondisi tertentu) 4. Mengandung JOIN 5. Klausa FROM mengandung view yang tidak updateable atau terdiri dari dua atau lebih tabel. 6. Subquery pada klausa WHERE mengandung referensi pada tabel yang ada pada klausa FROM 7. Hanya merujuk pada nilai literal. 8. View menggunakan algoritma (ALGORITHM) TEMPTABLE 378 BAB 21 Views



Misal kita buat view dengan nama penjualan_maret yang akan menampilkan data penjualan selama bulan Maret; 1. CREATE 2. VIEW penjualan_maret 3. AS SELECT id_trx, 4. id_pelanggan, 5. tgl_trx, 6. total_trx 7. FROM penjualan 8. WHERE MONTH(tgl_trx) = 3



Jika kita jalankan query SELECT * FROM penjualan_maret



Hasil yang kita peroleh; +--------+--------------+------------+-----------+ | id_trx | id_pelanggan | tgl_trx | total_trx | +--------+--------------+------------+-----------+ | 2 | 3 | 2017-03-22 | 395000 | | 4 | 1 | 2017-03-04 | 269000 | | 6 | 3 | 2017-03-07 | 256000 | | 7 | 2 | 2017-03-05 | 215000 | +--------+--------------+------------+-----------+



Selanjutnya, pada data dengan id_trx 2, kita ubah tanggal transaksinya menjadi 2017-02-22, query yang kita jalankan: mysql> UPDATE penjualan_maret -> SET tgl_trx = '2017-02-22' -> WHERE id_trx = 2; Query OK, 1 row affected (0.18 sec) Rows matched: 1 Changed: 1 Warnings: 0



Seperti yang telah kita bahas sebelumnya, bahwa perubahan data pada view sejatinya adalah perubahan data pada base table. Untuk itu, mari kita cek data pada tabel penjualan, jalankan perintah berikut: SELECT * FROM penjualan WHERE id_trx = 2



Panduan Lengkap Query MySQL 379



Hasil yang kita peroleh: +--------+--------------+------------+-----------+ | id_trx | id_pelanggan | tgl_trx | total_trx | +--------+--------------+------------+-----------+ | 2 | 3 | 2017-02-22 | 395000 | +--------+--------------+------------+-----------+



Dari tabel diatas terlihat bahwa pada tabel penjualan, data dengan id_trx 2, tgl_trx nya berubah menjadi 2017-02-22. Selain UPDATE, Anda dapat mencoba statemen INSERT atau DELETE untuk mengubah data pada view penjualan_maret. Selanjutnya, mari kita cek data pada view, kita jalankan kembali perintah SELECT * FROM penjualan_maret, hasil yang kita peroleh: +--------+--------------+------------+-----------+ | id_trx | id_pelanggan | tgl_trx | total_trx | +--------+--------------+------------+-----------+ | 4 | 1 | 2017-03-04 | 269000 | | 6 | 3 | 2017-03-07 | 256000 | | 7 | 2 | 2017-03-05 | 215000 | +--------+--------------+------------+-----------+



Dari data tersebut, terlihat bahwa data dengan id_trx 2 sudah tidak ada karena tidak termasuk transaksi bulan Maret. Pada kondisi tertentu, kita tidak ingin hal tersebut terjadi, untuk itu, kita dapat mencegahnya dengan menggunakan klausa WITH CHECK OPTION. Dengan klausa WITH CHECK OPTION, ketika terjadi perubahan data, maka akan dilakukan pengecekan apakah data tersebut memenuhi kriteria pada klausa WHERE yang ada pada statemen SELECT yang ada pada view, jika tidak memenuhi, maka akan muncul pesan error. Disamping itu juga dilakukan pengecekan apakah setelah dilakukan perubahan, data tersebut akan hilang pada tabel view, jika ya maka akan muncul pesan error. Misal, pada view penjualan_maret, kita tambahkan klausa WITH CHECK OPTION, jalankan query berikut:



380 BAB 21 Views



1. ALTER 2. VIEW penjualan_maret 3. AS SELECT id_trx, 4. id_pelanggan, 5. tgl_trx, 6. total_trx 7. FROM penjualan 8. WHERE MONTH(tgl_trx) = 3 9. WITH CHECK OPTION



Selanjutnya, pada data dengan id_trx 2 , kita ubah tgl_trx nya menjadi 201702-22, jalankan query berikut: 1. UPDATE penjualan_maret 2. SET tgl_trx = '2017-02-22' 3. WHERE id_trx = 2



Ketika menjalankan query tersebut, kita akan memperoleh pesan error SQL Error (1369): CHECK OPTION failed 'toko_buku.penjualan_maret', hal tersebut dikarenakan tgl_trx yang baru tidak memenuhi kriteria WHERE MONTH(tgl_trx) = 3. Klausa WITH CHECK OPTION sendiri memiliki dua opsi yaitu CASCADED dan LOCAL. Jika kita tidak mendefinisikan opsi, maka MySQL otomatis akan menggunakan opsi CASCADED. Seperti yang telah kita bahas sebelumnya, view dapat dibuat berdasarkan view lain, dengan opsi CASCADE, MySQL akan mengecek apakah perubahan data tersebut sesuai dengan kriteria yang ada pada view yang sedang dijalankan maupun view yang menjadi tabel referensi. Misal kita buat view lagi dengan nama penjualan_maret_kecil yang berisi data pada view penjualan_maret dengan nilai dibawah 300.000, query yang kita jalankan:



Panduan Lengkap Query MySQL 381



1. CREATE 2. VIEW penjualan_maret_kecil 3. AS SELECT id_trx, 4. id_pelanggan, 5. tgl_trx, 6. total_trx 7. FROM penjualan_maret 8. WHERE total_trx < 300000 9. WITH CASCADED CHECK OPTION



Pada query diatas kita tambahkan klausa WITH CASCADED CHECK OPTION yang sebenarnya juga bisa ditulis tanpa cascaded. Kita tambahkan CASCADED untuk memperjelas jenis CHECK OPTION nya. Pada kondisi diatas, ketika terjadi perubahan data, maka perubahan tersebut harus memenuhi kriteria CHECK OPTION pada view penjualan_maret dan penjualan_maret_kecil, dimana bulan transaksi nya harus Maret dan nilai transaksinya harus dibawah 300.000. Misal data view penjualan_maret_kecil adalah sebagai berikut: mysql> SELECT * FROM penjualan_maret_kecil; +--------+--------------+------------+-----------+ | id_trx | id_pelanggan | tgl_trx | total_trx | +--------+--------------+------------+-----------+ | 4 | 1 | 2017-03-04 | 269000 | | 6 | 3 | 2017-03-07 | 256000 | | 7 | 2 | 2017-03-05 | 215000 | +--------+--------------+------------+-----------+ 3 rows in set (0.00 sec)



selanjutnya data dengan id_trx 4 kita ubah tgl_trx nya menjadi 2017-02-22, query yang kita jalankan: 1. UPDATE penjualan_maret_kecil 2. SET tgl_trx = '2017-02-22' 3. WHERE id_trx = 4



Ketika query tersebut dijalankan, kita akan mendapati pesan error: SQL Error (1369): CHECK OPTION failed 382 BAB 21 Views



'toko_buku.penjualan_maret_kecil', karena tidak memenuhi kriteria pada klausa WHERE yang ada pada view penjualan_maret.



Opsi kedua dari WITH CHECK OPTION ini adalah LOCAL, dengan opsi LOCAL, MySQL hanya akan mengecek kriteria pada klausa WHERE yang ada pada view yang sedang berjalan, dan tidak mengecek pada view yang digunakan sebagai referensi. Misal, pada view penjualan_maret_kecil, kita ubah check option menjadi local ( WITH LOCAL CHECK OPTION ). Selanjutnya jika kita jalankan query update diatas, maka MySQL akan mengeksekusinya (melakukan update data), karena MySQL hanya akan mengecek kriteria pada klausa WHERE yang ada pada view penjualan_maret_kecil. Dengan WITH CHECK OPTION kita akan mengetahui apakah suatu view updateable atau tidak, yang berarti view tersebut dapat diupdate secara aman, namun demikian view yang tidak memenuhi kriteria updateable juga dapat kita ubah datanya, namun tidak ada jaminan adanya integritas data.



Panduan Lengkap Query MySQL 383



Halaman ini sengaja dikosongkan Jagowebdev.com



384 BAB 21 Views



BAB 22 Stored Procedures MySQL mengenal istilah yang disebut Stored Routines (SR). Stored Routines adalah sekumpulan statemen SQL yang memiliki nama tertentu yang disimpan di server, sehingga ketika client ingin menjalankan statemen SQL tersebut, client hanya perlu memanggil nama Sored Routines. Stored Routines terdiri dari dua yaitu Stored Procedure dan Stored Function. Pada BAB ini, kita akan membahas tentang Stored Procedure, sedangkan Stored Function akan kita bahas pada BAB berikutnya. Stored Procedure atau yang disingkat SP adalah sekumpulan perintah SQL (procedure) yang dapat di jalankan sekaligus yang tersimpan (stored) pada server database. Perlu diperhatikan bahwa server database berbeda dengan web server. Pada bab sebelumnya kita telah membahas view. Mungkin Anda bertanya apa beda view dengan SP? Bedanya, view merupakan sebuah tabel virtual dimana kita dapat menggunakannya pada statemen lain, seperti statemen SELECT, sedangkan SP merupakan statemen tersendiri yang langsung menghasilkan output yang berdiri sendiri, sehingga tidak bisa digunakan bersama dengan statemen lain. Namun demikian, keduanya terdapat persamaan yaitu pembatasan hak akses, dimana user tidak bisa langsung mengakses data / tabel yang digunakan pada statemen view maupun SP. Stored Procedure memiliki banyak manfaat yang semuanya dapat dirangkum dalam tiga kata: simplicity – security – performance. Adapun penjelasan detailnya adalah sebagai berikut: 



Menyederhanakan query yang kompleks dengan menyimpan query tersebut di dalam SP, selanjutnya kita cukup memanggilnya dengan perintah CALL. Panduan Lengkap Query MySQL 385







Menjaga integritas data. Jika banyak statement dijalankan, misal UPDATE dan DELETE maka dengan menjalankan query satu per satu secara terpisah, akan berpotensi menimbulkan kesalahan. Dengan mengumpulkannya menjadi satu maka potensi kesalahan tersebut dapat diminimalisir.







Meminimalisir perubahan. Jika tabel pada database berubah, kita hanya perlu mengubah stored procedure, tidak perlu mengubah query yang kita tulis di berbagai tempat pada aplikasi kita.







Eksekusi lebih cepat karena query disimpan dalam database. Dengan SP, pengiriman perintah client ke server berkurang karena cukup mengirim perintah CALL. Hal ini berbeda jika client mengirim query yang sama berulang ulang dimana query akan di baca (parsing) oleh database driver, dianalisa, dan dioptimasi setiap kali query dijalankan.







Mengurangi trafik antara client dan server. Misal kita akan mengeksekusi 5 perintah SQL, normalnya, client akan mengirim kelima perintah tersebut ke server, dengan SP client hanya perlu mengirim satu perintah saja.







Hanya perlu di tulis sekali dan dapat dijalankan dimana saja, tanpa perlu menulis ulang kode SQL, yang bisa jadi kode tersebut kompleks.







Membatasi hak akses user. Misal kita memiliki beberapa tabel dan kita tidak ingin user mengakses tabel tersebut, dengan SP kita dapat menyamarkan tabel tersebut dan cukup memberi hak akses EXECUTE (untuk memanggil SP) kepada user dan tidak memberi hak akses ke tabel.







Keamanan. Dengan membatasi hak akses user, keamanan data akan tetap terjaga, karena user tidak dapat mengubah (insert atau update) data maupun menghapus tabel. Disamping itu, karena disimpan pada server database, jika sesuatu terjadi pada web server, maka query masih aman, karena disimpan di tempat yang terpisah.



Meski demikian, Stored Procedure juga memiliki beberapa kekurangan, yaitu: 386 BAB 22 Stored Procedures







Meningkatnya load database karena semua dikerjakan di server, dan sedikit yang dikerjakan di client (aplikasi)







Lerning curve. Karena penulisan SP cukup kompleks, maka memerlukan pemahaman dan pengalaman yang cukup pada syntax SQL







Beban server CPU. Jika kita banyak menggunakan ekspresi logika pada SP, maka beban server untuk memproses SP tersebut akan bertambah, karena SQL merupakan bahasa deklaratif, sehingga kurang maksimal ketika memproses ekspresi logika



22.1. Membuat Stored Procedure Untuk membuat SP, kita mulai dengan statemen CREATE PROCEDURE dan diakhiri dengan END, format penulisannya adalah sebagai berikut: 1. 2. 3. 4. 5. 6.



DELIMITER $ CREATE PROCEDURE penjualan() BEGIN SELECT * FROM penjualan; END $ DELIMITER ;



Penting diperhatikan bahwa ketika membuat SP, kita harus menentukan delimiter. Delimiter adalah karakter yang digunakan sebagai akhir dari statement. Karakter default delimiter adalah titik koma ( ; ). Karena query pada SP menggunakan delimiter titik koma, maka jika kita tidak mengubah delimiter, statemen akan berhenti pada baris 4, karena MySQL menemukan tanda titik koma, sehingga akan muncul error. Agar MySQL dapat membaca dengan utuh statemen dari CREATE PROCEDURE hingga END, maka kita harus mengubah karakter delimiter. Pada contoh diatas, dengan statemen DELIMITER $, kita ubah delimiter menjadi tanda dollar. Setelah END kita tambahkan tanda $ untuk menandakan akhir dari statemen SP, selanjutnya dengan perintah DELIMITER ; kita kembalikan delimiter menjadi titik koma Panduan Lengkap Query MySQL 387



Perlu diperhatikan bahwa ketika kita membuat SP, query yang ada di dalam SP tidak langsung dieksekusi, MySQL hanya mendefinisikan SP dan menyimpannya pada database, sehingga dapat dieksekusi kemudian. Sebagai tambahan, sebelum membuat SP, kita bisa tambahkan statemen DROP yang akan menghapus SP dengan nama yang sama, hal ini bertujuan agar ketika membuat SP, tidak muncul pesan eror yang disebabkan adanya SP dengan nama yang sama, misal: 1. 2. 3. 4. 5. 6. 7.



DELIMITER $ DROP PROCEDURE IF EXISTS penjualan_all $ CREATE PROCEDURE penjualan_all() BEGIN SELECT * FROM penjualan; END $ DELIMITER ;



Perhatikan bahwa pada contoh diatas, pada baris 2 kita gunakan tanda $ sebagai akhir dari statemen DROP PROCEDURE



22.2. Membuat Stored Procedure Dengan Parameter Pada bab awal kita telah membahas bagaimana menampilkan data menggunakan statemen SELECT, statemen tersebut bersifat statis, artinya output yang dihasilkan tidak berubah. Dengan SP, kita dapat menambahkan parameter pada statemen SELECT, sehingga hasil yang kita peroleh berubah ubah sesuai nilai parameter yang dimasukkan. Parameter pada SP ini mirip dengan argumen pada fungsi yang digunakan oleh bahasa pemrograman pada umumnya, seperti PHP. Parameter ini berupa suatu nilai yang diisikan ketika kita memanggil SP, selanjutnya nilai tersebut dapat digunakan oleh statemen yang ada di dalam SP. Melanjutkan contoh sebelumnya, misal kita ingin menampilkan data penjualan spesifik untuk bulan tertentu. Kali ini kita tidak menuliskan bulan tersebut langsung pada statemen SELECT, melainkan kita jadikan 388 BAB 22 Stored Procedures



bulan tersebut sebagai parameter, sehingga data yang dihasilkan dapat berubah ubah sesuai dengan nilai bulan yang diisikan. Bentuk statemen SELECT nya akan seperti ini: 1. SELECT * 2. FROM penjualan 3. WHERE MONTH(tgl_trx) = parameter



Jika di buat dalam SP, maka query yang kita jalankan: 1. 2. 3. 4. 5. 6. 7. 8. 9.



DELIMITER $ DROP PROCEDURE IF EXISTS penjualan $ CREATE PROCEDURE penjualan (month INT) BEGIN SELECT * FROM penjualan WHERE MONTH(tgl_trx) = month; END $ DELIMITER ;



Perhatikan bahwa pada baris ke dua, kita tambahkan parameter pada procedure. Pada contoh diatas, penulis memberi nama parameter dengan nama month (Anda bebas memberi nama lain), selanjutnya kita tambahkan INT untuk menandakan bahwa parameter tersebut memiliki tipe data integer. Perlu dicatat bahwa jenis tipe data ini harus kita isikan, jika tidak, maka SP tidak akan bisa dibuat. Pada tipe data tertentu, kita harus mendefinisikan panjang data. Pada contoh diatas, kita boleh tidak menuliskan panjang data pada tipe data IN, karena MySQL akan otomatis memberi nilai 11 (panjang data maksimal). Untuk tipe data lain seperti character, maka kita harus mendefinisikan panjang datanya, misal VARCHAR(255) atau CHAR(50) Perlu diperhatikan juga bahwa pada SP terdapat tiga jenis parameter yaitu IN, OUT, dan INOUT. Pada contoh diatas, kita gunakan parameter berjenis IN, dimana ketika memanggil SP, kita memberikan (memasukkan) Panduan Lengkap Query MySQL 389



paramerter. Pada parameter berjenis OUT, maka ketika kita memanggil SP, kita akan mendapatkan nilai keluaran dari SP tersebut. Penting diperhatikan bahwa tidak seperti statemen fungsi pada bahasa pemrograman komputer, kita tidak dapat mendefinisikan nilai default pada parameter / argumen. SP dapat berisi lebih dari satu parameter, penulisan antar parameter dipisahkan dengan koma, misal kita buat SP yang akan mengambil data sales berdasarkan bulan transaksi dan nama: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.



DELIMITER $ DROP PROCEDURE IF EXISTS penjualan $ CREATE PROCEDURE penjualan ( bulan INT, nama_pelanggan VARCHAR(255) ) BEGIN SELECT id_pelanggan, nama, tgl_trx, total_trx FROM penjualan LEFT JOIN pelanggan USING (id_pelanggan) WHERE MONTH(tgl_trx) = bulan AND nama = nama_pelanggan; END $ DELIMITER ;



Perlu diperhatikan bahwa kita juga tidak boleh memberi nama parameter sama dengan nama kolom pada tabel yang digunakan pada SP, misal pada contoh diatas, parameter kedua penulis beri nama nama_pelanggan bukan nama saja, karena akan sama dengan kolom nama yang ada pada tabel pelanggan.



22.3. Memanggil Stored Procedure Untuk memanggil Stored Procedure yang telah kita buat, kita gunakan statemen CALL nama_sp atau dengan tanda kurung CALL nama_sp(), jika SP memiliki parameter, maka parameter wajib untuk diisikan, sehingga menjadi CALL nama_sp(parameter)



390 BAB 22 Stored Procedures



Misal, pada bagian sebelumnya kita telah membuat SP bernama penjualan_all, karena tanpa parameter, kita dapat memanggilnya dengan: CALL penjualan_all



atau CALL penjualan_all()



Sedangkan pada sp yang kedua, yaitu penjualan, karena sp tersebut memiliki parameter, maka kita harus mengisikan nilai parameter tersebut; CALL penjualan(3, 'Charlie')



Jika kita tidak mengisikan nilai parameter, maka akan muncul pesan error. Perhatikan bahwa tipe data parameter pertama SP penjualan adalah integer (INT), pada contoh diatas, kita isikan nilai 3 (integer – tipe data sesuai), namun demikian kita dapat mengisikan nilai dengan tipe data lain, misal string seperti pada contoh berikut: CALL penjualan('3', 'Charlie')



Hal ini dikarenakan MySQL akan melakukan type casting yang akan mengubah nilai inputan string menjadi integer. Ketika memanggil SP, kita juga dapat menyertakan nama database, misal CALL toko_buku.penjualan(3, 'Charlie'), hal ini kita lakukan jika SP yang kita panggil tidak berada di dalam default database yang sedang kita gunakan Selanjutnya, jika SP penjualan kita jalankan, hasil yang kita peroleh adalah: mysql> CALL penjualan(3, 'Charlie'); +--------------+---------+------------+-----------+ | id_pelanggan | nama | tgl_trx | total_trx | +--------------+---------+------------+-----------+ | 3 | Charlie | 2017-03-22 | 395000 |



Panduan Lengkap Query MySQL 391



| 3 | Charlie | 2017-03-07 | 256000 | +--------------+---------+------------+-----------+ 2 rows in set (0.02 sec)



22.4. Stored Procedure dengan Parameter IN, OUT, dan INOUT Sejauh ini kita telah berhasil membuat stored procedure dengan parameter. Seperti yang telah kita bahas sebelumnya, terdapat 3 jenis parameter pada stored procedure yaitu IN, OUT, dan INOUT: Parameter IN. Dengan tambahan parameter ini, berarti nilai parameter akan dimasukkan ( IN ) sehingga dapat digunakan oleh statemen dalam Stored Procedure. Mode ini merupakan mode default, sehingga, jika tidak didefinisikan maka akan dianggap menggunakan mode IN, misal pada contoh sebelumnya, kita membuat SP tanpa mendefinisikan mode CREATE PROCEDURE penjualan (bulan INT) jika ditulis menggunakan IN, maka statemen tersebut menjadi: CREATE PROCEDURE penjualan (IN bulan INT) Parameter OUT. Parameter ini akan mengembalikan nilai dari stored procedure ke statemen pemanggil (statemen CALL). Contoh kita buat SP dengan nama penjualan_total yang akan menghasilkan nilai total penjualan dari tabel penjualan berdasarkan bulan tertentu, query yang kita jalankan adalah: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.



DELIMITER $ DROP PROCEDURE IF EXISTS penjualan_total $ CREATE PROCEDURE penjualan_total( bulan INT, OUT total INT BEGIN SELECT SUM(total_trx) INTO total FROM penjualan WHERE MONTH(tgl_trx) = bulan; END $ DELIMITER ;



392 BAB 22 Stored Procedures



Pada contoh diatas, kita tambahkan keyword OUT pada parameter total. Selanjutnya, dengan statemen SELECT...INTO kita masukkan hasil dari query ke dalam variabel total. Seperti telah kita bahas pada bab sebelumnya, kita dapat memberi nilai pada variabel menggunakan SELECT...INTO atau statemen SET. Mari kita coba jalankan stored procedure tersebut: mysql> CALL penjualan_total(3, @total_penjualan); Query OK, 1 row affected (0.00 sec)



Pada query diatas, kita simpan hasil dari stored procedure ke dalam variabel @total_penjualan. Selanjutnya ketika kita tampilkan data variabel @total_penjualan maka akan berisi nilai total transaksi bulan 2 yaitu sebesar 1.135.000 mysql> SELECT @total_penjualan; +------------------+ | @total_penjualan | +------------------+ | 1135000 | +------------------+ 1 row in set (0.00 sec)



Pada SP, kita juga dapat menghasilkan nilai output lebih dari satu, misal, melanjutkan contoh sebelumnya, kita ubah stored procedure penjualan_total sehingga menghasilkan output nilai total penjualan dan total jumlah transaksinya, query yang kita jalankan: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.



DELIMITER $ DROP PROCEDURE IF EXISTS penjualan_total_jumlah $ CREATE PROCEDURE penjualan_total_jumlah ( bulan INT, OUT total INT, OUT jml_trx INT ) BEGIN -- total SELECT SUM(nilai_trx) INTO total FROM penjualan



Panduan Lengkap Query MySQL 393



13. WHERE MONTH(tgl_trx) = bulan; 14. 15. -- jumlah transaksi 16. SELECT COUNT(nilai_trx) 17. INTO jml_trx 18. FROM penjualan 19. WHERE MONTH(tgl_trx) = bulan; 20. END $ 21. DELIMITER ;



Pada contoh diatas, kita membuat dua statemen SELECT untuk memasukkan nilai ke parameter total dan jml_trx. Karena kedua statemen tersebut hampir sama, maka kita dapat menggabungkan keduanya menjadi satu: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.



DELIMITER $ DROP PROCEDURE IF EXISTS penjualan_total $ CREATE PROCEDURE penjualan_total ( bulan INT, OUT total INT, OUT jml_trx INT ) BEGIN SELECT SUM(total_trx), COUNT(id_trx) INTO total, jml_trx FROM penjualan WHERE MONTH(tgl_trx) = bulan; END $ DELIMITER ;



Selanjutnya mari kita panggil SP tersebut. mysql> CALL penjualan_total (3, @total, @jumlah); Query OK, 1 row affected (0.00 sec) mysql> SELECT @total, @jumlah; +---------+---------+ | @total | @jumlah | +---------+---------+ | 1135000 | 4 | +---------+---------+ 1 row in set (0.00 sec)



394 BAB 22 Stored Procedures



Parameter INOUT. Parameter ini merupakan gabungan dari parameter IN dan OUT yang artinya satu parameter akan sekaligus sebagai masukan dan sebagai keluaran, misal: kita buat stored procedure dengan nama penjualan_akumulatif: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.



DELIMITER $ DROP PROCEDURE IF EXISTS penjualan_akumulatif $ CREATE PROCEDURE penjualan_akumulatif ( INOUT total INT, OUT total_asli INT ) BEGIN SET total_asli = ( SELECT SUM(total) FROM penjualan ); SET total = total + total_asli; END $ DELIMITER ;



Pada contoh diatas, penulis menggunakan statemen SET untuk menyimpan nilai pada variabel total dan total_asli, pada baris 11, inputan dari statemen CALL akan dijumlahkan dengan variabel total_asli yang diperoleh dari query database, hasilnya akan dikembalikan ke variabel total. Contoh penggunaan SP tersebut adalah sebagai berikut: mysql> SET @total_akumulatif = 1000000; Query OK, 0 rows affected (0.00 sec) mysql> CALL penjualan_akumulatif(@total_akumulatif, @total_asli); Query OK, 0 rows affected (0.06 sec) mysql> SELECT @total_akumulatif, @total_asli; +-------------------+-------------+ | @total_akumulatif | @total_asli | +-------------------+-------------+ | 9000000 | 8000000 | +-------------------+-------------+ 1 row in set (0.00 sec)



Pada contoh diatas, dengan statemen SET kita definisikan variabel @total_akumulatif sebesar 100000, selanjutnya ketika kita memanggil SP penjualan_akumulatif, maka hasil SP, yaitu 8000000 akan disimpan Panduan Lengkap Query MySQL 395



pada variabel @total_asli, kemudian nilai tersebut akan dijumlahkan dengan nilai variabel @total_akumulatif, sehingga nilai variabel @total_akumulatif menjadi 9000000.



22.5. Stored Procedure Dengan Variabel Pada stored procedure, kita dapat menggunakan variabel. Pada BAB 20, kita telah membahas tentang user variabel. Pada SP, selain user variabel, kita juga dapat menggunakan local variable. Perbedaannya, user variabel bersifat global dan dapat digunakan untuk keseluruhan sesi (didalam maupun diluar SP), sedangkan untuk local variable, kita hanya dapat menggunakannya pada area (scope) tertentu, yaitu antara klausa BEGIN dan END. Untuk mendefinisikan local variable, kita gunakan statemen DECLARE yang diikuti dengan nama variabel. Misal: 1. DECLARE nama_variabel1 INT(4); 2. DECLARE nama_variabel2 INT(4); 3. DECLARE nama_variabel3 VARCHAR(5);



Catatan: penamaan variabel harus mengikuti aturan penulisan nama kolom. Setelah mendefinisikan nama variabel, kita harus mendefinisikan tipe data dan panjang data (wajib untuk tipe data tertentu seperti CHAR dan VARCHAR). Untuk tipe data yang sama, kita dapat menggabungkannya dalam satu deklarasi, misal: DECLARE nama_variabel1, nama_variabel2 INT;



Pada deklarasi diatas, semua variabel yang kita deklarasikan memiliki nilai awal NULL, kita dapat mengubah nilai awal tersebut (nilai default) dengan menambahkan klausa DEFAULT, misal:



396 BAB 22 Stored Procedures



DECLARE nama_variabel1 INT DEFAULT 10;



Pada contoh diatas, variabel nama_variabel1 memiliki nilai default 10. Selanjutnya, untuk memberi nilai pada variabel, kita dapat menggunakan statemen SET atau SELECT...INTO seperti yang kita gunakan pada user variable. Sebagai tambahan, pada local variable, kita tidak perlu menggunakan tanda @ seperti yang kita gunakan pada user variabel. Beberapa ketentuan penulisan statemen DECLARE: 



Harus berada di dalam blok BEGIN dan END.







Semua statemen DECLARE harus berada di paling atas tepat setelah BEGIN dan sebelum statemen lain ditulis.



Sebagai contoh, misal kita buat SP dengan nama harga_neto yang akan menghasilkan harga neto dari barang setelah diskon, Query yang kita jalankan: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.



DELIMITER $ DROP PROCEDURE IF EXISTS harga_neto $ CREATE PROCEDURE harga_neto( IN id INT, OUT harga_neto INT ) BEGIN DECLARE nilai_diskon FLOAT; SET nilai_diskon = ( SELECT diskon FROM diskon WHERE id_kategori = 0 AND expired > NOW() ); SELECT harga - (harga * nilai_diskon) INTO harga_neto FROM buku WHERE id_buku = id; END $



Panduan Lengkap Query MySQL 397



Pada contoh diatas, kita simpan nilai diskon pada variabel nilai_diskon. Perhatikan bahwa pada baris nomor 8, kita menggunakan tipe data float karena diskon berupa desimal yaitu 0,1 (10%). Selanjutnya kita hitung harga neto dengan mengurangkan harga produk dengan diskon, hasilnya kita masukkan ke dalam variabel harga neto. Jika kita panggil SP tersebut, maka hasil yang kita peroleh: mysql> CALL harga_neto(1, @harga_neto); Query OK, 1 row affected (0.00 sec) mysql> SELECT @harga_neto; +-------------+ | @harga_neto | +-------------+ | 53100 | +-------------+ 1 row in set (0.00 sec)



Harga awal adalah 59.000 setelah dikurang diskon 10% menjadi 53.100 Jika kita menggunakan model user variable, kita tidak perlu menggunakan statemen DECLARE, misal pada query diatas kita definisikan variabel nilai_diskon dengan statemen SET: 1. BEGIN 2. SET @nilai_diskon = ( SELECT diskon 3. FROM diskon 4. WHERE id_kategori = 0 5. AND expired > NOW() 6. ); 7. ... 8. END $



22.6. Statemen IF dan CASE Pada Stored Procedure Pada Store Procedure yang kompleks, akan banyak ekspresi logika yang dilakukan. Untuk keperluan tersebut, MySQL telah menyediakan berbagai control flow statement yaitu statemen IF ... ELSE dan CASE. Statemen 398 BAB 22 Stored Procedures



IF disini berbeda dengan fungsi IF yang kita gunakan pada statemen SELECT. IF pada statemen SELECT hanya bisa digunakan untuk menguji satu kondisi, sedang statemen IF yang kita bahas disini, karena bentuknya



statemen, maka dapat digunakan untuk menguji banyak kondisi. Statemen IF diawali dengan keyword IF dan diakhiri dengan END IF. Format umum penulisannya adalah sebagai berikut: IF kondisi THEN statemen [ESEIF kondisi THEN statemen] ... [ELSE statemen] END IF



Pada format diatas, statemen yang ada di dalam tanda kurung siku yaitu ELSEIF dan ELSE sifatnya opsional, tidak harus ada. Misal melanjutkan contoh sebelumnya, kita akan membuat diskon berdasarkan kategori buku, untuk kategori 1, diskon 20%, kategori 2, 15%, kategori 3 10%, sedangkan sisanya 5%. Query yang kita jalankan: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20.



DELIMITER $ CREATE DEFINER=`root`@`localhost` PROCEDURE `harga_neto2`( IN `id` INT, OUT `harga_awal` INT, OUT `harga_neto` INT, OUT `diskon` DECIMAL(10,2) ) BEGIN DECLARE kategori INT; DECLARE nilai_diskon FLOAT; SET kategori = (SELECT id_kategori FROM buku WHERE id_buku = id ); -- diskon (OUT) IF kategori = 1 THEN SET nilai_diskon = 0.2;



Panduan Lengkap Query MySQL 399



21. ELSEIF kategori = 2 22. THEN SET nilai_diskon = 0.15; 23. ELSEIF kategori = 3 24. THEN SET nilai_diskon = 0.1; 25. ELSE SET nilai_diskon = 0.08; 26. END IF; 27. 28. SET diskon = nilai_diskon; 29. 30. -- harga_awal (OUT) dan harga_neto (OUT) 31. SELECT harga, harga - (harga * diskon) 32. INTO harga_awal, harga_neto 33. FROM buku 34. WHERE id_buku = id; 35. END $ 36. DELIMITER ;



Ketika kita jalankan, maka hasil yang kita peroleh adalah: mysql> CALL harga_neto2 (1, @harga_awal, @harga_neto, @diskon); Query OK, 1 row affected (0.00 sec) mysql> SELECT @harga_awal, @harga_neto, @diskon; +-------------+-------------+---------+ | @harga_awal | @harga_neto | @diskon | +-------------+-------------+---------+ | 59000 | 53100 | 0.10 | +-------------+-------------+---------+ 1 row in set (0.00 sec)



Query diatas menghasilkan output harga awal, harga diskon, dan nilai diskon. Penjelasan: 



Pada baris 6 kita definisikan tipe data diskon dengan DECIMAL(10,2) yang artinya desimal dengan dua angka di belakang koma.







Pada baris 14 kita cari id_kategori dari buku yang memiliki id_buku 1, hasilnya kita simpan pada variabel kategori.







Pada baris 19 s.d 26, berdasarkan nilai pada variabel kategori, kita cari besarnya nilai diskon.



400 BAB 22 Stored Procedures







Pada baris 28 kita simpan nilai_diskon pada variabel diskon sebagai nilai keluaran (OUT)







Selanjutnya kita gunakan statemen SELECT untuk mencari harga awal dan harga diskon berdasarkan id_buku, hasilnya kita simpan pada variabel keluaran harga_awal dan harga_diskon.



Selain menggunakan statemen IF, untuk menguji kondisi, kita dapat menggunakan statemen CASE, keduanya memiliki fungsi yang sama tergantung kita lebih nyaman menggunakan yang mana. Adapun struktur penulisan statemen CASE adalah: CASE case_value WHEN when_value THEN statement_list [WHEN when_value THEN statement_list] ... [ELSE statement_list] END CASE



Selain cara diatas, terdapat bentuk lain penulisan statemen CASE, yaitu: CASE WHEN search_condition THEN statement_list [WHEN search_condition THEN statement_list] ... [ELSE statement_list] END CASE



cara kedua ini umumnya kita gunakan untuk menuliskan CASE pada statemen SELECT. Karena memiliki alur yang mudah dipahami, cara pertama lebih pas digunakan jika kita ingin melakukan pengujian satu nilai, seperti penggunaan fungsi IF pada statemen SELECT. Sedangkan cara kedua lebih mirip dengan statemen IF dimana kita menguji kondisi yang berbeda beda. Misal pada contoh sebelumnya, kita ubah SP harga_neto2 menggunakan statemen CASE bentuk pertama:



Panduan Lengkap Query MySQL 401



1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34.



DELIMITER $ DROP PROCEDURE IF EXISTS harga_neto2$ CREATE PROCEDURE harga_neto2( IN id INT, OUT harga_awal INT, OUT harga_neto INT, OUT diskon DECIMAL(10,2) ) BEGIN DECLARE kategori INT; DECLARE nilai_diskon FLOAT; SET kategori = (SELECT id_kategori FROM buku WHERE id_buku = id ); -- diskon (OUT) CASE kategori WHEN 1 THEN SET nilai_diskon = 0.2; WHEN 2 THEN SET nilai_diskon = 0.15; WHEN 3 THEN SET nilai_diskon = 0.1; ELSE SET nilai_diskon = 0.08; END CASE; SET diskon = nilai_diskon; -- harga_awal (OUT) dan harga_neto (OUT) SELECT harga, harga - (harga * diskon) INTO harga_awal, harga_neto FROM buku WHERE id_buku = id; END $ DELIMITER ;



SP diatas memiliki fungsi yang sama dengan SP yang kita buat menggunakan statemen IF, misal kita panggil SP tersebut untuk mendapatkan harga neto produk dengan ID 2: mysql> CALL harga_neto2 (2, @harga_awal, @harga_neto, @diskon); Query OK, 1 row affected (0.00 sec) mysql> SELECT @harga_awal, @harga_neto, @diskon;



402 BAB 22 Stored Procedures



+-------------+-------------+---------+ | @harga_awal | @harga_neto | @diskon | +-------------+-------------+---------+ | 75000 | 63750 | 0.20 | +-------------+-------------+---------+ 1 row in set (0.00 sec)



Pada contoh diatas, karena produk dengan ID 2 memiliki id_kategori 1, maka diskon yang didapatkan sebesar 0.2 (20%). Statemen CASE diatas jika diubah ke dalam bentuk kedua akan menjadi seperti berikut ini: 1. CASE 2. WHEN kategori = 1 THEN SET nilai_diskon = 0.2; 3. WHEN kategori = 2 THEN SET nilai_diskon = 0.15; 4. WHEN kategori = 3 THEN SET nilai_diskon = 0.1; 5. ELSE SET nilai_diskon = 0.08; 6. END CASE;



22.7. Parameter Tambahan (Optional) Pada Stored Procedure Ketika kita membuat SP, terdapat parameter tambahan yaitu definer dan karakteristik yang secara otomatis ditambahkan. Letak keduanya adalah sebagai berikut: CREATE [DEFINER] PROCEDURE nama_procedure() [karakteristik] BEGIN ... END



Karakteristik terdiri dari: COMMENT 'string' LANGUAGE SQL [NOT] DETERMINISTIC



Panduan Lengkap Query MySQL 403



{ CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } SQL SECURITY { DEFINER | INVOKER }



Karakteristik ditulis tidak harus urut sesuai urutan diatas, disamping itu, kita juga dapat menggunakan karakteristik tertentu sesuai kebutuhan, misal hanya menggunakan COMMENT. Penjelasan dari parameter tambahan tersebut adalah sebagai berikut: 



DEFINER terkait siapa yang mendefinisikan/membuat SP, definer ini berisi username yang ketika SP dibuat otomatis akan berisi username



yang sedang digunakan. Kita dapat mengisikan username kita sendiri atau user lain. User yang mendefinisikan SP otomatis akan memiliki hak akses untuk memanggil SP tersebut (EXECUTE), mengubahnya (ALTER) dan menghapusnya (DROP), karakteristik ini disimpan pada variable sistem automatic_sp_privileges. Jika parameter ini dikosongkan, maka akan otomatis diisi dengan data user yang mendefinisikan SP. 



COMMENT digunakan untuk memberikan komentar pada SP. komentar ini bermanfaat untuk menjelaskan fungsi dari SP tersebut, yang bisa



jadi ketika SP tersebut sudah lama dibuat, kita akan lupa apa sebenarnya fungsi dari SP tersebut. 



LANGUAGE yang bernilai SQL, mengindikasikan bahwa SP berisi statemen SQL. Saat ini hanya bahasa SQL yang didukung, ke depan, bisa jadi kita dapat menulis SP dengan bahasa lain.







DETERMINISTIC berarti bahwa SP akan menghasilkan nilai yang sama pada input yang sama, nilai defaultnya adalah NOT DETERMINISTIC. Sejauh ini query yang kita buat adalah NON DETERMINISTIC yang



artinya jika isi dari tabel yang kita gunakan pada SP berubah, maka output dari SP juga berubah. 



CONTAINS SQL berarti SP tidak mengandung statemen untuk membaca atau menulis data seperti SET @nama = 'Alfa'. Untuk parameter lain:



(1) NO SQL berarti SP tidak mengandung statemen SQL, sedangkan (2) 404 BAB 22 Stored Procedures



READ SQL berarti SP mengandung statemen untuk membaca data (SELECT), tetapi tidak untuk menulis data, (3) MODIFY SQL DATA berarti bahwa SP mengandung statemen untuk menulis data, seperti INSERT dan DELETE



Secara default MySQL akan menggunakan CONTAINS SQL, namun demikian MySQL tidak mengecek karakteristik ini, misal jika kita menggunakan CONTAINS NO SQL, kita tetap dapat menggunakan statemen INSERT, UPDATE, dan DELETE 



SQL SECURITY bisa berisi DEFINER atau INVOKER, nilai defaultnya adalah DEFINER. SP dapat berisi query untuk memanipulasi data pada tabel, misal untuk SP yang berisi statemen untuk menambahkan data pada tabel A, maka pada SQL SECURITY INVOKER, user yang memanggil SP tersebut harus memiliki hak akses untuk menambahkan data ke tabel A, jika DEFINER, maka hak akses untuk menambahkan data tersebut harus dimiliki oleh pembuat SP, yang didefinisikan pada parameter DEFINER (pembahasan paling atas)



Contoh penulisan SP lengkap dengan karakteristiknya: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17.



DELIMITER $ DROP PROCEDURE IF EXISTS `harga_neto2` $ CREATE DEFINER=`root`@`localhost` PROCEDURE `harga_neto2`( IN `id` INT, OUT `harga_awal` INT, OUT `harga_neto` INT, OUT `diskon` DECIMAL(10,2) ) LANGUAGE SQL NOT DETERMINISTIC CONTAINS SQL SQL SECURITY DEFINER COMMENT 'Stored Procedure yang digunakan untuk menghitung harga neto setelah dikurangi diskon' BEGIN ... END $ DELIMITER ;



Panduan Lengkap Query MySQL 405



22.8. Menampilkan Stored Procedure Yang Ada Pada Database Untuk menampilkan semua stored procedure yang ada pada server database, gunakan perintah berikut: SHOW PROCEDURE STATUS



Ketika kita jalankan perintah tersebut, data yang ditampilkan kurang lebih sebagai berikut: +-----------------+-----------------------+-----------+----------------+ | Db | Name | Type | Definer | +-----------------+-----------------------+-----------+----------------+ | tutorial | penjualan_akumulatif | PROCEDURE | root@localhost | | tutorial | penjualan_total_bulan | PROCEDURE | root@localhost | | shop | sales_neto | PROCEDURE | root@localhost | | shop | sales_month | PROCEDURE | root@localhost | +-----------------+-----------------------+-----------+----------------+



Lanjutan… +---------------------+---------------------+---------------+---------+ | Modified | Created | Security_type | Comment | +---------------------+---------------------+---------------+---------+ | 2017-03-18 05:14:50 | 2016-03-18 05:14:50 | DEFINER | | | 2017-03-18 20:42:18 | 2016-03-18 20:42:18 | DEFINER | | | 2017-03-18 17:20:53 | 2016-03-18 17:20:53 | DEFINER | | | 2017-03-18 19:47:05 | 2016-03-18 19:47:05 | DEFINER | | +---------------------+---------------------+---------------+---------+



Untuk menampilkan procedure pada database tertentu kita gunakan klausa where, misal kita tampilkan hanya procedure yang ada pada database toko_buku, maka perintah yang kita jalankan: SHOW PROCEDURE STATUS WHERE db = 'toko_buku'



Atau jika kita ingin menampilkan nama procedure yang mengandung kata tertentu, kita bisa menggunakan operator LIKE, misal kita tampilkan SP yang mengandung kata order: SHOW PROCEDURE STATUS WHERE name LIKE '%order%'



406 BAB 22 Stored Procedures



Seperti filter yang digunakan pada tabel umumnya, kita juga dapat mencari SP berdasarkan kolom lain seperti tanggal pembuatan. Jika kita ingin menampilkan query yang ada pada stored procedure, kita dapat menggunakan perintah: SHOW CREATE PROCEDURE nama_procedure



Jika kita mendefinisikan nama database di depan nama procedure, maka akan dipanggil SP yang ada pada database tersebut, jika tidak didefinisikan, maka akan ditampilkan SP yang ada pada database yang sedang digunakan. Misal kita tampilkan data SP harga_neto2: mysql> SET sql_mode = 'ANSI'; Query OK, 0 rows affected (0.02 sec) mysql> SHOW CREATE PROCEDURE harga_neto2\G; *************************** 1. row *************************** Procedure: harga_neto2 sql_mode: STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION Create Procedure: CREATE DEFINER=`root`@`localhost` PROCEDURE `harga_neto2`( IN id INT, OUT harga_awal INT, OUT harga_neto INT, OUT diskon DECIMAL(10,2) ) BEGIN DECLARE kategori INT; DECLARE nilai_diskon FLOAT; SET kategori = (SELECT id_kategori FROM buku WHERE id_buku = id ); -- diskon (OUT) CASE kategori WHEN 1 THEN SET nilai_diskon = 0.2; WHEN 2 THEN SET nilai_diskon = 0.15; WHEN 3 THEN SET nilai_diskon = 0.1;



Panduan Lengkap Query MySQL 407



ELSE SET nilai_diskon = 0.08; END CASE; SET diskon = nilai_diskon; -- harga_awal (OUT) dan harga_neto (OUT) SELECT harga, harga - (harga * diskon) INTO harga_awal, harga_neto FROM buku WHERE id_buku = id; END character_set_client: utf8mb4 collation_connection: utf8mb4_general_ci Database Collation: latin1_swedish_ci 1 row in set (0.00 sec)



Pada query diatas, penulis mengubah sql_mode menjadi ANSI agar hasil yang ditampilkan lebih mudah dibaca.



22.9. Mengubah Stored Procedure Pada MySQL, kita dapat mengubah stored procedure menggunakan statemen ALTER sebagai berikut: ALTER PROCEDURE nama_procedure [karakteristik ...]



Meski dapat mengubah SP, kita hanya dapat mengubah karakteristiknya saja, tidak dapat mengubah parameter atau isi dari Stored Procedure. Karakteristik yang dapat diubah adalah: COMMENT 'string' LANGUAGE SQL { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } SQL SECURITY { DEFINER | INVOKER }



Untuk mengubah parameter atau isi dari SP, kita harus menghapus SP tersebut dengan statemen DROP, baru kemudian kita buat SP baru dengan nama yang sama, seperti yang kita lakukan pada beberapa contoh sebelumnya. 408 BAB 22 Stored Procedures



22.10. Menghapus Stored Procedure Untuk menghapus stored procedure, gunakan statemen DROP PROCEDURE diikuti nama stored procedure. Misal kita akan menghapus SP harga_neto, query yang kita jalankan: DROP PROCEDURE harga_neto



Sebagai tambahan, kita dapat mendefinisikan nama database dimana SP tersebut berada, misal: DROP PROCEDURE toko_buku.harga_neto



Jika tidak didefinisikan, maka MySQL akan secara implisit menambahkan nama database yang sekarang sedang digunakan ke depan nama SP. Kita juga dapat menambahkan klausa IF EXISTS untuk mengetes apakah SP tersebut ada, misal: DROP PROCEDURE IF EXISTS harga_neto



Jika tidak menggunakan IF EXISTS, maka jika nama SP tidak ditemukan, akan muncul pesan ERROR SQL Error (1305): PROCEDURE tutorial.nama_procedure does not exist Hal ini mengakibatkan query berikutnya tidak akan dieksekusi, untuk itu sebaiknya selalu gunakan klausa IF EXISTS



Panduan Lengkap Query MySQL 409



Halaman ini sengaja dikosongkan Jagowebdev.com



410 BAB 22 Stored Procedures



BAB 23 Stored Function Pada BAB sebelumnya kita telah membahas Stored Routines yang pertama yang itu Stored Procedure, pada BAB ini, kita akan membahas Stored Routines yang kedua yaitu Stored Function. Stored Function atau SF adalah fungsi (function) yang dibuat oleh user yang disimpan (stored) dalam database. Mirip dengan Stored Procedure (SP), SF juga bermanfaat untuk menyederhanakan syntax SQL yaitu cukup dengan memanggil statemen tertentu saja, tidak perlu menulis berulang ulang query yang kompleks. Karakteristik Stored Functions: 



Sama dengan stored procedure, SF juga dapat menerima parameter, namun parameter yang diterima hanya parameter masukan saja (parameter IN pada SP).







SF Hanya menghasilkan satu nilai (single value) dengan tipe data tertentu yang didefinisikan di bagian awal SF. Jika ingin menghasilkan lebih dari satu nilai, gunakan stored procedure.







SF sama halnya dengan fungsi bawaan SQL seperti SUM, COUNT, dll sehingga dapat digabung dengan statemen lain, misal: SELECT SF(..), SUM(..)



23.1. Membuat Stored Function Untuk membuat stored function, format yang digunakan adalah: 1. CREATE FUNCTION nama_fungsi ([parameter]) 2. RETURNS tipe_data [CHARSET character_set] 3. BEGIN 4. RETURN statemen 5. END



Panduan Lengkap Query MySQL 411



Penjelasan: 



Klausa CHARSET bersifat opsional.







Parameter boleh untuk tidak diisi. Kita tidak bisa menyertakan IN, OUT, maupun INOUT pada parameter, semua parameter secara implisit bersifat IN







Klausa RETURNS pada baris 2 harus ada. Perhatikan bukan klausa RETURN tetapi RETURNS (ada tambahan S).







Isi dari fungsi (antara BEGIN dan END) harus mengandung setidaknya satu statemen RETURN (tidak ada tambahan S), yang digunakan untuk menghentikan eksekusi fungsi dan mengembalikan hasil kepada pemanggil fungsi.



Contoh penggunaan stored function: misal kita buat fungsi untuk menampilkan data total penjualan untuk bulan dan tahun tertentu pada tabel penjualan. Query yang kita jalankan: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.



DELIMITER $ DROP FUNCTION IF EXISTS total_perbulan $ CREATE FUNCTION total_perbulan(bulan INT, tahun INT) RETURNS INT BEGIN RETURN (SELECT SUM(total_trx) FROM penjualan WHERE MONTH(tgl_trx) = bulan AND YEAR(tgl_trx) = tahun ); END $ DELIMITER ;



Pada contoh diatas, kita membuat SF dengan nama total_perbulan yang akan menghitung total penjualan pada bulan dan tahun tertentu. Seperti pada stored procedure, kita juga dapat menjalankan statemen SQL pada SF, selain itu, kita juga perlu mengubah delimiter, karena isi dari SF juga menggunakan delimiter titik koma. Selanjutnya, mari kita panggil fungsi tersebut:



412 BAB 23 Stored Function



SELECT total_perbulan(3, 2017) AS total_3_2017 Hasilnya: +--------------+ | total_3_2017 | +--------------+ | 1135000 | +--------------+



Lebih lanjut, ketika membuat SF kita juga dapat menambahkan definer dan parameter tambahan seperti COMMENT, LANGUAGE, DETERMINISTIC, dll, format lengkapnya adalah sebagai berikut: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.



CREATE [DEFINER] FUNCTION nama_fungsi ([parameter]) RETURNS tipe_data CHARSET utf8 COMMENT 'string' LANGUAGE SQL [NOT] DETERMINISTIC { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } SQL SECURITY { DEFINER | INVOKER } BEGIN RETURN statemen END



Penjelasan masing masing deterministic sama persis dengan penjelasan pada stored procedure.



23.2. Stored Function Dengan Lebih Dari Satu Statemen Return Pada SF kita dapat mendefinisikan lebih dari satu statemen RETURN, terutama SF yang mengandung control flow. Misal pada tabel buku, kita akan memberi nama status stok buku berdasarkan jumlah stok yaitu sedikit, cukup, dan banyak. Query yang kita jalankan:



Panduan Lengkap Query MySQL 413



1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.



DELIMITER $ DROP FUNCTION IF EXISTS status_stok $ CREATE FUNCTION status_stok(jml_stok INT) RETURNS VARCHAR(50) BEGIN IF jml_stok >= 10 THEN RETURN ('BANYAK'); ELSE IF jml_stok =3 THEN RETURN ('CUKUP'); ELSE IF jml_stok > 0 AND jml_stok = 10 10. THEN SET @nama_status = "BANYAK"; 11. ELSE IF jml_stok =3 12. THEN SET @nama_status = "CUKUP"; 13. ELSE IF jml_stok > 0 AND jml_stok SET sql_mode = 'ANSI'; Query OK, 0 rows affected (0.00 sec) mysql> SHOW CREATE FUNCTION status_stok\G; *************************** 1. row *************************** Function: status_stok sql_mode: STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION Create Function: CREATE DEFINER=`root`@`localhost` FUNCTION `status_stok`(jml_stok INT) RETURNS varchar(50) CHARSET latin1 BEGIN SET @nama_status = 'KOSONG'; IF jml_stok >= 10 THEN SET @nama_status = 'BANYAK'; ELSE IF jml_stok =3 THEN SET @nama_status = 'CUKUP'; ELSE IF jml_stok > 0 AND jml_stok SELECT * FROM user; Empty set (0.00 sec)



Ternyata sekarang tabel user menjadi kosong. Kenapa seperti itu? Pada MySQL, setiap kali statemen dijalankan, maka MySQL akan melakukan commit yang artinya perubahan akan di simpan secara permanen ke dalam database, misal ketika kita menjalankan statemen INSERT, maka ketika MySQL berhasil memasukkan data ke tabel, seketika itu akan melakukan commit yang artinya data tersebut benar benar disimpan pada tabel secara permanen. Tindakan commit seketika tersebut disebut dengan istilah autocommit. Melalui Transaction, kita ubah pola commit tersebut. Dengan statemen START TRANSACTION, kita cegah MySQL untuk melakukan commit ketika terjadi perubahan data hingga kita menjalankan statemen COMMIT atau ROLLBACK. Pada contoh sebelumnya, ketika kita tambahkan data pada tabel user, MySQL belum melakukan commit, meskipun data tersebut telah ditampilkan pada tabel user. Selanjutnya, ketika kita jalankan perintah ROLLBACK, MySQL membatalkan semua perubahan yang telah terjadi, sehingga tabel user menjadi kosong kembali, atau jika kita ubah ROLLBACK menjadi COMMIT, MySQL akan melakukan commit dengan menyimpan perubahan menjadi permanen, sehingga tabel user akan berisi data alfa dan bravo. Setelah kita menjalankan statemen COMMIT atau ROLLBACK, maka transaksi berakhir dan pola commit pada MySQL akan kembali seperti semula pada kondisi sebelum statemen START TRANSACTION dijalankan. misal jika kita tambahkan data ke tabel user maka data tersebut akan langsung disimpan secara permanen. Contoh lain, perhatikan query berikut ini: mysql> START TRANSACTION;



422 BAB 24 Transaction



Query OK, 0 rows affected (0.08 sec) mysql> INSERT INTO user VALUES('alfa'); Query OK, 1 row affected (0.02 sec) mysql> INSERT INTO user VALUES('alfa '); ERROR 1062 (23000): Duplicate entry 'alfa' for key 'username' mysql> ROLLBACK; Query OK, 0 rows affected (0.04 sec) mysql> SELECT * FROM user; Empty set (0.00 sec)



Pada contoh diatas, statemen INSERT yang pertama berhasil sedangkan yang kedua gagal karena alamat email sama, setelah kita jalankan statemen ROLLBACK, semua perubahan akan dibatalkan, termasuk statemen INSERT yang pertama, namun jika kita jalankan COMMIT, perubahan yang dilakukan oleh statemen INSERT yang pertama akan disimpan secara permanen ke tabel user.



24.3. Membuat Transaksi Dengan Autocommit Terkait dengan autocommit, secara default autocommit bersifat true, kita dapat membuatnya non aktif dengan menggunakan statemen SET autocommit = 0. Jika autocommit off, maka MySQL tidak akan melakukan commit sampai kita menjalankan statemen COMMIT untuk menyimpan perubahan atau ROLLBACK untuk mengembalikan data ke kondisi semula. Perhatikan contoh berikut: mysql> SET autocommit = 0; Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO user VALUES('alfa'); Query OK, 1 row affected (0.04 sec) mysql> SELECT * FROM user; +----------+ | username |



Panduan Lengkap Query MySQL 423



+----------+ | alfa | +----------+ 1 row in set (0.00 sec) mysql> ROLLBACK; Query OK, 0 rows affected (0.09 sec) mysql> SELECT * FROM user; Empty set (0.00 sec)



Pada contoh diatas, meskipun kita telah menambahkan data username alfa ke dalam tabel user, namun data tersebut belum disimpan secara permanen. Hal tersebut dikarenakan autocommit tidak aktif, sehingga ketika kita jalankan statemen ROLLBACK, data dikembalikan seperti semula, jika kita jalankan statemen COMMIT, data tersebut akan disimpan secara permanen. Hal ini mirip dengan transaksi bukan ? (ya, kita bahas di paragraf berikutnya) Ketika autocommit OFF, maka sejatinya Transaksi sudah berjalan baik ada maupun tidak ada statemen START TRANSACTION, selanjutnya, ketika kita menjalankan statemen COMMIT atau ROLLBACK, maka kita hanya membuat apakan perubahan yang telah terjadi akan disimpan secara permanen atau dibatalkan. Transaksi akan benar benar berhenti sampai kita mengubah autocommit menjadi ON. Perhatikan contoh berikut: mysql> SET autocommit = 0; Query OK, 0 rows affected (0.08 sec) mysql> START TRANSACTION; Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO user VALUES ('alfa'); Query OK, 1 row affected (0.09 sec) mysql> INSERT INTO user VALUES ('bravo'); Query OK, 1 row affected (0.00 sec) mysql> COMMIT; Query OK, 0 rows affected (0.08 sec)



424 BAB 24 Transaction



mysql> SELECT * FROM user;



+-----------+ | username | +-----------+ | alfa | | bravo | +-----------+ 2 rows in set (0.00 sec)



Pada query diatas, ketika kita menjalankan statemen COMMIT, maka data akan disimpan secara permanen pada database, namun demikian, transaksi belum berakhir, statemen setelahnya akan dianggap MySQL sebagai bagian dari transaksi (meskipun kita tidak menjalankan kembali statemen START TRANSACTION), mari kita lanjutkan percobaan diatas: mysql> INSERT INTO user VALUES ('charlie'); Query OK, 1 row affected (0.03 sec) mysql> INSERT INTO user VALUES ('bravo'); ERROR 1062 (23000): Duplicate entry 'bravo ' for key 'username' mysql> ROLLBACK; Query OK, 0 rows affected (0.05 sec) mysql> SELECT * FROM user;



+-----------+ | username | +-----------+ | alfa | | bravo | +-----------+ 2 rows in set (0.00 sec) mysql> SET autocommit = 1; Query OK, 0 rows affected (0.00 sec)



Pada query diatas, setelah autocommit menjadi aktif, maka transaksi berakhir. Seperti yang telah kita bahas sebelumnya, transaksi akan berakhir ketika kita menjalankan statemen COMMIT, ROLLBACK, atau mengaktifkan kembali autocommit. Metode tersebut merupakan metode eksplisit untuk menghentikan transaksi, namun demikian transaksi akan otomatis Panduan Lengkap Query MySQL 425



berhenti dan MySQL akan melakukan commit jika pada transaksi terdapat statemen yang tidak bisa digunakan dalam transaksi, hal ini disebut implisit commit. Statemen yang tidak dapat digunakan pada transaksi diantaranya statemen yang berkaitan dengan perubahan struktur tabel seperti CREATE, ALTER, dan DROP. List lengkapnya dapat dilihat di http://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html. Perhatikan contoh berikut: mysql> START TRANSACTION; Query OK, 0 rows affected (0.12 sec) mysql> INSERT INTO user VALUES('charlie'); Query OK, 1 row affected (0.05 sec) mysql> ALTER TABLE user ADD COLUMN `email` VARCHAR(50) NOT NULL AFTER `username`; Query OK, 0 rows affected (0.45 sec) mysql> ROLLBACK; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM user; +----------+ | username | +----------+ | alfa | | bravo | | charlie | +----------+ 3 rows in set (0.00 sec)



Pada contoh diatas, sebelum MySQL menjalankan statemen ALTER TABLE, MySQL akan melakukan commit, sehingga data username charlie ditambahkan secara permanen ke dalam database dan statemen ROLLBACK tidak berpengaruh lagi.



24.4. Menggunakan SAVEPOINT Dengan SAVEPOINT kita dapat mengembalikan kondisi transaksi pada titik tertentu. Untuk melakukannya, buat SAVEPOINT dengan nama tertentu 426 BAB 24 Transaction



pada bagian tertentu transaksi, selanjutnya, untuk mengembalikan transaksi ke kondisi pada SAVEPOINT tersebut, gunakan statemen ROLLBACK TO diikuti nama SAVEPOINT. Perhatikan contoh berikut: mysql> START TRANSACTION; Query OK, 0 rows affected (0.10 sec) mysql> INSERT INTO user values('delta'); Query OK, 1 row affected (0.11 sec) mysql> SAVEPOINT savepoint_1; Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO user values('foo'); Query OK, 1 row affected (0.00 sec) mysql> ROLLBACK TO savepoint_1; Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO user values('golf'); Query OK, 1 row affected (0.00 sec) mysql> COMMIT; Query OK, 0 rows affected (0.07 sec) mysql> SELECT * FROM user; +----------+ | username | +----------+ | alfa | | bravo | | charlie | | delta | | golf | +----------+ 5 rows in set (0.00 sec)



Pada contoh diatas ketika kita jalankan statemen ROLLBACK TO savepoint_1, maka semua perubahan setelah savepoint_1 akan di batalkan.



Panduan Lengkap Query MySQL 427



24.5. Otomasi ROLLBACK Sejauh ini, kita menjalankan statemen ROLLBACK secara manual, artinya kita yang mengidentifikasi kondisi dimana kita akan melakukan rollback. Dalam praktek, kondisi tersebut harus dapat diidentifikasi oleh aplikasi, sehingga ROLLBACK dapat dilakukan secara otomatis, misal saat terjadi error pada bagian tertentu. Agar aplikasi dapat secara otomatis mengidentifikasi kondisi, maka kita perlu ekspresi logika, yang dalam hal ini statemen IF, perlu diperhatikan bahwa statemen IF ini berbeda dengan fungsi IF yang kita gunakan pada statemen SELECT, yang telah kita bahas pada BAB terdahulu. Pada MySQL, statemen IF hanya bisa dijalankan pada compound statement yaitu blok statemen yang diawali dengan BEGIN dan diakhiri dengan END. Compound statement ini hanya ada pada stored routines: STORED PROCEDURE, STORED FUNCTION, dan TRIGGER, sehingga jika transaksi yang kita buat mengandung statemen IF, maka harus kita buat di dalam stored routines tersebut. Misal kita buat transaksi dalam stored procedure bernama transaksi sebagai berikut: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.



DELIMITER $ DROP PROCEDURE IF EXISTS transaksi; CREATE PROCEDURE transaksi () BEGIN DECLARE sql_error BOOL DEFAULT 0; DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN SET sql_error = 1; END;



START TRANSACTION; INSERT INTO user VALUES ('nitro'); INSERT INTO user VALUES ('alfa'); -- Error: duplikasi data 15. INSERT INTO user VALUES ('zebra'); 16.



428 BAB 24 Transaction



17. IF sql_error = 0 18. THEN COMMIT; 19. ELSE 20. ROLLBACK; 21. END IF; 22. END $ 23. DELIMITER ;



Jika kita jalankan, maka tidak ada penambahan data pada tabel user karena terjadi duplikasi data pada username alfa, jika kita ganti alfa dengan, misal gama, maka data pada tabel user akan bertambah 3 username, yaitu: nitro, gama, dan zebra Pada query diatas, pertama tama kita definisikan variabel sql_error dengan nilai 0, selanjutnya kita gunakan statemen DECLARE EXIT HANDLER FOR SQLEXCEPTION untuk menangkap pesan error (ketika terjadi error). Pada statemen tersebut, kita gunakan DECLARE EXIT karena ketika terjadi error, maka query akan berhenti (exit), selain EXIT, terdapat handler bernama WARNING yang akan menangkap jika ada waring). Format penulisan DECLARE ... HANDLER adalah: DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN statemen; END;



Jika statemen hanya satu baris, statemen tersebut bisa langsung ditulis tanpa harus menggunakan BEGIN...END, sehingga statemen DECLARE pada contoh diatas dapat kita ubah menjadi: DECLARE EXIT HANDLER FOR SQLEXCEPTION SET sql_error = 1



Dengan statemen DECLARE EXIT HANDLER, maka ketika terjadi error, MySQL akan mengeksekusi statemen tersebut yang akan akan mengubah nilai variabel sql_error menjadi 1, dengan demikian ketika MySQL mengeksekusi statemen IF, maka kondisi ELSE yang akan terpenuhi, sehingga statemen ROLLBACK yang akan dijalankan. Panduan Lengkap Query MySQL 429



Dalam praktek, cara diatas kurang praktis karena bisa jadi kondisi selalu berubah ubah, yang mengakibatkan syntax pada stored procedure selalu berubah, dan tidaklah praktis jika kita berulang membuat stored procedure, selain itu, kita juga sulit mendeteksi penyebab terjadinya error (kita bahas pada sub BAB 24.6. Membuat Transaksi (Lanjutan)). Untuk itu, pengujian error dapat dilakukan pada level aplikasi, sehingga kita tidak perlu membuat stored procedure. Contoh berikut implementasi pada PHP: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30.