Anda di halaman 1dari 539

EKSKLUSIF

PANDUAN
QUERY MySQL
Tutorial dan referensi lengkap
SQL pada MySQL

INSERT SELECT
TRANSACTION

TRIGGERS
UPDATE
SQL
VIEWS EVENTS

CROSSTAB
DELETE DDL

Agus Prawoto Hadi


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 prawoto.hadi@gmail.com

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. Numeric............................................................................................................. 63

6.1.1. 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. Klausa USING ..................................................................................... 157

x Daftar Isi
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-community-
5.7.17.0.msi dengan ukuran file sekitar 380 Mb, bukan yang mysql-installer-web-
community-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. Masing-
masing 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. 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
10. CHARACTER SET latin1
11. AUTO_INCREMENT=10;

Perhatikan bahwa titik koma ditulis di akhir statemen.

Pada contoh diatas, kolom id_pelanggan kita beri atribut


AUTO_INCREMENT sedangkan pada tabel juga kita beri atribut
AUTO_INCREMENT dengan nilai 10.

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', 'alfa@yahoo.com');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM pelanggan;


+--------------+------+---------+----------------+
| id_pelanggan | nama | alamat | email |
+--------------+------+---------+----------------+
| 10 | alfa | Jakarta | alfa@yahoo.com |
+--------------+------+---------+----------------+

Panduan Lengkap Query MySQL 47


1 row in set (0.00 sec)

mysql> INSERT INTO pelanggan (nama, alamat, email) VALUES


('beta', 'Jakarta', 'beta@yahoo.com');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM pelanggan;


+--------------+------+---------+----------------+
| id_pelanggan | nama | alamat | email |
+--------------+------+---------+----------------+
| 10 | alfa | Jakarta | alfa@yahoo.com |
| 11 | beta | Jakarta | beta@yahoo.com |
+--------------+------+---------+----------------+

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 anonym@gmail.com

ALTER TABLE pengarang MODIFY email VARCHAR(255) DEFAULT


"anonym@gmail.com"

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:

Storage
Tipe Data Value
(byte)

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


TINYINT ([M]) 1
255
Signed: -32768 s.d 32767, Unsigned:
SMALLINT ([M]) 2
0 s.d 65535
MEDIUMINT Signed: -32768 s.d 32767, Unsigned:
3
([M]) 0 s.d 16777215
Signed: -2147483648 s.d
INT ([M]) 2147483648, Unsigned: 0 s.d 4
4294967295
Signed: -9223372036854775808 s.d
BIGINT ([M]) 9223372036854775807, Unsigned: 0 8
s.d 18446744073709551615
Tergantung
DECIMAL([M,D]) Tergantung nilai M dan D
M dan D
Minimum Nonzero Value:
FLOAT[(M,D)] ±1.175494351E-38 s.d ± 4
3.402823466E+38
Minimum Nonzero Value: ±
DOUBLE [(M,D)] 2.2250738585072014E-308 s.d ± 8
1.7976931348623157E+308
Tergantung
BIT 0 s.d 2M-1, dimana 1 ≤ M ≤ 64
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
-99999.99 s.d
DECIMAL(5, 2) 0.00 s.d 99999.9
99999.99

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. INSERT INTO `tes_enum` (`col_enum`) VALUES ('Alfa');


2. INSERT INTO `tes_enum` (`col_enum`) VALUES ('Beta');
3. INSERT INTO `tes_enum` (`col_enum`) VALUES ('Charlie');
4. INSERT INTO `tes_enum` (`col_enum`) VALUES ('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]
1000-01-01 9999-12-31
DATETIME 8+(fp)
00:00:00[.000000] 23:59:59[.999999]
1970-01-01 2038-01-19
TIMESTAMP 4+(fp)
00:00:00[.000000] 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-5-


2017', '%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 (1970-
01-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-01-


01 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. mysql> SHOW CREATE TABLE penjualan \G;


2. *************************** 1. row ***************************
3. Table: penjualan
4. Create Table: CREATE TABLE `penjualan` (
5. `id_trx` int(11) NOT NULL,
6. `id_pelanggan` int(11) NOT NULL,
7. `tgl_trx` datetime DEFAULT CURRENT_TIMESTAMP,
8. `total_trx` int(11) DEFAULT NULL
9. ) ENGINE=InnoDB DEFAULT CHARSET=latin1
10. 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 | anton@gmail.com |
| 2 | Braskie | braskie@yahoo.com |
| 3 | Charlie | charlie@gmail.com |
| 4 | Deni | deni@gmail.com |
+--------------+----------+---------------------+

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. `total_trx` INT(11) NOT NULL DEFAULT '0',
6. PRIMARY KEY (`id_trx`),
7. FOREIGN KEY (`id_pelanggan`)
8. REFERENCES pelanggan (`id_pelanggan`)
9. ON UPDATE CASCADE ON DELETE RESTRICT
10. )

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. SELECT *
2. FROM information_schema.table_constraints
3. 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. SELECT *
2. FROM information_schema.key_usage_column
3. 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 KEY, dapat dilihat pada tabel


referential_constraints

1. SELECT *
2. FROM information_schema.referential_constraints
3. 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. SELECT id_buku, judul, tgl_terbit


2. FROM buku1
3. WHERE id_penerbit = 1
4. 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. SELECT id_buku, judul, tgl_terbit


2. FROM buku1
3. WHERE id_penerbit = 1
4. 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. SELECT id_buku, judul, tgl_terbit


2. FROM buku1
3. WHERE id_penerbit = 4
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. SELECT id_penerbit, COUNT(judul) AS jumlah_buku


2. FROM buku1
3. GROUP BY id_penerbit
4. 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. SELECT judul, tgl_terbit


2. FROM buku
3. WHERE id_penerbit = 1
4. ORDER BY tgl_terbit DESC, judul ASC
5. 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. SELECT judul, tgl_terbit


2. FROM buku
3. WHERE id_penerbit = 1
4. ORDER BY tgl_terbit DESC, judul ASC
5. 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. SELECT judul, tgl_terbit, pengarang.nama, penerbit.nama


2. FROM buku, pengarang, penerbit
3. WHERE buku.id_pengarang = pengarang.id_pengarang
4. AND buku.id_penerbit = penerbit.id_penerbit
5. ORDER BY tgl_terbit DESC
6. 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. SELECT judul AS 'Judul Buku',


2. tgl_terbit AS 'Tanggal Terbit',
3. pengarang.nama AS Pengarang,
4. penerbit.nama AS Penerbit
5. FROM buku, pengarang, penerbit
6. WHERE buku.id_pengarang = pengarang.id_pengarang
7. AND buku.id_penerbit = penerbit.id_penerbit
8. ORDER BY tgl_terbit DESC
9. 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. SELECT bk.judul AS 'Judul Buku',
2. bk.tgl_terbit AS 'Tanggal Terbit',
3. pg.nama AS Pengarang,
4. pn.nama AS Penerbit
5. FROM buku AS bk, pengarang AS pg, penerbit AS pn
6. WHERE bk.id_pengarang = pg.id_pengarang
7. AND bk.id_penerbit = pn.id_penerbit
8. ORDER BY tgl_terbit DESC
9. LIMIT 5

Sama seperti pada kolom alias, kita juga dapat mengabaikan penggunaan
AS, sehingga kode yang kita tulis menjadi:

1. SELECT bk.judul 'Judul Buku',


2. bk.tgl_terbit 'Tanggal Terbit',
3. pg.nama Pengarang,
4. pn.nama Penerbit
5. FROM buku bk, pengarang pg, penerbit pn
6. WHERE bk.id_pengarang = pg.id_pengarang
7. AND bk.id_penerbit = pn.id_penerbit
8. ORDER BY tgl_terbit DESC
9. 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:

Operator Keterangan

A>B True jika A Lebih besar dari B

A<B True jika A Lebih kecil dari B

A >= B True jika A lebih besar atau sama dengan B

A <= B True jika A lebih kecil atau sama dengan B

A=B True jika A sama dengan B

A != B atau A <> B True jika A tidak sama dengan B

Tabel 9.2. Operator Pembanding

Penting diperhatikan bahwa ketika mengevaluasi nilai pada operator, jika


diperlukan, MySQL akan mengubah tipe data nilai tersebut, disamping itu
juga tidak dibedakan antara huruf besar dan huruf kecil.

Contoh: jika nilai yang kita bandingkan berupa string (teks) namun isi
string tersebut berupa numeric/angka maka MySQL akan mengubahnya
menjadi numeric.

Contoh berikut ini akan bernilai true

mysql> 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. SELECT judul, tgl_terbit, id_penerbit


2. FROM buku
3. WHERE id_penerbit = 1 OR id_penerbit = 2
4. ORDER BY tgl_terbit DESC
5. 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. SELECT judul, tgl_terbit, id_penerbit


2. FROM buku
3. WHERE id_penerbit = 1 AND tgl_terbit >= "2016-00-00"
4. ORDER BY tgl_terbit DESC
5. 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. SELECT judul, tgl_terbit, id_penerbit


2. FROM buku
3. WHERE id_penerbit IN (1, 3, 4)
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 <=
nilai_maksimum

Contoh: query berikut akan mengambil data buku yang dipublikasikan


antara bulan Juni s.d Desember 2016

138 BAB 9 Operator


1. SELECT judul, id_pengarang, tgl_terbit
2. FROM buku
3. WHERE tgl_terbit BETWEEN "2015-06-00" AND "2015-12-31"

Hasil yang kita peroleh:


+----------------------------------------------+--------------+------------+
| judul | id_pengarang | tgl_terbit |
+----------------------------------------------+--------------+------------+
| Blogger untuk Pemula | 5 | 2015-06-15 |
| Trik Kolaborasi ANDROID dengan PHP dan MySQL | 10 | 2015-12-22 |
+----------------------------------------------+--------------+------------+

Contoh lain kita ambil data buku yang memiliki rentang harga 25000 s.d
50000

1. SELECT judul, harga


2. FROM buku
3. WHERE harga BETWEEN 25000 AND 50000
4. ORDER By harga DESC
5. LIMIT 5

Hasil:
+--------------------------------------+-------+
| judul | harga |
+--------------------------------------+-------+
| Buku Sakti Wordpress | 49800 |
| Ide Bisnis Bermodal Blog | 49800 |
| Desain Grafis dengan Powerpoint | 46800 |
| Otodidak Membuat Blog dengan Blogger | 39800 |
| Jago Wordpress | 39800 |
+--------------------------------------+-------+

9.6. Operator NOT


Operator not digunakan untuk membalik kondisi yang telah ditentukan
sebelumnya atau dalam arti lain menghasilkan data selain dari kondisi
yang telah ditetapkan. Sebagai contoh, kita balik query pada contoh
sebelumnya, kita ambil semua data buku yang tidak terbit di tahun 2016
dan id_penerbitnya bukan 1 atau 3

Panduan Lengkap Query MySQL 139


1. SELECT judul, id_penerbit, tgl_terbit
2. FROM buku
3. WHERE NOT (
4. (id_penerbit = 1 OR id_penerbit = 3) AND
tgl_terbit >= "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-00-
00 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. SELECT judul, nama
2. FROM buku
3. LEFT JOIN penerbit ON buku.id_penerbit =
4. 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. SELECT id_buku, judul, jml_barang, total


2. FROM buku
3. LEFT JOIN penjualan_detail
4. 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. SELECT judul, nama


2. FROM buku
3. RIGHT JOIN penerbit
4. 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. SELECT judul, nama


2. FROM buku
3. RIGHT JOIN penerbit
4. ON buku.id_penerbit = penerbit.id_penerbit
5. 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. SELECT judul, nama
2. FROM buku
3. LEFT JOIN penerbit ON buku.id_penerbit = penerbit.id_penerbit
4. UNION
5. SELECT judul, nama
6. FROM buku
7. 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. SELECT judul, pg.nama AS nama_pengarang, pn.nama AS nama_penerbit


2. FROM buku
3. LEFT JOIN pengarang AS pg
4. ON buku.id_pengarang = pg.id_pengarang
5. LEFT JOIN penerbit AS pn
6. 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. SELECT judul, pg.nama AS pengarang


2. FROM buku
3. LEFT JOIN pengarang AS pg USING (id_pengarang)
4. 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. SELECT judul, pn.nama AS nama_penerbit


2. , pg.nama AS nama_pengarang
3. FROM buku
4. NATURAL LEFT JOIN pengarang pg
5. 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. SELECT judul, nama AS nama_penerbit


2. FROM buku
3. LEFT JOIN penerbit USING (id_penerbit)
4. WHERE judul LIKE "%mysql%" AND nama LIKE "%andi%"
5. 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. SELECT judul, nama AS nama_penerbit


2. FROM buku
3. LEFT JOIN penerbit ON buku.id_penerbit =
4. penerbit.id_penerbit
WHERE nama LIKE "%andi%"

dan query inner join berikut ini:

1. SELECT judul, nama AS nama_penerbit


2. FROM buku
3. JOIN penerbit ON buku.id_penerbit = penerbit.id_penerbit
4. 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 17:01:02 merupakan waktu data


dimasukkan.

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. INSERT INTO penjualan_rekap


2. SELECT LAST_INSERT_ID(), '2017-03-05', NOW(), SUM(total_trx)
3. FROM penjualan
4. 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-01-


22', '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 2017-
05-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 ') AS Hasil

Sebelum: Hasil query:


+-----------+ +-------+
| Judul | | Hasil |
+-----------+ +-------+
| Judul | | Judul |
+-----------+ +-------+

Contoh LTRIM:

SELECT LTRIM(' Judul ') AS Hasil

Sebelum: Hasil query:


+-----------+ +----------+
| Judul | | Hasil |
+-----------+ +----------+
| Judul | | Judul |
+-----------+ +----------+

Contoh RTRIM:

SELECT RTRIM(' Judul ') AS Hasil

Sebelum: Hasil query:


+-----------+ +--------+
| Hasil | | Hasil |
+-----------+ +--------+
| Judul | | 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: ', 95)

200 BAB 12 Functions


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:', tgl_terbit,
4. ', Harga:', harga
5. ) AS buku
6. FROM buku

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-MM-


DD 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 2016-
03-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)
Hari dalam satu minggu berbentuk angka (0 = Minggu, 6 =
%w
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. SELECT id_buku, judul


2. FROM buku
3. WHERE id_buku > FLOOR( RAND() * (5-2) ) + 2
4. 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. SELECT *
2. FROM tabel_buku
3. WHERE id_buku > 2
4. ORDER BY RAND()
5. 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


Menghasilkan string dengan tipe data BINARY. Jika
BINARY[(N)] opsi N digunakan, maka panjang data yang dihasilkan
maksimal N byte
Menghasilkan string dengan tipe data CHAR. Jika opsi
CHAR[(N)] N digunakan, maka jumlah karakter yang dihasilkan
sejumlah N
DATE Menghasilkan tipe data DATE
DATETIME Menghasilkan tipe data DATETIME
Menghasilkan tipe data DECIMAL, opsi M untuk
membatasi jumlah digit maksimal yang akan
DECIMAL[(M[,D])] 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


Menghasilkan tipe data INTEGER dengan jenis SIGNED
SIGNED[INTEGER]
yang artinya mencakup nilai positif dan negatif
Menghasilkan tipe data INTEGER dengan jenis
UNSIGNED[INTEGER] 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 BY ini dengan
mendefinisikan sendiri klausa GROUP BY

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. SELECT nama AS "Nama Penerbit",


2. MAX(tgl_terbit) AS "Terbit Terakhir",
3. COUNT(judul) AS "Jumlah Buku",
4. SUM(harga) AS "Jumlah Harga",
5. COUNT(harga) * SUM(harga) AS "Total Harga"
6. FROM penerbit
7. LEFT JOIN buku
8. USING(id_penerbit)
9. 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. SELECT nama AS nama_penerbit,


2. MAX(YEAR(tgl_terbit)) AS tahun_terbit,
3. COUNT(judul) AS jumlah_buku,
4. SUM(harga) AS jumlah_harga,
5. COUNT(harga) * SUM(harga) AS total_harga
6. FROM penerbit
7. LEFT JOIN buku USING(id_penerbit)
8. GROUP BY id_penerbit
9. 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. SELECT nama AS nama_penerbit,


2. MAX(YEAR(tgl_terbit)) AS tahun_terbit,
3. COUNT(judul) AS jumlah_buku,
4. SUM(harga) AS jumlah_harga,
5. COUNT(harga) * SUM(harga) AS total_harga
6. FROM penerbit
7. LEFT JOIN buku
8. USING(id_penerbit)
9. GROUP BY id_penerbit
10. HAVING tahun_terbit > 2014
11. 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. SELECT nama AS nama_penerbit,


2. MAX(YEAR(tgl_terbit)) AS tahun_terbit,
3. COUNT(judul) AS jumlah_buku,
4. SUM(harga) AS jumlah_harga,
5. COUNT(harga) * SUM(harga) AS total_harga
6. FROM penerbit
7. LEFT JOIN buku
8. USING(id_penerbit)
9. GROUP BY id_penerbit
10. HAVING tahun_terbit > 2014
11. ORDER BY tahun_terbit DESC
12. 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. SELECT COALESCE(SUM(stok), 0) AS jumlah_buku


2. FROM penerbit
3. LEFT JOIN buku USING(id_penerbit)
4. 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. WHEN harga = 0
6. THEN judul
7. ELSE harga
8. END

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-00-
00

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 kolom
FROM tabel
WHERE kondisi
GROUP BY kolom
HAVING kondisi
ORDER BY 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. SELECT nilai
2. FROM `uas`
3. ORDER BY nilai DESC
4. 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. SELECT id_barang,
2. nama_barang,
3. penjualan.harga,
4. COUNT(id_transaksi) AS jumlah,
5. penjualan.harga * COUNT(id_transaksi) AS total,
6. MAX(tanggal) AS transaksi_terakhir
7. FROM barang
8. LEFT JOIN penjualan AS penjualan USING(id_barang)
9. WHERE MONTH(tanggal) = 3
10. 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. SELECT id_barang, harga,


2. COUNT(id_barang) AS jumlah,
3. MAX(tanggal) AS tanggal
4. FROM penjualan
5. WHERE YEAR(tanggal) = 2017 AND MONTH(tanggal) = 3
6. GROUP BY id_barang

Sedangkan query utamanya adalah:

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 tabel_barang
8. LEFT JOIN (subquery) AS penjualan
9. USING (id_barang)
10. 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. IFNULL(tanggal, "-") AS trx_trakhir
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. GROUP BY id_barang
15. ) AS penjualan
16. USING (id_barang)
17. 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. SELECT id_barang,
2. nama_barang,
3. tanggal,
4. penjualan.harga
5. FROM penjualan
6. LEFT JOIN barang USING (id_barang)
7. WHERE id_barang = 2 AND
8. penjualan.harga < ( SELECT harga
9. FROM barang
10. WHERE id_barang = 2
11. )

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. SELECT id_barang,
2. nama_barang
3. FROM penjualan
4. LEFT JOIN barang USING (id_barang)
5. WHERE id_transaksi IN ( SELECT id_transaksi
6. FROM penjualan
7. GROUP BY id_barang
8. HAVING count(*) > 2
9. )

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. SELECT id_transaksi
2. FROM penjualan
3. GROUP BY id_barang
4. 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. SELECT id_barang,
2. nama_barang
3. FROM penjualan
4. LEFT JOIN barang USING (id_barang)
5. 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. SELECT id_barang,
2. nama_barang
3. FROM penjualan
4. LEFT JOIN barang USING (id_barang)
5. WHERE id_transaksi = ANY (SELECT id_transaksi
6. FROM penjualan
7. GROUP BY id_barang
8. HAVING count(*) > 2
9. )

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. SELECT id_barang, nama_barang


2. FROM penjualan
3. LEFT JOIN barang USING(id_barang)
4. GROUP BY id_barang
5. 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. SELECT nama_barang, barang.harga


2. FROM barang
3. LEFT JOIN penjualan USING (id_barang)
4. GROUP BY barang.id_barang
5. 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. SELECT id_barang,
2. nama_barang
3. FROM penjualan
4. JOIN barang USING(id_barang)
5. 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. SELECT id_barang, nama_barang


2. FROM penjualan
3. RIGHT JOIN barang USING (id_barang)
4. 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. SELECT id_barang,
2. nama_barang,
3. COUNT(id_transaksi) AS jml_transaksi
4. FROM barang
5. LEFT JOIN penjualan USING (id_barang)
6. 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. SELECT id_barang,
2. nama_barang,
3. COUNT(id_transaksi) AS jml_transaksi,
4. SUM(penjualan.harga) AS jml_penjualan,
5. (SELECT SUM(harga) FROM penjualan) AS total,
6. CONCAT(
7. ROUND(
8. SUM(penjualan.harga)
9. / (SELECT SUM(harga) FROM penjualan)
10. * 100
11. , 2
12. )
13. , "%"
14. ) AS persen
15. FROM barang
16. LEFT JOIN penjualan USING (id_barang)
17. 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 Tabel B
+-----------+------------+-----------+ +-----------+------------+---------+
| id_retur | tgl_retur | jml_retur | | id_barang | tgl_trx | harga |
+-----------+------------+-----------+ +-----------+------------+---------+
| 1 | 2017-03-10 | 3500000 | | 2 | 2017-02-15 | 3100000 |
| 1 | 2017-03-12 | 3250000 | | 3 | 2017-03-12 | 3250000 |
| 2 | 2017-02-15 | 3100000 | +-----------+------------+---------+
| 2 | 2017-02-15 | 3100000 |
+-----------+------------+-----------+

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. SELECT kolom1, kolom2, kolom3


2. FROM tabel1
3. WHERE kondisi
4. UNION atau UNION ALL
5. SELECT kolom1, kolom2, kolom3
6. FROM tabel2
7. WHERE kondisi
8. [statemen SELECT yang lain…]
9. 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. SELECT tgl_trx, total_trx, "order" AS jenis_trx


2. FROM penjualan
3. WHERE id_pelanggan = 2
4. UNION ALL
5. SELECT tgl_retur, nilai_retur, "retur" AS jenis_trx
6. FROM retur
7. WHERE id_pelanggan = 2
8. 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. statemen SELECT pertama


2. UNION ALL
3. statemen SELECT kedua
4. 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. UNION
5. SELECT id_pelanggan, nama, "transaksi" AS jenis
6. FROM retur
7. LEFT JOIN pelanggan USING(id_pelanggan)
8. UNION ALL
9. SELECT id_pelanggan, nama, "-" AS jenis
10. 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. SELECT id_pelanggan, nama


2. FROM pelanggan
3. UNION ALL
4. SELECT id_pelanggan, nama
5. FROM penjualan
6. LEFT JOIN pelanggan USING(id_pelanggan)
7. 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. SELECT NULL AS id_retur, id_pelanggan, tgl_trx
2. FROM penjualan
3. UNION ALL
4. SELECT id_retur, id_pelanggan, tgl_retur
5. 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. SELECT *
2. FROM (
3. 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. SELECT id_pelanggan, tgl_trx AS tanggal, "order" AS
2. jenis_trx
3. FROM penjualan
4. ORDER BY tgl_trx DESC
5. 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. SELECT id_pelanggan, tgl_trx AS tanggal, "order" AS jenis_trx


2. FROM penjualan
3. UNION ALL
4. SELECT id_pelanggan, tgl_retur, "retur" AS jenis_trx
5. FROM retur
6. 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. SELECT id_pelanggan, tgl_trx AS tanggal, "order" AS jenis_trx


2. FROM penjualan
3. UNION ALL
4. (SELECT id_pelanggan, tgl_retur, "retur" AS jenis_trx
5. FROM retur
6. 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. SELECT id_pelanggan, nama, tanggal, jenis_trx


2. FROM (SELECT id_pelanggan, tgl_trx AS tanggal, "order" AS
3. jenis_trx
4. FROM penjualan
5. UNION ALL
6. SELECT id_pelanggan, tgl_retur, "retur" AS jenis_trx
7. FROM retur
8. ) AS penjualan
9. 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. SELECT id_trx, nama, bln_trx, thn_trx, SUM(nilai_trx)


2. FROM sales
3. GROUP BY id_trx
4. 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. SELECT bln_trx, nama, COUNT(id_trx), SUM(nilai_trx)


2. FROM sales
3. GROUP BY bln_trx, nama
4. 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. SELECT bln_trx, thn_trx, nama, COUNT(id_trx), SUM(nilai_trx)


2. FROM sales
3. GROUP BY bln_trx, thn_trx, nama
4. 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. SELECT
2. IFNULL(thn_trx, "TOTAL") AS tahun,
3. IFNULL(bln_trx, "TOTAL") AS bulan,
4. IFNULL(nama, "TOTAL") AS nama_sales,
5. COUNT(id_trx),
6. SUM(nilai_trx)
7. FROM sales
8. GROUP BY thn_trx, bln_trx, nama
9. 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. SELECT
2. IFNULL(nama, "TOTAL") AS nama_sales,
3. COUNT(id_trx),
4. SUM(nilai_trx)
5. FROM sales2
6. GROUP BY nama_sales
7. 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. SELECT
2. IFNULL(MONTH(tgl_trx), "TOTAL") as bln_trx,
3. IFNULL(nama, "TOTAL") as nama_sales,
4. COUNT(id_trx),
5. SUM(nilai_trx)
6. FROM sales2
7. GROUP BY MONTH(tgl_trx), nama
8. 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. SELECT
2. IFNULL(UPPER(nama), "TOTAL") as nama_sales,
3. COUNT(id_trx),
4. SUM(nilai_trx)
5. FROM sales2
6. GROUP BY UPPER(nama)
7. 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. SELECT IFNULL(thn_trx, 'TOTAL') AS tahun,


2. IFNULL(bln_trx, 'TOTAL') AS bulan,
3. IFNULL(nama, 'TOTAL') AS nama_sales,
4. COUNT(id_trx),
5. SUM(nilai_trx)
6. FROM sales
7. GROUP BY thn_trx DESC, bln_trx DESC, nama
8. 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. SELECT * FROM
2. (
3. SELECT IFNULL(thn_trx, '1-TOTAL') AS tahun,
4. IFNULL(bln_trx, '1-TOTAL') AS bulan,
5. IFNULL(nama, 'TOTAL') AS nama_sales,
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) |
+---------+---------+------------+---------------+----------------+
| 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. SELECT IFNULL(thn_trx, 'TOTAL') AS tahun,


2. IFNULL(bln_trx, 'TOTAL') AS bulan,
3. IFNULL(nama, 'TOTAL') AS nama_sales,
4. COUNT(id_trx),
5. SUM(nilai_trx)
6. FROM sales
7. GROUP BY thn_trx, bln_trx, nama
8. WITH ROLLUP
9. 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. SELECT IFNULL(nama, "TOTAL") AS NAMA_SALES,


2. SUM( IF(MONTH(tgl_trx) = 1, nilai_trx, 0) ) AS januari,
3. SUM( IF(MONTH(tgl_trx) = 2, nilai_trx, 0) ) AS februari,
4. SUM( nilai_trx ) AS total
5. FROM sales3
6. GROUP BY nama
7. 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. SELECT IFNULL(nama, "TOTAL") AS nama_sales,


2. COUNT( IF(MONTH(tgl_trx) = 1, nilai_trx, NULL) ) AS trx_1,
3. SUM( IF(MONTH(tgl_trx) = 1, nilai_trx, 0) ) AS bln_1,
4. COUNT( IF(MONTH(tgl_trx) = 2, nilai_trx, NULL) ) AS trx_2,
5. SUM( IF(MONTH(tgl_trx) = 2, nilai_trx, 0) ) AS bln_2,
6. COUNT( nilai_trx ) AS jml_trx,
7. SUM( nilai_trx ) AS total
8. FROM sales3
9. GROUP BY nama
10. WITH ROLLUP

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. SELECT IFNULL(nama, "SUB TOTAL") AS nama_sales,


2. IFNULL(tim, "TOTAL") as sales_tim,
3. COUNT( IF(MONTH(tgl_trx) = 1, nilai_trx, NULL) ) AS tx_1,
4. SUM( IF(MONTH(tgl_trx) = 1, nilai_trx, 0) ) AS bln_1,
COUNT( IF(MONTH(tgl_trx) = 2, nilai_trx, NULL) ) AS tx_2,
5. SUM( IF(MONTH(tgl_trx) = 2, nilai_trx, 0) ) AS bln_2,
6. COUNT( nilai_trx ) AS jml_tx,
7. SUM( nilai_trx ) AS total
8. FROM sales3
9. GROUP BY tim, nama
10. WITH ROLLUP

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. SELECT IFNULL(nama, 'SUB TOTAL') AS nama_sales,


2. IFNULL(tim, 'TOTAL') as sales_tim,
3. COUNT( IF(MONTH(tgl_trx) = 1, nilai_trx, NULL) ) AS tx_1,
SUM( IF(MONTH(tgl_trx) = 1, nilai_trx, 0) ) AS bln_1,
4.
COUNT( IF(MONTH(tgl_trx) = 2, nilai_trx, NULL) ) AS tx_2,
5.
SUM( IF(MONTH(tgl_trx) = 2, nilai_trx, 0) ) AS bln_2,
6. COUNT( nilai_trx ) AS jml_tx,
7. SUM( nilai_trx ) AS total
8. FROM sales3
9. GROUP BY tim DESC, nama DESC
10. WITH ROLLUP

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. SELECT * FROM (
2. SELECT
3. nama, tim,
4. SUM(IF(MONTH(tgl_trx) = 1, nilai_trx, 0)) AS bln_1,
5. COUNT(IF(MONTH(tgl_trx) = 1, id_trx, NULL)) AS trx_1,
6. SUM(IF(MONTH(tgl_trx) = 2, nilai_trx, 0)) AS bln_2,
7. COUNT(IF(MONTH(tgl_trx) = 2, nilai_trx, NULL)) AS trx_2,
8. COUNT(id_trx) AS jml_trx,
9. SUM(nilai_trx) AS total_trx
10. FROM sales3
11. GROUP BY tim, nama
12. ORDER BY total_trx DESC
13. ) AS tabel_sales
14. UNION ALL
15. SELECT 'TOTAL' AS nama, '' AS tim,
16. SUM(IF(MONTH(tgl_trx) = 1, nilai_trx, 0)) AS bln_1,
17. COUNT(IF(MONTH(tgl_trx) = 1, id_trx, NULL)) AS trx_1,
18. SUM(IF(MONTH(tgl_trx) = 2, nilai_trx, 0)) AS bln_2,
19. COUNT(IF(MONTH(tgl_trx) = 2, nilai_trx, NULL)) AS trx_2,
20. COUNT(id_trx) AS jml_trx,
21. SUM(nilai_trx) AS total_trx
22. 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. 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. );
12.
13. SET @SQL = CONCAT('SELECT IFNULL(nama, "TOTAL") AS nama_sales, ',
14. @sql_dinamis, '
15. FROM sales3
16. GROUP BY nama WITH ROLLUP'
17. );
18.
19. PREPARE stmt FROM @sql;
20. EXECUTE stmt;
21. 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. SELECT IFNULL(nama, "TOTAL") AS nama_sales,


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
4. FROM sales3
5. GROUP BY nama
6. 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. SELECT IFNULL(nama, "TOTAL") AS nama_sales,


2. COUNT( IF(MONTH(tgl_trx) = 1, nilai_trx, NULL) ) AS trx_1,
3. SUM( IF(MONTH(tgl_trx) = 1, nilai_trx, 0) ) AS bln_1,
4. COUNT( IF(MONTH(tgl_trx) = 2, nilai_trx, NULL) ) AS trx_2,
5. SUM( IF(MONTH(tgl_trx) = 2, nilai_trx, 0) ) AS bln_2,
6. COUNT(tgl_trx) AS JML_TRX,
7. SUM(nilai_trx) AS TOTAL
8. FROM sales3
9. GROUP BY nama
10. WITH ROLLUP

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 full-
text 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. SELECT judul
2. FROM buku
3. WHERE MATCH(judul) AGAINST('mysql')
4. LIMIT 3;

Jika kita ingin secara eksplisit mendefinisikan nama mode, kita dapat
menambahkannya pada argumen fungsi AGAINST():

1. SELECT judul
2. FROM buku
3. WHERE MATCH(judul) AGAINST('mysql IN NATURAL LANGUAGE MODE')
4. 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. SELECT judul
2. FROM buku
3. WHERE judul LIKE '%mysql%'
4. 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. SELECT judul, MATCH(judul) AGAINST('mysql') AS score
2. FROM buku
3. WHERE MATCH(judul) AGAINST('mysql')
4. 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 deskripsi

Pemrograman Kemampuan yang disediakan oleh MySQL berupa


Stored Procedure stored procedure, function dan trigger tidak
Pada MySQL + cd 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 MySQL adalah database yang sangat populer.
Database Buku ini dirancang sebagai referensi cepat untuk
Menggunakan mencari solusi-solusi atau teknik-teknik untuk
MySQL menjawab banyak pertanyaan spesifik ketika
menggunakan MySQL.

MySQL Untuk Buku ini membahas langkah demi langkah


Pemula menggunakan MySQL, lengkap dengan contoh-
contoh 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 Pencarian dilakukan seperti pada mode natural language


operator)

Kata yang mengikuti operator ini memiliki score yang


> lebih tinggi dibanding kata yang lain.

Panduan Lengkap Query MySQL 345


Kata yang mengikuti operator ini memiliki score yang
< lebih rendah dibanding kata yang lain.

Mengelompokkan kata dalam sebuah ekspresi,


memungkinkan kata dalam grup tersebut memiliki
()
kriteria tertentu, seperti: harus ada dalam pencarian,
dikecualikan dari pencarian, memiliki score tertentu, dll

Membuat kata yang mengikuti operator ini memiliki score


~ negatif, tetapi tidak dikecualikan pada hasil pencarian.

Kata diikuti 0 atau lebih karakter lainnya. Hanya bisa


* diletakkan di belakang kata.

Hasil pencarian harus mengandung kata sama persis


" dengan kata yang ada di dalam tanda kutip.

Tabel 19.1 Operator Pada Full Text Search

Contoh penggunaan:

 'php mysl' Mencari teks yang mengandung kata php atau mysql,
sama seperti klausa OR

 '+php +mysql' Mencari teks yang mengandung kata php dan mysql,
sama seperti klausa AND

 '+php mysql' Mencari teks yang mengandung kata php (opsional


mysql) dan beri score yang tinggi jika terdapat kata mysql

 '+php -mysql' Mencari teks yang mengandung kata php tetapi tidak
mengandung kata mysql.

 '+php ~mysql' Mencari teks yang mengandung kata php. Jika teks
tersebut mengandung kata mysql, beri score yang lebih rendah
daripada yang tidak mengandung kata mysql.

 '+php +(>mysql <mssql)' Mencari teks yang mengandung kata php


dan mysql atau php dan mssql, php dan mysql memiliki score lebih
tinggi dibanding php dan mssql.

346 BAB 19 FULL TEXT Search


 'blog*' Mencari teks yang mengandung kata blog, seperti blog,
blogger, blogging

 '"php dan mysql"' Mencari teks yang mengandung kata sama persis
'php dan mysql'

Sebagai tambahan, berikut contoh penggunaan full-text search tanpa


operator:

1. SELECT judul
2. FROM buku
3. WHERE MATCH(judul) AGAINST('php 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 |
| Kumpulan Aplikasi PHP untuk Pemula |
| Framework PHP Yii 2 |
| Pemrograman Database Menggunakan MySQL |
| Pemrograman Stored Procedure Pada MySQL + cd |
| MySQL Untuk Pemula |
+----------------------------------------------+

Pada contoh diatas, karena kita tidak menggunakan operator apapun, full-
text search akan mencari judul yang mengandung kata php atau mysql,
sama seperti mode natural language mode atau tanpa klausa: IN BOOLEAN
MODE WHERE MATCH(judul) AGAINST('php mysql');

19.6. Query Expansion

Mode terakhir adalah query expansion. Pada mode ini, full-text akan
melakukan pencarian dua kali, yaitu menggunakan natural language mode,
kemudian kata dari hasil pencarian yang paling relevan (score tertinggi)
akan digunakan untuk melakukan pencarian berikutnya.

Panduan Lengkap Query MySQL 347


Untuk menggunakan mode ini, kita gunakan klausa WITH QUERY
EXPANSION pada fungsi AGAINST(), misal, pada contoh berikut, kita akan
melakukan pencarian judul buku yang mengandung kata database.

Pencarian menggunakan natural language mode:

1. SELECT judul, MATCH(judul) AGAINST('database') AS score


2. FROM buku
3. WHERE MATCH(judul) AGAINST('database');

Hasil:
+----------------------------------------+--------------------+
| judul | score |
+----------------------------------------+--------------------+
| Pemrograman Database Menggunakan MySQL | 2.8319292068481445 |
| Database Systems + CD | 2.7910914421081543 |
+----------------------------------------+--------------------+

Pencarian menggunakan Query Expansion

1. SELECT judul, MATCH(judul) AGAINST('database' WITH QUERY


EXPANSION) AS score
2. FROM buku
3. WHERE MATCH(judul) AGAINST('database' WITH QUERY EXPANSION);

Hasil:
+-------------------------------------------------------+--------------------+
| judul | score |
+-------------------------------------------------------+--------------------+
| Pemrograman Database Menggunakan MySQL | 2.900294780731201 |
| Database Systems + CD | 2.7910914421081543 |
| Mudah Menggunakan Internet Untuk Pemula | 1.0428276062011719 |
| Pemrograman PHP Dan MySQL Untuk Pemula | 0.8146394491195679 |
| Pemrograman Stored Procedure Pada MySQL + cd | 0.8146394491195679 |
| From Zero To A Pro: Pemrograman Aplikasi Android + cd | 0.5186294317245483 |
| PHP dan MySQL Langkah Demi Langkah + CD | 0.2960100471973419 |
| MySQL Untuk Pemula | 0.2960100471973419 |
| Trik Kolaborasi ANDROID dengan PHP dan MySQL | 0.2960100471973419 |
+-------------------------------------------------------+--------------------+

Penjelasan:

Query pertama menghasilkan baris dengan judul Pemrograman Database


Menggunakan MySQL dan Database Systems + CD, karena keduanya memiliki
score yang sama, maka pada query selanjutnya, full-text menggunakan

348 BAB 19 FULL TEXT Search


kata pada kedua baris tersebut untuk melakukan query berikutnya, yaitu
kata pemrograman, menggunakan, mysql, dan system

Panduan Lengkap Query MySQL 349


Halaman ini sengaja dikosongkan
Jagowebdev.com

350 BAB 19 FULL TEXT Search


BAB 20 Variable

MySQL memungkinkan kita untuk menyimpan data pada variabel yang


nantinya variabel ini dapat dipanggil pada statemen SQL berikutnya.
Variabel pada MySQL memiliki karakteristik sama seperti variabel pada
bahasa pemrograman umumnya, namun demikian, terdapat beberapa
perbedaan mendasar.

Terdapat tiga jenis variabel pada MySQL yaitu User-defined variable, local
variable dan system variable. Pada bab ini kita hanya membahas user-
defined variable saja, karena jenis variabel ini yang paling sering
digunakan. Untuk local variabel, dibahas pada BAB Stored Procedure.

20.1. Penulisan User-Defined Variable


Pada MySQL, variable dapat di deklarasikan menggunakan dua cara yaitu
menggunakan statement SET dan SELECT diikuti nama variable.

Contoh pendeklarasian variable;

1. SET @nama := 'Agus Prawoto Hadi';


2. SELECT @website := 'Jagowebdev.com';

Pada variabel, terdapat istilah yang dikenal dengan operator assignment.


Operator ini berguna untuk memasukkan nilai pada variabel. MySQL,
menyediakan dua buah operator assignment, yaitu = dan := selain itu,
terdapat sebuah klausa yang juga berfungsi sebagai assignment, yaitu
klausa INTO

1. Operator sama dengan ( = ). Operator ini hanya dapat digunakan jika


kita membuat variabel dengan statemen SET, karena pada statemen
SELECT, operator ini digunakan sebagai operator pembanding
(comparison operator), jika tetap menggunakan operator ini pada
statemen SELECT, maka nilai variabel tidak akan tersimpan.

Panduan Lengkap Query MySQL 351


2. Operator := . Operator ini dapat digunakan pada statemen SET
maupun SELECT

3. Klausa INTO. Klausa INTO hanya dapat digunakan pada statemen


SELECT. Format penulisannya adalah SELECT ekspresi INTO
@nama_variabel FROM nama_tabel

Ketika mendefinisikan variabel, kita bebas memilih nama untuk variabel


tersebut, namun demikian, nama variabel harus memenuhi beberapa
ketentuan, yaitu:
1. Nama variabel harus diawali dengan tanda @
2. Setelah karakter @ karakter berikutnya harus huruf, angka, titik (.),
underscore (_), atau dollar ($)
3. Kita juga dapat menggunakan karakter lain jika nama variabel barada
dalam tanda kutip (satu atau dua tanda kutip) atau backtick (`), misal:
@'nama-variable', @"nama-variable", dan @`nama-variable`

4. Mulai MySQL versi 5, nama variable bersifat case insensitive yang


artinya tidak membedakan huruf besar dan huruf kecil, sehingga
@nama_variable akan sama dengan @Nama_Variable.

5. Jika nilai variabel merupakan hasil dari query, maka query tersebut
harus berada di dalam tanda kurung, misal: SET @total := (SELECT
SUM(nilai_trx) FROM penjualan);
6. Untuk mendeklarasikan lebih dari satu variable, gunakan tanda koma,
misal:

SET @a = 1, @b = 2;
SELECT @a, @b;

atau

SELECT @a := 1, @b := 2;

352 BAB 20 Variable


20.2. Karakteristik User-Defined Variable
Ketika menggunakan dan mendefinisikan variabel terdapat beberapa hal
yang perlu diperhatikan:

1. Nilai variable dapat berupa integer, decimal, float, string, atau NULL:

2. Variable hanya dapat diisi satu nilai. Jika nilai tersebut berupa tabel
hasil query, maka tabel tersebut harus terdiri dari satu kolom dan satu
baris, jika tabel terdiri dari lebih dari satu baris, maka akan digunakan
baris terakhir, Misal:

SELECT @nilai := nilai_trx


FROM sales3
WHERE nama = "Alfa"

Hasil:
+---------------------+
| @nilai := nilai_trx |
+---------------------+
| 250000 |
| 125000 |
| 215000 |
| 350000 |
| 250000 |
+---------------------+

Karena baris terakhir bernilai 225000, maka variable @nilai akan


berisi 225000, mari kita tes dengan memanggil variable @nilai:

SELECT @nilai;

Hasil:
+--------+
| @nilai |
+--------+
| 225000 |
+--------+

Panduan Lengkap Query MySQL 353


3. Jika hasil query bernilai NULL, atau tidak menghasilkan data, maka nilai
variabel tidak akan berubah. Misal variabel @nilai pada contoh diatas,
kita isi dengan query yang menghasilkan nilai NULL

mysql> SELECT @nilai := nilai_trx


-> FROM tabel_sales
-> WHERE nama = "Zero";
Empty set (0.00 sec)
mysql> SELECT @nilai;
+--------+
| @nilai |
+--------+
| 225000 |
+--------+
1 row in set (0.00 sec)

Pada contoh diatas terlihat bahwa variabel @nilai tetap bernilai


225000.

4. User-defined variable dapat digunakan di sebagian besar klausa,


kecuali pada klausa tertentu yang memerlukan nilai literal secara
eksplisit, misal klausa LIMIT pada statemen SELECT dan klausa IGNORE
N LINE pada statemen LOAD DATA

User-defined variable bersifat session specific yang artinya hanya berlaku


pada MySQL klien tertentu, dengan demikian variabel ini tidak dapat
diakses oleh client lain, namun hal ini tidak berlaku bagi user yang
memiliki hak akses pada database Performance Schema.

Karakteristik lain dari variabel ini adalah sekali di deklarasikan, maka akan
dapat digunakan terus hingga session selesai ( koneksi tertutup atau user
logout).

20.3. Deklarasi Variable Dengan SET dan


SELECT
Seperti yang telah kita bahas pada bagian sebelumnya, kita dapat
mendeklarasikan variabel dengan statement SELECT dan SET. Perbedaan
keduanya adalah jika menggunakan SET, maka variabel hanya diberi nilai,

354 BAB 20 Variable


jika menggunakan SELECT, maka selain diberi nilai, variable juga akan
langsung di eksekusi, karena seperti yang telah kita bahas, statemen
SELECT digunakan untuk mengambil dan menampilkan data. Berikut ini
contoh perbedaan keduanya:

mysql> SET @nama = 'Agus Prawoto Hadi';


Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @website := 'JagoWebDev.com';


+-----------------------------+
| @website := 'JagoWebDev.com' |
+-----------------------------+
| NULL |
+-----------------------------+
1 row in set (0.00 sec)

Pada contoh diatas, terlihat bahwa pada perintah kedua, MySQL akan
menampilkan tabel yang berisi nilai dari variable @website, pada saat yang
sama, MySQL juga menyimpan nama dan nilai variabel tersebut, mari kita
tes dengan memanggil variable @website:

mysql> SELECT @website;


+----------------+
| @website |
+----------------+
| JagoWebDev.com |
+----------------+
1 row in set (0.00 sec)

Jika statement SELECT diikuti dengan INTO, sehingga statemen menjadi


SELECT .. INTO, maka nilai dari variabel tersebut tidak dicetak, misal:

mysql> SELECT 'JagoWebDev.com' INTO @website;


Query OK, 1 row affected (0.00 sec)

mysql> SELECT @website;


+----------------+
| @website |
+----------------+
| JagoWebDev.com |

Panduan Lengkap Query MySQL 355


+----------------+
1 row in set (0.00 sec)

Contoh lain:

mysql> SELECT MAX(nilai_trx) INTO @nilai_max FROM sales;


Query OK, 1 row affected (0.00 sec)

mysql> SELECT @nilai_max;


+------------+
| @nilai_max |
+------------+
| 350000 |
+------------+
1 row in set (0.00 sec)

20.4. Berbagai Contoh Penggunaan Variable


Dalam praktek, penggunaan variabel ini sangat bervariasi, tergantung dari
kondisi yang ada. Bagian ini akan menyajikan berbagai contoh penggunaan
variabel, dengan harapan dapat menambah pemahaman bagaimana
mendefinisikan dan menggunakan variabel.

Contoh 1: variable digunakan untuk menampilkan nomor urut. Misal kita


memiliki tabel ujian, yang berisi data nama siswa beserta nilai ujian
sebagai berikut:
+------+---------+-------+
| id | nama | nilai |
+------+---------+-------+
| 1 | Alfa | 97 |
| 2 | Bravo | 78 |
| 3 | Charlie | 83 |
| 4 | Delta | 81 |
| 5 | Echo | 79 |
+------+---------+-------+

Selanjutnya, dengan variable kita buat nomor urut sekaligus sebagai


peringkat berdasarkan nilai ujian. Query yang kita jalankan:

356 BAB 20 Variable


1. SET @no = 0;
2. SELECT @no := @no + 1 AS peringkat,
3. nama,
4. nilai
5. FROM ujian
6. ORDER BY nilai DESC

Hasil yang kita peroleh:


+-----------+---------+-------+
| peringkat | nama | nilai |
+-----------+---------+-------+
| 1 | Alfa | 97 |
| 2 | Charlie | 83 |
| 3 | Delta | 81 |
| 4 | Echo | 79 |
| 5 | Bravo | 78 |
+-----------+---------+-------+

Pada query diatas, pertama tama kita deklarasikan variabel @no dengan
nilai 0, selanjutnya, pada statement SELECT, variabel tersebut kita sertakan
pada hasil query sehingga, setiap kali variabel tersebut dieksekusi, nilainya
akan selalu bertambah satu @no := @no + 1, sehingga akan membentuk
data nomor urut.

Query diatas masih berupa dua statement, pada kondisi tertentu kita perlu
membuatnya menjadi satu statemen, untuk keperluan tersebut, kita dapat
mendeklarasikan variabel pada bagian klausa FROM:

1. SELECT @no := @no + 1 AS peringkat,


2. nama,
3. nilai
4. FROM (SELECT @no := 0) AS tml_table, tabel_ujian
5. ORDER BY nilai DESC

Pada query diatas, pertama tama MySQL akan menyimpan nilai variabel
@no, hal ini dikarenakan setiap kali menjalankan statemen SELECT,
pertama kali yang dieksekusi adalah klausa FROM, selanjutnya, variabel @no
tersebut di gunakan oleh klausa SELECT

Panduan Lengkap Query MySQL 357


Contoh 2: contoh selanjutnya, kita tampilkan data siswa yang memiliki
peringkat 3 s.d 5, query yang kita jalankan:

1. SELECT * FROM (
2. SELECT @no := @no + 1 AS peringkat,
3. nama,
4. nilai
5. FROM (SELECT @no := 0) AS tml_table, ujian
6. ORDER BY nilai DESC
7. ) AS tmp_table
8. WHERE peringkat BETWEEN 3 AND 5

Hasil;
+-----------+-------+-------+
| peringkat | nama | nilai |
+-----------+-------+-------+
| 3 | Delta | 81 |
| 4 | Echo | 79 |
| 5 | Bravo | 78 |
+-----------+-------+-------+

Pada query diatas, pertama tama MySQL akan menjalankan subquery,


subquery tersebut akan menghasilkan temporary table dengan bentuk
sama persis seperti pada Contoh 1, selanjutnya, saat menjalankan query
utama, MySQL akan mengambil data temporary table dengan nilai
peringkat antara ke 3 s.d 5

Contoh 3: Melanjutkan contoh sebelumnya, kali ini kita akan memberi


keterangan pada masing masing nilai, apakah nilai tersebut diatas nilai
rata-rata atau dibawah nilai rata-rata. Query yang kita jalankan:

1. SET @rata_rata := (SELECT ROUND(AVG(nilai)) FROM


tabel_ujian);
2. SELECT
3. nama,
4. nilai,
5. @rata_rata AS rata_rata,
6. CASE
7. WHEN nilai > @rata_rata
8. THEN 'Diatas rata-rata'
9. WHEN nilai = @rata_rata

358 BAB 20 Variable


10. THEN 'Sama dengan rata-rata'
11. ELSE 'Dibawah rata-rata'
12. END AS keterangan
13. FROM tabel_ujian
14. ORDER BY nilai DESC

Hasil yang kita peroleh:


+---------+-------+-----------+-----------------------+
| nama | nilai | rata_rata | keterangan |
+---------+-------+-----------+-----------------------+
| Alfa | 85 | 81 | Diatas rata-rata |
| Charlie | 83 | 81 | Diatas rata-rata |
| Delta | 81 | 81 | Sama dengan rata-rata |
| Echo | 79 | 81 | Dibawah rata-rata |
| Bravo | 77 | 81 | Dibawah rata-rata |
+---------+-------+-----------+-----------------------+

Pada contoh diatas, nilai rata-rata kita simpan terlebih dahulu pada
variabel @rata_rata, selanjutnya kita bandingkan nilai pada masing
masing baris dengan nilai pada variabel @rata_rata, hasilnya kita
masukkan ke dalam kolom keterangan.

Contoh 4: Contoh selanjutnya, misal kita akan menampilkan data


akumulasi penjualan per bulan, kali ini kita akan menggunakan tabel
sales2. Adapun isi tabel tersebut adalah sebagai berikut:
+--------+---------+------------+-----------+
| id_trx | nama | tgl_trx | nilai_trx |
+--------+---------+------------+-----------+
| 1 | Alfa | 2017-03-20 | 250000 |
| 2 | Charlie | 2017-01-10 | 175000 |
| 3 | Bravo | 2017-02-22 | 310000 |
| 4 | Bravo | 2017-02-11 | 250000 |
| 5 | Alfa | 2017-03-15 | 300000 |
+--------+---------+------------+-----------+

Selanjutnya, jalankan query berikut:

1. SELECT bulan, jml_trx, total_trx, @x:= @x + total_trx


AS akumulasi
2. FROM
3. (SELECT @x:=0) AS num,

Panduan Lengkap Query MySQL 359


4. (SELECT MONTH(tgl_trx) AS bulan,
5. COUNT(id_trx) AS jml_trx,
6. SUM(nilai_trx) AS total_trx
7. FROM sales2
8. GROUP BY MONTH(tgl_trx)
9. ) AS sales

Hasil yang kita peroleh:


+-------+---------+-----------+-----------+
| bulan | jml_trx | total_trx | akumulasi |
+-------+---------+-----------+-----------+
| 1 | 1 | 175000 | 175000 |
| 2 | 2 | 560000 | 735000 |
| 3 | 2 | 550000 | 1285000 |
+-------+---------+-----------+-----------+

Pada tabel diatas, total penjualan s.d bulan Januari adalah 175.000, s.d
bulan Februari adalah 735.000 (175.000 + 560000), dan total penjualan s.d
bulan Maret adalah 1.850.000 (175.000 + 560000 + 550000). Pada query
diatas, pertama tama MySQL akan menjalankan subquery:

1. (SELECT @x:=0) num,


2. (SELECT MONTH(tgl_trx) AS bulan,
3. COUNT(id_trx) AS jml_trx,
4. SUM(nilai_trx) AS total_trx
5. FROM sales2
6. GROUP BY MONTH(tgl_trx)
7. ) AS sales

Yang akan menghasilkan temporary tabel:


+-------+---------+-----------+
| bulan | jml_trx | total_trx |
+-------+---------+-----------+
| 1 | 1 | 175000 |
| 2 | 2 | 560000 |
| 3 | 2 | 550000 |
+-------+---------+-----------+

Selanjutnya, pada query utama, MySQL akan mengambil data kolom bulan,
jml_trx, dan total_trx, kemudian pada bagian @x:= @x + total_trx,

360 BAB 20 Variable


MySQL akan menjumlahkan secara kumulatif variabel @x dengan nilai pada
kolom total_trx.

20.5. Variable Sebagai Identifier


Variable digunakan untuk menyimpan nilai dan tidak dapat digunakan
sebagai identifier pada suatu perintah SQL (misal nama kolom, tabel atau
database). Misal kita menyimpan nama kolom tgl_trx ke dalam variabel
@tgl_trx, jalankan query berikut:

mysql> SET @tgl_trx := 'tgl_trx';


Query OK, 0 rows affected (0.00 sec)

Selanjutnya, kita jalankan query untuk menampilkan data kolom nama dan
tgl_trx pada tabel sales2

SELECT nama, @tgl_trx FROM sales2;

Hasil:
+---------+----------+
| nama | @tgl_trx |
+---------+----------+
| Alfa | tgl_trx |
| Charlie | tgl_trx |
| Bravo | tgl_trx |
| Bravo | tgl_trx |
| Alfa | tgl_trx |
+---------+----------+

Pada contoh diatas, kolom @tgl_trx akan berisi nilai dari variabel @tgl_trx
yaitu string 'tgl_trx' bukan isi dari kolom tgl_trx. Demikian juga untuk
nama tabel, jika nama tabel kita simpan pada variable, maka ketika
dijalankan akan muncul pesan error, misal:

mysql> SET @tabel := 'tabel_sales';


Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM @tabel;

Panduan Lengkap Query MySQL 361


ERROR 1064 (42000): 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 '@tabel' at line 1

Meski demikian, kita masih tetap dapat menggunakan variabel sebagai


identifier, caranya dengan mendefinisikannya secara tidak langsung
melalui query yang disimpan pada suatu variabel. Variabel yang berisi SQL
ini nantinya akan dieksekusi menggunakan prepared statemen,
pembahasan tentang hal ini dapat diikuti pada BAB 18 – Crosstab

362 BAB 20 Variable


BAB 21 Views

21.1. Memahami View


Pada database, view merupakan query berupa statemen SELECT yang
disimpan di dalam server database yang digunakan untuk menampilkan
data berupa tabel. Karena berupa query, view ini tidak memiliki data
sendiri, melainkan mengambil data dari tabel riil pada database atau dari
view lain. Tabel yang digunakan pada statemen SELECT yang ada pada view
disebut BASE TABLE, di sepanjang bab ini, kita akan sering
menggunakan istilah tersebut.

Karena hasil query dari view berupa tabel yang tidak tersimpan pada
database, maka view ini sering disebut dengan tabel virtual atau virtual
table, meski demikian, MySQL juga menganggap view ini sebagai tabel
sehingga tetap dapat terlihat ketika kita menjalankan perintah SHOW
TABLES, disamping itu, pesan error atau warning terkait view akan di di
tampilkan seperti error pada tabel umumnya.

Sebagai tambahan, view ini bersifat permanen, tidak temporal, sehingga


setelah dibuat, maka view ini akan selalu dapat digunakan sampai view
tersebut dihapus.

Jika digambarkan dalam bentuk diagram, maka view dapat digambarkan


seperti gambar berikut:

Panduan Lengkap Query MySQL 363


VIEW
C1.1 C1.3 C2.2 C3.2 C3.3

SELECT * FROM nama_view

SELECT C1.1,
C1.3,
C2.2,
C3.2,
C3.3
C1.1 C1.2 C1.3 C2.1 C2.2 C2.3 C3.1 C3.2 C3.3
FROM `Tabel 1`
LEFT JOIN `Tabel 2`
ON C1.1 = C2.1
LEFT JOIN `Tabel 3`
ON C1.1 = C3.1
WHERE C2.1 = 'AKTIF'
ORDER BY C.2.2
Tabel 2 Tabel 2 Tabel 3 LIMIT 10

BASE TABLE

Gambar 21.1 Ilustrasi Views

21.2. Kelebihan dan Kekurangan View


Salah satu alasan kenapa kita menggunakan view adalah ketika kita
memiliki satu atau beberapa tabel yang harus kita share ke user lain namun
terbatas hanya kolom tertentu saja, dengan view, kita dapat
menyembunyikan kolom tersebut atau menyamarkan nama nya, selain itu
kita juga dapat menutup akses ke tabel aslinya.

Anda mungkin bertanya, seberapa perlu kita menggunakan view.


Penggunaan View dapat memberikan berbagai keuntungan, diantaranya:

364 BAB 21 Views


1. View dapat mengurangi kompleksitas query. Jika tabel dihasilkan
dari query yang kompleks, seperti hasil dari penggabungan (join) dari
beberapa tabel, maka dengan view, kita hanya perlu memanggil tabel
hasil view dengan satu perintah SELECT, tidak perlu berkali kali
menulis perintah SQL yang kompleks.

2. View dapat digunakan untuk mengubah format data atau


membuat kolom agregasi. Karena tabel view merupakan hasil dari
perintah SQL, maka kita dapat membuat kolom baru pada tabel
tersebut dengan nilai hasil manipulasi dari kolom lain. Misal kita dapat
membuat kolom total penjualan dengan menggunakan fungsi SUM atau
mengubah format tanggal menggunakan fungsi CAST.

3. View dapat digunakan untuk mengubah nama kolom. Jika tabel


memiliki nama kolom yang kurang pas atau kita ingin
menyembunyikan nama asli kolom suatu tabel, maka dengan view, kita
dapat mengubah nama kolom tersebut untuk ditampilkan ke user.

4. View dapat membatasi data (kolom) apa saja yang akan kita
tampilkan ke user lain. Ketika membuat view, kita dapat memilih
kolom apa saja yang akan kita tampilkan pada view, sehingga dapat
menjaga agar data sensitif tidak ter ekspose ke luar. Pada MySQL,
Administrator dapat memberi akses ke user agar hanya dapat
mengakses view tidak pada tabel riil.

5. Tidak memakan tempat. Karena hanya query, bukan tabel riil, maka
tidak ada data yang disimpan oleh view, sehingga tidak memakan
tempat pada database

Meskipun terdapat kelebihan, penggunaan view memiliki beberapa


kekurangan, diantaranya:

1. Masalah performance. Karena view disusun dari query, maka


performance dari view tersebut tergantung dari query yang disimpan,
yang bisa jadi akan menurunkan performa query, terutama jika view
tersebut kompleks atau dibuat berdasarkan view lain.

2. Ketergantungan tabel. Karena view merupakan hasil query dari tabel


lain (baik tabel riil maupun view) maka ketika struktur tabel utama

Panduan Lengkap Query MySQL 365


berubah (kolom berubah), maka kita juga harus mengubah view
tersebut.

3. Index tidak dapat digunakan pada view. Meskipun hasilnya berupa


tabel, namun kita tidak bisa membuat index pada tabel yang dihasilkan
oleh view. Jika kita menggunakan algoritma merge (dibahas nanti),
MySQL akan menggunakan index dari tabel yang digunakan sebagai
referensi view, jika menggunakan algoritma temptable, maka index
tidak akan digunakan ketika view dijalankan.

21.3. Membuat View


Untuk membuat view, kita gunakan perintah CREATE VIEW, adapun format
umum untuk membuat view adalah sebagai berikut:

1. CREATE
2. VIEW nama_view
3. AS statemen_select

Statemen_select dapat mengandung JOIN, UNION, maupun Subquery.

Setelah view dibuat, maka untuk menampilkan data yang ada pada
statemen_select kita cukup memanggil nama_view tersebut, sebagai
contoh kita memiliki tabel berikut:

Tabel pelanggan
+--------------+----------+--------------------+
| id_pelanggan | nama | email |
+--------------+----------+--------------------+
| 1 | Anton | anton@gmail.com |
| 2 | Braskie | braskie@yahoo.com |
| 3 | Charlie | charlie@gmail.com |
| 4 | Deni | deni@gmail.com |
+--------------+----------+--------------------+

Tabel penjualan
+--------+--------------+------------+-----------+
| id_trx | id_pelanggan | tgl_trx | total_trx |
+--------+--------------+------------+-----------+
| 2 | 3 | 2017-03-22 | 395000 |

366 BAB 21 Views


| 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 |
+--------+--------------+------------+-----------+

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 |
+----------+--------+--------------+------------+-------------+

Tabel tersebut ada di dalam database toko_buku

Selanjutnya kita buat view untuk menampilkan semua data penjualan


beserta nama pelanggan dan tgl_retur (jika ada). Query yang kita jalankan
adalah;

1. CREATE
2. VIEW penjualan_view
3. AS SELECT id_trx,
4. nama AS nama_pelanggan,
5. tgl_trx,
total_trx,
6.
tgl_retur,
7. nilai_retur
8. FROM penjualan
9. LEFT JOIN pelanggan USING(id_pelanggan)
10. LEFT JOIN retur USING(id_trx)
11. ORDER BY tgl_trx DESC

Hal hal yang perlu diperhatikan ketika membuat view:

1. View hanya dapat digunakan untuk menjalankan satu statemen yaitu


SELECT, sehingga kita tidak bisa menggunakan statemen SET dan
SELECT dalam waktu yang sama

2. Hasil query ketika membuat view akan berbentuk tetap dan tidak
terpengaruh pada perubahan struktur tabel. Misal jika view dibuat
untuk menampilkan semua kolom SELECT * FROM penjualan, maka

Panduan Lengkap Query MySQL 367


ketika ada penambahan kolom pada tabel penjualan, maka kolom baru
tersebut tidak ikut ditampilkan, sedangkan jika terdapat pengurangan
kolom, maka akan terjadi error ketika dilakukan pemanggilan view.

3. Seperti tabel, nama view harus mengikuti aturan penamaan tabel,


disamping itu, nama view harus unik, tidak boleh sama dengan tabel
atau view yang sudah ada.

4. Banyaknya view yang dapat dibuat tidak terbatas.

5. View dapat berada di dalam view lain (Nested View). Perlu


diperhatikan bahwa karena view ini hanyalah sebuah query, maka jika
bentuknya kompleks akan berpengaruh pada performa database

6. Sebelum MySQL versi 5.7.7, klausa FROM yang ada pada statemen
SELECT tidak dapat mengandung subquery, misal: SELECT * FROM
(SELECT … ) AS temp

7. Pada statemen SELECT yang ada di dalam view, kita bisa menggunakan
klausa ORDER BY, namun, ketika kita memanggil view dengan
mendefinisikan ORDER BY tersendiri, maka ORDER BY pada view
tersebut akan diabaikan.

21.4. Memanggil View


Untuk memanggil view, kita gunakan statemen SELECT, sama seperti ketika
kita memanggil tabel riil, contoh:

SELECT * FROM nama_view

Misal kita panggil view penjualan_view, jalankan perintah berikut:

SELECT * FROM penjualan_view

Hasil yang kita peroleh:


+--------+----------------+------------+-----------+------------+-------------+
| id_trx | nama_pelanggan | tgl_trx | total_trx | tgl_retur | nilai_retur |
+--------+----------------+------------+-----------+------------+-------------+
| 2 | Charlie | 2017-03-22 | 395000 | 2017-03-29 | 175000 |

368 BAB 21 Views


| 6 | Charlie | 2017-03-07 | 256000 | NULL | NULL |
| 7 | Braskie | 2017-03-05 | 215000 | 2017-03-21 | 215000 |
| 4 | Anton | 2017-03-04 | 269000 | NULL | NULL |
| 5 | Deni | 2017-02-15 | 110000 | NULL | NULL |
| 3 | Braskie | 2017-01-10 | 360000 | NULL | NULL |
| 8 | Charlie | 2016-12-12 | 270000 | NULL | NULL |
| 9 | Charlie | 2016-12-12 | 325000 | NULL | NULL |
+--------+----------------+------------+-----------+------------+-------------+

Pada tabel diatas terlihat bahwa kolom nama pada tabel pelanggan
berubah menjadi nama_pelanggan, hal ini dikarenakan pada saat membuat
view, kita gunakan alias nama_pelanggan (nama AS nama_pelanggan)
pada kolom tersebut. Jika saat membuat view kita gunakan alias pada
kolom, maka ketika memanggil view, kita tidak dapat memanggil nama asli
dari kolom tersebut, melainkan harus menggunakan nama aliasnya, jika
tidak, akan muncul pesan error bahwa kolom tidak ditemukan: SQL Error
(1054): Unknown column 'nama' in 'field list

Seperti telah disampaikan sebelumnya bahwa view sama seperti tabel


pada umumnya, sehingga query yang dapat digunakan untuk tabel riil, juga
dapat digunakan pada view. Misal, kita akan menampilkan data order yang
hanya terdapat data returnya, query yang kita jalankan :

1. SELECT *
2. FROM penjualan_view
3. WHERE tgl_retur IS NOT NULL

Hasil:
+--------+----------------+------------+-----------+------------+-------------+
| id_trx | nama_pelanggan | tgl_trx | total_trx | tgl_retur | nilai_retur |
+--------+----------------+------------+-----------+------------+-------------+
| 2 | Charlie | 2017-03-22 | 395000 | 2017-03-29 | 175000 |
| 7 | Braskie | 2017-03-05 | 215000 | 2017-03-21 | 215000 |
+--------+----------------+------------+-----------+------------+-------------+

Kita juga dapat melakukan berbagai fungsi agregasi seperti pada tabel riil.
Misal kita buat resume data order yang sukses (order yang tidak memiliki
retur). Query yang kita jalankan:

1. SELECT nama_pelanggan,
2. COUNT(tgl_trx) AS jml_trx,
3. SUM(total_trx) AS total

Panduan Lengkap Query MySQL 369


4. FROM penjualan_view
5. WHERE tgl_retur IS NULL
6. GROUP BY nama_pelanggan
7. ORDER BY total DESC

Hasil:
+----------------+---------+--------+
| nama_pelanggan | jml_trx | total |
+----------------+---------+--------+
| Charlie | 3 | 851000 |
| Braskie | 1 | 360000 |
| Anton | 1 | 269000 |
| Deni | 1 | 110000 |
+----------------+---------+--------+

Pada contoh diatas, kita hitung banyaknya transaksi dengan menghitung


banyaknya row pada kolom total_trx menggunakan fungsi COUNT, selain
itu dengan ORDER BY, kita urutkan data berdasarkan total nilai transaksi
urut dari data yang paling besar

Perhatikan bahwa query yang disimpan pada view akan dieksekusi


setiap kali view dipanggil, sehingga pada view yang kompleks,
pemanggilan view bisa mempengaruhi performa database

21.5. Mengubah View Dengan Klausa OR


REPLACE
Ketika membuat view, kita dapat menambahkan klausa OR REPLACE.
Seperti arti replace yang berarti ganti, dengan klausa ini, jika nama view
sudah ada maka akan diganti dengan yang baru, jika belum ada, maka akan
dibuat view baru. Misal kita buat view dengan nama yang sama dengan
view yang telah kita buat sebelumnya yaitu penjualan_view, namun kali
ini kita tambahkan klausa OR REPLACE

1. CREATE
2. OR REPLACE

370 BAB 21 Views


3. VIEW penjualan_view
4. (ID, `TGL TRANSAKSI`, `NILAI TRANSAKSI`)
5. AS SELECT id_trx,
6. tgl_trx,
7. total_trx
8. FROM penjualan
9. LEFT JOIN retur USING(id_trx)
10. WHERE id_retur IS NULL

Pada contoh diatas, ketika kita panggil view penjualan_view, tabel yang
dihasilkan tidak lagi sama seperti contoh sebelumnya melainkan berubah
sesuai dengan view yang baru.

mysql> SELECT * FROM penjualan_view;


+----+---------------+-----------------+
| ID | TGL TRANSAKSI | NILAI TRANSAKSI |
+----+---------------+-----------------+
| 3 | 2017-01-10 | 360000 |
| 4 | 2017-03-04 | 269000 |
| 5 | 2017-02-15 | 110000 |
| 6 | 2017-03-07 | 256000 |
| 8 | 2016-12-12 | 270000 |
| 9 | 2016-12-12 | 325000 |
+----+---------------+-----------------+
5 rows in set (0.00 sec)

21.6. Membuat View Dengan Column List


Selain cara yang telah kita bahas sebelumnya, kita juga dapat membuat
view dengan mendefinisikan nama kolom pada baris tersendiri, kolom ini
disebut column list. Adapun format penulisannya adalah sebagai berikut:

1. CREATE
2. VIEW nama_view
3. (kolom1, kolom2, kolom2, ...)
4. AS statemen_select

Misal kita ubah view penjualan_view seperti yang telah kita buat pada
contoh sebelumnya dengan mendefinisikan nama kolom sebagai berikut:

Panduan Lengkap Query MySQL 371


1. CREATE
2. OR REPLACE
3. VIEW penjualan_view
4. (ID, `NAMA PELANGGAN`, `TGL TRANSAKSI`, `NILAI
TRANSAKSI`, `TGL RETUR`, `NILAI RETUR`)
5. AS SELECT id_trx,
6. Nama AS nama_pelanggan,
7. tgl_trx,
8. total_trx,
9. tgl_retur,
10. nilai_retur
11. FROM penjualan
12. LEFT JOIN pelanggan USING(id_pelanggan)
13. LEFT JOIN retur USING(id_trx)
14. ORDER BY tgl_trx DESC

Perhatikan bahwa pada contoh diatas, pada nama kolom yang


mengandung spasi, seperti NAMA PELANGGAN, kita menggunakan tanda
back tick (`), tidak bisa menggunakan tanda kutip satu ( ' ) maupun tanda
kutip dua ( " ).

Jika kita panggil view tersebut:

SELECT * FROM penjualan_view

Maka hasil yang kita peroleh:


+----+----------------+---------------+-----------------+------------+-------------+
| ID | NAMA PELANGGAN | TGL TRANSAKSI | NILAI TRANSAKSI | TGL RETUR | NILAI RETUR |
+----+----------------+---------------+-----------------+------------+-------------+
| 2 | Charlie | 2017-03-22 | 395000 | 2017-03-29 | 175000 |
| 6 | Charlie | 2017-03-07 | 256000 | NULL | NULL |
| 7 | Braskie | 2017-03-05 | 215000 | 2017-03-21 | 215000 |
| 4 | Anton | 2017-03-04 | 269000 | NULL | NULL |
| 5 | Deni | 2017-02-15 | 110000 | NULL | NULL |
| 3 | Braskie | 2017-01-10 | 360000 | NULL | NULL |
| 9 | Charlie | 2016-12-12 | 325000 | NULL | NULL |
| 8 | Charlie | 2016-12-12 | 270000 | NULL | NULL |
+----+----------------+---------------+-----------------+------------+-------------+

372 BAB 21 Views


21.7. Perubahan Pada Base Table
Ketika terjadi perubahan data pada base table, view juga ikut berubah. Hal
ini karena setiap view dipanggil, query pada view tersebut dijalankan,
sehingga akan menampilkan data terkini dari base table.

Jika terjadi perubahan pada struktur base tabel, misal nama kolom
berubah, maka view tidak dapat digunakan lagi, misal pada tabel
penjualan, kita ganti kolom id_pelanggan menjadi id_plg, maka ketika kita
jalankan perintah SELECT * FROM penjualan_view, maka akan muncul
pesan error:

mysql> 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 2017-
02-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. DELIMITER $
2. CREATE PROCEDURE penjualan()
3. BEGIN
4. SELECT * FROM penjualan;
5. END $
6. 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. DELIMITER $
2. DROP PROCEDURE IF EXISTS penjualan_all $
3. CREATE PROCEDURE penjualan_all()
4. BEGIN
5. SELECT * FROM penjualan;
6. END $
7. 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. DELIMITER $
2. DROP PROCEDURE IF EXISTS penjualan $
3. CREATE PROCEDURE penjualan (month INT)
4. BEGIN
5. SELECT *
6. FROM penjualan
7. WHERE MONTH(tgl_trx) = month;
8. END $
9. 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. DELIMITER $
2. DROP PROCEDURE IF EXISTS penjualan $
3. CREATE PROCEDURE penjualan (
4. bulan INT,
5. nama_pelanggan VARCHAR(255)
)
6.
BEGIN
7. SELECT id_pelanggan, nama, tgl_trx, total_trx
8. FROM penjualan
9. LEFT JOIN pelanggan USING (id_pelanggan)
10. WHERE MONTH(tgl_trx) = bulan
11. AND nama = nama_pelanggan;
12. END $
13. 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. DELIMITER $
2. DROP PROCEDURE IF EXISTS penjualan_total $
3. CREATE PROCEDURE penjualan_total(
4. bulan INT,
5. OUT total INT
BEGIN
6.
SELECT SUM(total_trx)
7. INTO total
8. FROM penjualan
9. WHERE MONTH(tgl_trx) = bulan;
10. END $
11. 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. DELIMITER $
2. DROP PROCEDURE IF EXISTS penjualan_total_jumlah $
3. CREATE PROCEDURE penjualan_total_jumlah (
4. bulan INT,
5. OUT total INT,
6. OUT jml_trx INT
7. )
8. BEGIN
9. -- total
10. SELECT SUM(nilai_trx)
11. INTO total
12. 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. DELIMITER $
2. DROP PROCEDURE IF EXISTS penjualan_total $
3. CREATE PROCEDURE penjualan_total (
4. bulan INT,
5. OUT total INT,
OUT jml_trx INT
6.
)
7. BEGIN
8. SELECT SUM(total_trx), COUNT(id_trx)
9. INTO total, jml_trx
10. FROM penjualan
11. WHERE MONTH(tgl_trx) = bulan;
12. END $
13. 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. DELIMITER $
2. DROP PROCEDURE IF EXISTS penjualan_akumulatif $
3. CREATE PROCEDURE penjualan_akumulatif (
4. INOUT total INT,
5. OUT total_asli INT
6. )
7. BEGIN
8. SET total_asli = ( SELECT SUM(total)
9. FROM penjualan
10. );
11. SET total = total + total_asli;
12. END $
13. 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. DELIMITER $
2. DROP PROCEDURE IF EXISTS harga_neto $
3. CREATE PROCEDURE harga_neto(
4. IN id INT,
5. OUT harga_neto INT
6. )
7. BEGIN
8. DECLARE nilai_diskon FLOAT;
9. SET nilai_diskon = ( SELECT diskon
10. FROM diskon
11. WHERE id_kategori = 0
12. AND expired > NOW()
13. );
14. SELECT harga - (harga * nilai_diskon)
15. INTO harga_neto
16. FROM buku
17. WHERE id_buku = id;
18. 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. DELIMITER $
2. CREATE DEFINER=`root`@`localhost` PROCEDURE `harga_neto2`(
3. IN `id` INT,
4. OUT `harga_awal` INT,
5. OUT `harga_neto` INT,
6. OUT `diskon` DECIMAL(10,2)
7.
8. )
9.
10. BEGIN
11. DECLARE kategori INT;
12. DECLARE nilai_diskon FLOAT;
13.
14. SET kategori = (SELECT id_kategori
15. FROM buku
16. WHERE id_buku = id );
17.
18. -- diskon (OUT)
19. IF kategori = 1
20. 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. DELIMITER $
2. DROP PROCEDURE IF EXISTS harga_neto2$
3. CREATE PROCEDURE harga_neto2(
4. IN id INT,
5. OUT harga_awal INT,
6. OUT harga_neto INT,
7. OUT diskon DECIMAL(10,2)
8. )
9.
10. BEGIN
11. DECLARE kategori INT;
12. DECLARE nilai_diskon FLOAT;
13.
14. SET kategori = (SELECT id_kategori
15. FROM buku
16. WHERE id_buku = id );
17.
18. -- diskon (OUT)
19. CASE kategori
20. WHEN 1 THEN SET nilai_diskon = 0.2;
21. WHEN 2 THEN SET nilai_diskon = 0.15;
22. WHEN 3 THEN SET nilai_diskon = 0.1;
23. ELSE SET nilai_diskon = 0.08;
24. END CASE;
25.
26. SET diskon = nilai_diskon;
27.
28. -- harga_awal (OUT) dan harga_neto (OUT)
29. SELECT harga, harga - (harga * diskon)
30. INTO harga_awal, harga_neto
31. FROM buku
32. WHERE id_buku = id;
33. END $
34. 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. DELIMITER $
2. DROP PROCEDURE IF EXISTS `harga_neto2` $
3. CREATE DEFINER=`root`@`localhost` PROCEDURE
4. `harga_neto2`(
5. IN `id` INT,
6. OUT `harga_awal` INT,
7. OUT `harga_neto` INT,
8. OUT `diskon` DECIMAL(10,2)
9. )
10. LANGUAGE SQL
11. NOT DETERMINISTIC
12. CONTAINS SQL
13. SQL SECURITY DEFINER
COMMENT 'Stored Procedure yang digunakan untuk
menghitung harga neto setelah dikurangi diskon'
14. BEGIN
15. ...
16. END $
17. 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. DELIMITER $
2. DROP FUNCTION IF EXISTS total_perbulan $
3. CREATE FUNCTION total_perbulan(bulan INT, tahun INT)
4. RETURNS INT
5. BEGIN
6. RETURN (SELECT SUM(total_trx)
7. FROM penjualan
8. WHERE MONTH(tgl_trx) = bulan
9. AND YEAR(tgl_trx) = tahun
10. );
11. END $
12. 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. CREATE [DEFINER] FUNCTION nama_fungsi ([parameter])


2. RETURNS tipe_data CHARSET utf8
3. COMMENT 'string'
4. LANGUAGE SQL
5. [NOT] DETERMINISTIC
6. { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL
7. DATA }
8. SQL SECURITY { DEFINER | INVOKER }
9. BEGIN
10. 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. DELIMITER $
2. DROP FUNCTION IF EXISTS status_stok $
3. CREATE FUNCTION status_stok(jml_stok INT)
4. RETURNS VARCHAR(50)
5. BEGIN
6. IF jml_stok >= 10
7. THEN RETURN ('BANYAK');
8. ELSE IF jml_stok <= 9 AND jml_stok >=3
9. THEN RETURN ('CUKUP');
10. ELSE IF jml_stok > 0 AND jml_stok <= 2
11. THEN RETURN ('SEDIKIT');
12. END IF;
13. END $
14. DELIMITER ;

Selanjutnya mari kita panggil fungsi tersebut, jalankan query berikut:

1. SELECT judul, harga, stok, status_stok(stok)


2. FROM buku

Ternyata kita mendapati error: SQL Error (1321): FUNCTION


status_stok ended without RETURN. Kenapa bisa seperti itu? Hal
tersebut dikarenakan SF tidak menemukan statemen RETURN yaitu pada
stok dengan jumlah 0, karena memang kita belum mendefinisikan
statemen RETURN untuk jumlah stok 0.

Berdasarkan contoh diatas, maka sebisa mungkin hanya menggunakan


satu statemen RETURN. Hal ini untuk menghindari error ketika statemen IF
tidak memenuhi kondisi tertentu sehingga tidak ada statemen RETURN yang
di eksekusi. Mari kita ubah kode diatas dengan hanya menggunakan satu
statemen RETURN yaitu dengan mengubah statemen RETURN yang ada pada
setiap ekspresi IF menjadi variabel:

1. DELIMITER $
2. DROP FUNCTION IF EXISTS status_stok $
3. CREATE FUNCTION status_stok(jml_stok INT)
4. RETURNS VARCHAR(50)
5. BEGIN
6.
7. SET @nama_status = "KOSONG";

414 BAB 23 Stored Function


8.
9. IF jml_stok >= 10
10. THEN SET @nama_status = "BANYAK";
11. ELSE IF jml_stok <= 9 AND jml_stok >=3
12. THEN SET @nama_status = "CUKUP";
13. ELSE IF jml_stok > 0 AND jml_stok <= 2
14. THEN SET @nama_status = "SEDIKIT";
15. END IF;
16.
17. RETURN @nama_status;
18. END $
19. DELIMITER ;

Pada contoh diatas, kita gunakan variabel @nama_status untuk


menyimpan nama status stok

TIPS: Ketika membuat stored function selalu usahakan untuk


menggunakan satu statemen RETURN pada bagian akhir kode dan
hindari penggunaan control flow yang menyebabkan tidak
dieksekusinya statemen RETURN

23.3. Menampilkan Semua Stored Function


Untuk menampilkan semua function yang ada di server database, kita
gunakan perintah:

SHOW FUNCTION STATUS

Ketika perintah tersebut kita jalankan, maka akan muncul data kurang
lebih seperti tabel berikut:
+-----------+----------------+----------+----------------+
| Db | Name | Type | Definer |
+-----------+----------------+----------+----------------+
| toko_buku | status_stok | FUNCTION | root@localhost |
| toko_buku | total_perbulan | FUNCTION | root@localhost |
+-----------+----------------+----------+----------------+

Lanjutan:

Panduan Lengkap Query MySQL 415


+---------------------+---------------------+---------------+---------+
| Modified | Created | Security_type | Comment |
+---------------------+---------------------+---------------+---------+
| 2017-03-11 20:25:59 | 2017-03-11 20:25:59 | DEFINER | |
| 2016-03-11 18:44:06 | 2017-03-11 18:44:06 | DEFINER | |
+---------------------+---------------------+---------------+---------+

Seperti query tabel pada umumnya, kita dapat memfilter data tersebut
menggunakan klausa WHERE, misal kita ingin menampilkan SF yang ada
pada database toko_buku yang mengandung kata status, maka kita
gunakan perintah:

1. SHOW FUNCTION STATUS


2. WHERE db = 'toko_buku'
3. AND name LIKE '%status%'

Untuk menampilkan detail dari suatu SF termasuk isi dari SF tersebut, kita
gunakan perintah berikut:

SHOW CREATE FUNCTION nama_function

Misal kita ingin menampilkan detail dari SF status_stok, hasil yang kita
peroleh adalah sebagai berikut:

mysql> 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 <= 9 AND jml_stok >=3
THEN SET @nama_status = 'CUKUP';
ELSE IF jml_stok > 0 AND jml_stok <= 2
THEN SET @nama_status = 'SEDIKIT';
END IF;

416 BAB 23 Stored Function


RETURN @nama_status;
END
character_set_client: utf8mb4
collation_connection: utf8mb4_general_ci
Database Collation: latin1_swedish_ci
1 row in set (0.00 sec)

Pada contoh diatas penulis mengubah sql_mode menjadi ANSI agar hasil
yang ditampilkan lebih mudah dibaca.

23.4. Mengubah Stored Function


Stored Function yang telah kita buat dapat kita ubah menggunakan
perintah ALTER, format penulisannya adalah:

ALTER FUNCTION nama_function [karakteristik...]

Namun sama seperti pada Stored Procedure, kita tidak dapat merubah
nama maupun isi dari SF, solusinya, terlebih dahulu kita hapus SF tersebut
dengan statemen DROP baru kemudian kita buat SF baru dengan nama yang
sama.

23.5. Menghapus Stored Function


Stored Function yang telah kita buat dapat kita hapus menggunakan
perintah DROP FUNCTION diikuti nama fungsi, seperti yang telah kita
lakukan pada contoh bagian pembuatan SF:

DROP FUNCTION nama_fungsi;

Kita juga dapat menambahkan nama database pada nama fungsi sebagai
berikut:

DROP FUNCTION nama_database.nama_fungsi

Jika nama database tidak didefinisikan, maka MySQL akan secara implisit
menambahkan nama database yang sedang digunakan.

Panduan Lengkap Query MySQL 417


Seperti umumnya perintah DROP, kita dapat menambahkan klausa IF
EXISTS untuk menguji apakah SF yang kita hapus ada di dalam database.

Misal:

DROP FUNCTION IF EXISTS nama_fungsi

Jika tidak menggunakan klausa IF EXISTS, maka jika SF tidak ditemukan


dalam database, query akan berhenti dan muncul pesan ERROR misal SQL
Error (1305): FUNCTION toko_buku.nama_fungsi does not exist.
Hal ini mengakibatkan query berikutnya tidak dieksekusi, untuk itu
sebaiknya gunakan selalu klausa IF EXISTS

23.6. Stored Procedure atau Stored


Function ?
Karena stored function ini mirip dengan stored procedure, dimana kita
dapat menggunakan berbagai statemen SQL termasuk statemen untuk
memanipulasi data, maka setelah membahas kedua stored routines
tersebut, mungkin Anda menjadi bingung kapan menggunakan Stored
Procedure dan kapan menggunakan Stored Function.

Ketika memilih apakah menggunakan SP atau SF, hal mendasar yang perlu
diperhatikan adalah bahwa Stored Function hanyalah fungsi seperti fungsi
MySQL pada umumnya, misal: fungsi SUM dan COUNT, sehingga perannya
hanya sebagai pelengkap dan tidak dapat berdiri sendiri, untuk
menjalankannya selalu membutuhkan statemen induk seperti SELECT,
sebaliknya, Stored Procedure, meruakan statemen yang berdiri sendiri
yang dipanggil menggunakan statemen CALL

Kesimpulannya, jika Stored Routine yang kita buat bertujuan hanya untuk
mengolah data spesifik (tanpa memanipulasi data pada database) dan hasil
pengolahan tersebut langsung dapat digunakan, maka gunakan Stored
Function, sedangkan jika Stored Routines yang kita gunakan bertujuan
untuk memanipulasi data pada tabel database (menggunakan statemen
INSERT, UPDATE, DELETE, dll), gunakan Stored Procedure.

418 BAB 23 Stored Function


BAB 24 Transaction

24.1. Memahami Transaksi


Dalam SQL, istilah Transaction mengacu pada beberapa statemen SQL yang
dieksekusi sebagai satu kesatuan, jika salah satu statemen gagal, maka
semua eksekusi statemen dibatalkan. Sebagai contoh, misal kita memiliki
kondisi sebagai berikut:

 Terdapat data daftar transaksi per buku per pelanggan yang akan
disimpan pada tabel penjualan_detail. Data tersebut merinci buku
apa saja yang dibeli oleh pelanggan.

 Setelah berhasil disimpan pada tabel penjualan_detail, selanjutnya


data tersebut kita rekap mejadi satu baris, yang hasilnya kita simpan
pada tabel penjualan.

 Terakhir, kita update stok buku yang ada pada tabel buku dengan
mengurangkan jumlah stok dengan jumlah buku yang terjual.

Dari ketiga tahapan diatas dapat kita bayang jika salah satu dari tahapan
tersebut gagal dieksekusi, maka data yang di sajikan menjadi tidak akurat.
Misal data stok buku gagal diupdate, maka pada transaksi berikutnya,
untuk buku yang seharusnya stok nya habis, buku tersebut tetap dapat
dibeli. Pada kondisi demikian maka kita harus memastikan bahwa ketiga
statemen diatas harus berhasil dieksekusi, disinilah peran Transaksi.

Dengan Transaction, jika tahap pertama dan kedua berhasil, namun tahap
ke tiga gagal, maka keseluruhan proses dapat dibatalkan dan data yang
telah di masukkan ke tabel dapat dibatalkan (ROLLBACK), jika keseluruhan
tahap berhasil maka semua data akan disimpan secara permanen
(COMMIT)

Dari contoh diatas, dapat kita simpulkan bahwa salah satu manfaat
terpenting dari transaction ini adalah untuk menjaga integritas data, yang

Panduan Lengkap Query MySQL 419


artinya kebenaran data dapat diandalkan dan konsistensi data antara tabel
yang satu dengan yang lain dapat tetap terjaga.

Lebih jauh, sistem Transaksi pada database memiliki properti ACID (ACIF
Property), yaitu: Atomic, Consistent, Durable, dan Isolated. Adapun
penjelasannya adalah sebagai berikut:

Atomic

Memastikan bahwa semua proses berhasil di eksekusi, jika ada yang gagal,
maka semua proses dibatalkan dan semua data yang telah berubah
dikembalikan ke kondisi semula, atau lebih simpelnya: semua atau tidak
sama sekali

Consistency

Data pada database tetap konsisten (sesuai dengan aturan yang


ditetapkan) setelah transaksi dilakukan. misal: jika baris suatu tabel gagal
untuk mendapatkan ID dari tabel lain maka proses akan dibatalkan karena
data pada tabel tersebut terputus, tidak dapat terhubung dengan tabel lain.

Isolation

Isolation atau isolasi berarti ketika terjadi transaksi maka data yang
sedang diakses, akan di isolir sehingga tidak bisa di akses oleh operasi lain,
untuk dapat mengakses data tersebut, harus menunggu operasi pertama
selesai.

Durability

Ketika transaksi berhasil dilakukan maka perubahan data pada database


dilakukan secara permanen, dan tidak akan hilang meskipun terjadi
gangguan baik dari sisi software maupun hardware.

24.2. Membuat Transaksi


Pada MySQL, transaksi dimulai dengan statemen START TRANSACTION,
setelah itu kita jalankan berbagai statemen lain untuk memanipulasi data,
jika semua statemen tersebut berhasil dijalankan, maka kita jalankan
statemen COMMIT agar semua perubahan menjadi permanen, atau jika ada

420 BAB 24 Transaction


salah satu yang gagal kita batalkan seluruh perubahan dengan perintah
ROLLBACK

Sebagai contoh, misal kita buat sebuah tabel dengan nama user sebagai
berikut:

CREATE TABLE user (username VARCHAR(50), UNIQUE (username))


ENGINE=InnoDB;

Tabel tersebut terdiri dari satu field bernama username yang bersifat unik,
yang artinya tidak boleh ada data username yang sama.

Selanjutnya, kita buat transaksi dan tambahkan data pada tabel tersebut.
Jalankan query berikut:

START TRANSACTION;
INSERT INTO user VALUES('alfa')
INSERT INTO user VALUES('bravo');

Sebagai catatan: kita juga dapat memulai transaksi dengan statemen BEGIN
atau BEGIN WORK, namun keduanya bukan standar SQL (tidak digunakan
oleh DBMS lain) sehingga disarankan menggunakan START TRANSACTION.

Selanjutnya, cek isi dari tabel user dengan menjalankan perintah:

SELECT * FROM user

Hasil yang kita peroleh:


+-----------+
| username |
+-----------+
| alfa |
| bravo |
+-----------+

Berikutnya, kita jalankan statemen:

ROLLBACK;

Panduan Lengkap Query MySQL 421


Cek kembali isi dari tabel user dengan menjalankan perintah

mysql> 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. DELIMITER $
2. DROP PROCEDURE IF EXISTS transaksi;
3. CREATE PROCEDURE transaksi ()
4. BEGIN
5. DECLARE sql_error BOOL DEFAULT 0;
6.
7. DECLARE EXIT HANDLER FOR SQLEXCEPTION
8. BEGIN
9. SET sql_error = 1;
10. END;
11.
12. START TRANSACTION;
13. INSERT INTO user VALUES ('nitro');
14. 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. <?php
2. $conn = mysqli_connect('localhost', 'root', '', 'tutorial_buku');
3. if (!$conn)
4. die('Gagal terhubung dengan MySQL');
5.
6. $sql_error = 0;
7.
8. mysqli_begin_transaction($conn);
9. $query = mysqli_query($conn, "INSERT INTO user VALUES ('nitro')");
10. if (!$query)
11. $sql_error = 1;
12.
13. // ERROR: duplikasi data
14. $query = mysqli_query($conn, "INSERT INTO user VALUES ('alfa')");
15. if (!$query)
16. $sql_error = 1;
17.
18. $query = mysqli_query($conn, "INSERT INTO user VALUES ('zebra')");
19. if (!$query)
20. $sql_error = 1;
21.
22. if ($sql_error) {
23. echo 'Transaksi Gagal';
24. mysqli_rollback($conn);
25. } else {
26. echo 'Transaksi Berhasil';
27. mysqli_commit($conn);
28. }
29.
30. mysqli_close($conn);

Pada script diatas, jika query berhasil, maka PHP akan mencetak output ke
browser berupa ‘Transaksi Berhasil’ kemudian menjalankan commit,
sebaliknya, jika gagal maka PHP akan mencetak output ‘Transaksi Gagal”
dan menjalankan rollback.

430 BAB 24 Transaction


24.6. Membuat Transaksi (Lanjutan)
Setelah kita paham bagaimana transaksi bekerja, selanjutnya mari kita
buat transaksi yang melibatkan beberapa tabel. Transaksi ini merupakan
implementasi dari proses transaksi penjualan yang kita bahas pada bagian
awal bab ini. Pada transaksi ini, kita akan menggunakan tiga tabel yaitu
tabel penjualan_detail, tabel penjualan, dan tabel buku. Data yang ada pada
ketiga tabel tersebut tampak seperti pada tabel dibawah ini:

Tabel: penjualan
+--------+--------------+------------+-----------+
| id_trx | id_pelanggan | tgl_trx | total_trx |
+--------+--------------+------------+-----------+
| 2 | 3 | 2017-03-22 | 395000 |
| 3 | 2 | 2017-01-10 | 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: penjualan_detail
+---------------+--------+---------+------------+--------------+--------+-------+
| id_trx_detail | id_trx | id_buku | jml_barang | harga_satuan | diskon | total |
+---------------+--------+---------+------------+--------------+--------+-------+
| 1 | 2 | 9 | 1 | 46800 | 0 | 46800 |
| 2 | 2 | 4 | 1 | 34800 | 0 | 34800 |
| 3 | 2 | 6 | 2 | 33800 | 0 | 67600 |
| 4 | 3 | 9 | 1 | 46800 | 0 | 46800 |
| 5 | 3 | 10 | 2 | 39800 | 0 | 79600 |
+---------------+--------+---------+------------+--------------+--------+-------+

Tabel: buku
mysql> SELECT id_buku, judul, harga FROM buku WHERE id_buku IN(3,6,8);
+---------+----------------------+-------+------+
| id_buku | judul | harga | stok |
+---------+----------------------+-------+------+
| 3 | MySQL Untuk Pemula | 34800 | 5 |
| 6 | Blogger untuk Pemula | 33800 | 3 |
| 8 | Jago Wordpress | 39800 | 3 |
+---------+----------------------+-------+------+
3 rows in set (0.00 sec)

Panduan Lengkap Query MySQL 431


Hubungan antar tabel seperti tampak pada gambar berikut:

Gambar 24.1 Relasi antar tabel penjualan, penjualan_detail, dan buku

Selanjutnya, kita akan memproses data penjualan dengan id_pelanggan 3


dengan rincian sebagai berikut:

 Dua buah buku MySQL Untuk Pemula dengan harga per item Rp.
34.800
 Satu buah buku Blogger Untuk Pemula dengan harga per item Rp.
33.800
 Satu buah buku Jago Wordpress dengan harga per item Rp. 39.800

Langkah yang akan kita lakukan adalah:

 Memasukkan data id_pelanggan dan tgl_trx ke tabel penjualan untuk


mendapatkan nilai id_trx baru (field id_trx auto increment)

 id_trx tersebut kita gunakan untuk memasukkan data ke tabel


penjualan_detail.

 Selanjutnya kita hitung total transaksi dan hasilnya kita masukkan ke


dalam field nilai_trx yang ada pada tabel penjualan yang id_trx nya
sama.

432 BAB 24 Transaction


 Terakhir, update stok yang ada pada tabel buku.

Jika kita gunakan stored procedure, maka query untuk transaksinya adalah
sebagai berikut:

1. DELIMITER $
2. DROP PROCEDURE IF EXISTS tambah_transaksi;
3. CREATE PROCEDURE tambah_transaksi()
4. BEGIN
5. DECLARE sql_error BOOL DEFAULT 0;
6. DECLARE id_terakhir INT;
7. DECLARE EXIT HANDLER FOR SQLEXCEPTION
8. BEGIN
9. SET sql_error = 1;
10. END;
11.
12. START TRANSACTION;
13.
14. -- Memasukkan data id_pelanggan dan tgl_trx ke penjualan
15. INSERT INTO penjualan (id_pelanggan, tgl_trx, total_trx)
16. VALUES(3, NOW(), 0);
17.
18. -- Dapatkan nilai terakhir dari id_trx
19. SET id_terakhir = LAST_INSERT_ID();
20.
21. -- Memasukkan data ke penjualan_detail
22. INSERT INTO penjualan_detail (id_trx, id_buku, jml_barang,
harga_satuan, diskon, total) VALUES
23. (id_terakhir, 3, 2, 34800, 0, 69600),
24. (id_terakhir, 6, 1, 33800, 0, 33800),
25. (id_terakhir, 8, 1, 39800, 0, 39800);
26.
27. -- Update nilai total transaksi
28. UPDATE penjualan SET total_trx = (SELECT SUM(total)
29. FROM penjualan_detail
30. WHERE id_trx = id_terakhir
31. );
32.
33. -- Update stok
34. UPDATE buku SET stok = stok - 2 WHERE id_buku = 3;
35. UPDATE buku SET stok = stok - 1 WHERE id_buku = 6;
36. UPDATE buku SET stok = stok - 1 WHERE id_buku = 8;
37.
38. IF sql_error = 0
39. THEN COMMIT;
40. ELSE
41. ROLLBACK;
42. END IF;

Panduan Lengkap Query MySQL 433


43. END $
44. DELIMITER ;

Untuk memastikan data yang masuk sudah benar, kita dapat cek data pada
masing masing tabel:

mysql> SELECT * FROM penjualan WHERE tgl_trx = DATE(NOW());


+--------+--------------+------------+-----------+
| id_trx | id_pelanggan | tgl_trx | nilai_trx |
+--------+--------------+------------+-----------+
| 10 | 3 | 2017-03-18 | 143200 |
+--------+--------------+------------+-----------+
1 row in set (0.02 sec)

mysql> SELECT * FROM penjualan_detail WHERE id_trx = 10;


+--------------+--------+-----------+------------+--------------+--------+--------+
| id_trx_detil | id_trx | id_barang | jml_barang | harga_satuan | diskon | total |
+--------------+--------+-----------+------------+--------------+--------+--------+
| 25 | 10 | 3 | 2 | 34800 | 0 | 69600 |
| 26 | 10 | 6 | 1 | 33800 | 0 | 33800 |
| 27 | 10 | 8 | 1 | 39800 | 0 | 39800 |
+--------------+--------+-----------+------------+--------------+--------+--------+
3 rows in set (0.00 sec)

mysql> SELECT id_buku, judul, stok FROM buku WHERE id_buku IN(3,6,8);
+---------+----------------------+-------+
| id_buku | judul | stok |
+---------+----------------------+-------+
| 3 | MySQL Untuk Pemula | 3 |
| 6 | Blogger untuk Pemula | 2 |
| 8 | Jago Wordpress | 2 |
+---------+----------------------+-------+
3 rows in set (0.00 sec)

Hasil diatas sudah sesuai dengan yang kita harapkan.

Dalam kondisi riil, bisa dipastikan bahwa data transaksi satu dengan yang
lain tidak akan sama, sehingga kita harus mengubah stored procedure
setiap kali ada transaksi, yaitu dengan cara menghapus ( DROP) dan
membuatnya lagi (CREATE PROCEDURE). Untuk itu, seperti yang telah kita
bahas, lebih praktis kita buat transaksi pada level aplikasi. Penerapan
transaksi diatas pada PHP:

1. <?php
2. $conn = mysqli_connect('localhost', 'root', '', 'toko_buku');
3. if (!$conn)
4. die('Gagal terhubung dengan MySQL: ' . mysqli_error($conn));
5.

434 BAB 24 Transaction


6. $sql_error = '';
7.
8. // Mulai transaksi
9. mysqli_begin_transaction($conn);
10.
11. // Masukkan id_pelanggan dan tgl_trx ke tabel penjualan
12. $query = mysqli_query($conn, "INSERT INTO penjualan (id_pelanggan,
tgl_trx, total_trx) VALUES (3, NOW(), 0)");
13.
14. if (!$query)
15. $sql_error .= 'ERROR : ' . mysqli_error($conn) . '<br/>';
16.
17. // Dapatkan id terakhir
18. $id_terakhir = mysqli_insert_id($conn);
19.
20. // Masukkan data ke tabel transaksi_detail
21. $query = mysqli_query($conn, "INSERT INTO penjualan_detail (id_trx,
id_buku, jml_barang, harga_satuan, diskon, total) VALUES
22. ($id_terakhir, 3, 2, 34800, 0, 69600),
23. ($id_terakhir, 6, 1, 33800, 0, 33800),
24. ($id_terakhir, 8, 1, 39800, 0, 39800);");
25.
26. if (!$query)
27. $sql_error .= 'ERROR : ' . mysqli_error($conn) . '<br/>';
28.
29. // Update field nilai_trx pada tabel penjualan
30. $query = mysqli_query($conn, "UPDATE penjualan SET total_trx =
31. ( SELECT SUM(total)
32. FROM penjualan_detail
33. WHERE id_trx = $id_terakhir
34. )"
35. );
36. if (!$query)
37. $sql_error .= 'ERROR : ' . mysqli_error($conn) . '<br/>';
38.
39. // Update stok pada tabel barang
40. $stok = array(3 => 2, 6 => 1, 8 => 1);
41. foreach ($stok as $id_barang => $terjual)
42. {
43. $query = mysqli_query($conn, "UPDATE buku
44. SET stok = stok - $terjual
45. WHERE id_buku = $id_barang"
46. );
47. if (!$query)
48. $sql_error .= 'ERROR : ' . mysqli_error($conn) . '<br/>';
49. }
50.
51. if ($sql_error) {
52. echo $sql_error;

Panduan Lengkap Query MySQL 435


53. mysqli_rollback($conn);
54. } else {
55. echo 'Transaksi Berhasil';
56. mysqli_commit($conn);
57. }
58.
59. mysqli_close($conn);

Pada contoh diatas, setiap error yang terjadi kita simpan pada variabel
$sql_error, sehingga jika transaksi gagal, kita tahu query yang
menyebabkan error, sehingga mudah diperbaiki. Perhatikan pada baris 41,
kita gunakan loop untuk mengupdate data stok, cara ini lebih praktis
daripada menulis query satu per satu.

24.7. Store Engine Yang Digunakan


Ketika membuat transaksi database, maka tabel yang terlibat dalam
transaksi tersebut harus memiliki store engine InnoDB, karena hanya store
engine tersebut yang mendukung transaksi, dengan berbagai fitur pada
storage engine tersebut, maka ACID property dapat terwujud dengan baik.

Untuk melihat storage engine yang tersedia dan fitur yang didukung, kita
dapat menggunakan perintah

SHOW ENGINES

atau

SELECT * FROM INFORMATION_SCHEMA.ENGINES

Hasil yang kita peroleh:


+--------------------+---------+-----------+--------------+------+------------+
| Engine | Support | Comment | Transactions | XA | Savepoints |
+--------------------+---------+-----------+--------------+------+------------+
| FEDERATED | NO | Federated | NULL | NULL | NULL |
| MRG_MYISAM | YES | Collection| NO | NO | NO |
| MyISAM | YES | MyISAM sto| NO | NO | NO |
| BLACKHOLE | YES | /dev/null | NO | NO | NO |
| CSV | YES | CSV storag| NO | NO | NO |
| MEMORY | YES | Hash based| NO | NO | NO |
| ARCHIVE | YES | Archive st| NO | NO | NO |

436 BAB 24 Transaction


| InnoDB | DEFAULT | Supports t| YES | YES | YES |
| PERFORMANCE_SCHEMA | YES | Performanc| NO | NO | NO |
+--------------------+---------+-----------+--------------+------+------------+

Pada tabel diatas, terlihat bahwa hanya Engine InnoDB yang mendukung
transaksi. Untuk dapat langsung memperoleh tabe yang mendukung
transaksi, kita dapat menambahkan klausa WHERE sebagai berikut:

SELECT * FROM INFORMATION_SCHEMA.ENGINES


WHERE TRANSACTIONS = 'YES'

24.8. Isolasi Transaksi


MySQL adalah database yang memiliki sistem multi user, artinya banyak
pengguna dapat menggunakan database yang sama dan tabel yang sama,
baik membaca atau menulis data. Ketika user menjalankan transaksi yang
sama, maka pada kondisi tertentu, user tertentu perlu mengetahui
perubahan data yang dilakukan oleh user lain yang menjalankan transaksi
namun belum di commit.

InnoDB menerapkan berbagai model isolasi transaksi yang


memungkinkan pengguna untuk melihat perubahan yang dilakukan oleh
user lain yang melakukan transaksi, meskipun perubahan tersebut belum
di commit dan mungkin bisa jadi di rollback.

Jenis masalah yang timbul terkait transaksi:

 Dirty reads. Level ini memungkinkan user tertentu melihat perubahan


yang dilakukan oleh user lain yang melakukan transaksi, meskipun
perubahan tersebut belum di commit dan masih terdapat
kemungkinan di rollback.

 Nonrepeatable reads. Artinya transaksi tidak memberikan hasil yang


sama setiap kali dijalankan statemen SELECT. Hal ini terjadi karena
transaksi lain telah mengubah baris pada tabel.

 Phantom rows. Phantom rows berarti munculnya baris baru yang


sebelumnya tidak ada. Misal suatu transaksi mengeksekusi statemen
SELECT sedangkan transaksi lain menambahkan baris pada tabel. Jika

Panduan Lengkap Query MySQL 437


transaksi pertama menjalankan statemen SELECT lagi maka akan
tampak baris baru.

Untuk mengatasi permasalahan tersebut diatas, MySQL menyediakan 4


level isolasi transaksi. Level ini mengatur kriteria perubahan (yang
dilakukan oleh suatu transaksi) yang dapat dilihat oleh transaksi lain.

 READ UNCOMMITTED yang berarti bahwa transaksi dapat melihat


perubahan yang dilakukan oleh transaksi lain meskipun belum di
lakukan commit.

 READ COMMITTED yang berarti bahwa transaksi dapat melihat


perubahan yang dilakukan oleh transaksi lain hanya jika telah
dilakukan commit.

 REPEATABLE READ. Jika suatu transaksi menjalankan statemen


SELECT dua kali, maka hasil yang diperoleh akan sama, meskipun
transaksi lain telah melakukan perubahan data. Level ini merupakan
level isolasi default yang digunakan MySQL

 SERIALIZABLE. Baris yang sedang digunakan oleh suatu transaksi


tidak dapat diubah oleh transaksi lain hingga transaksi yang
menggunakan baris tersebut selesai. Hal ini memungkinkan transaksi
untuk membaca baris suatu tabel dan disaat yang sama mencegah
transaksi lain mengubah data pada baris tersebut.

Tabel berikut ini menggambarkan tiap level isolasi terkait dengan masalah
dirty reads, nonrepeatable reads, dan phantom rows.

Dirty Nonrepeatable Phantom


Level Isolasi
Reads Reads Rows
READ UNCOMMITED YA YA YA
READ COMMITED TIDAK YA YA

REPEATABLE READ TIDAK TIDAK TIDAK

SERIALIZEABLE TIDAK TIDAK TIDAK

Tabel 24.1. Jenis Isolasi Transaksi

438 BAB 24 Transaction


Secara default, MySQL menerapkan level isolasi REPEATABLE READ. Mode
ini dapat diubah dengan menggunakan statemen SET TRANSACTION, yang
dapat diterapkan di tiga tempat sebagai berikut:

SET GLOBAL TRANSACTION ISOLATION LEVEL level_transaksi


SET SESSION TRANSACTION ISOLATION LEVEL level_transaksi
SET TRANSACTION ISOLATION LEVEL level_transaksi

Penjelasan:

 Dengan keyword GLOBAL, maka default level isolasi diterapkan pada


sesi berikutnya, sesi yang sedang berjalan tidak terpengaruh.

 Dengan keyword SESSION, maka level isolasi akan diterapkan pada


transaksi berikutnya pada sesi yang sama.

 Tanpa keyword GLOBAL dan SESSION, maka level isolasi akan


diterapkan pada satu transaksi berikutnya, misal:

1. SET TRANSACTION ISOLATION LEVEL SERIALIZEABLE;


2. START TRANSACTION;
3. INSERT INTO tabel VALUES(nilai1, nilai2, nilai3);

Level SERIALIZEABLE hanya berlaku pada transaksi pada baris 2,


hingga transaksi tersebut selesai

Client yang memiliki privilege SUPER dapat mengatur level isolasi GLOBAL
(bentuk pertama) yang akan secara default diterapkan pada setiap client.
Namun demikian, setiap client dapat mengatur level isolasi sendiri baik
pada SESSION (bentuk kedua) atau spesifik pada transaksi tertentu
(bentuk ke tiga), tidak perlu hak akses khusus untuk mengatur level
transaksi.

Untuk mengubah level isolasi secara GLOBAL dapat dilakukan


menggunakan dua cara yaitu:

 Menggunakan command line, --transaction-isolation=level,


penamaan level disini menggunakan dash (-) bukan spasi, sehingga

Panduan Lengkap Query MySQL 439


misal untuk level REPEATABLE READ, ditulis REPEATABLE-READ,
contoh: --transaction-isolation=REPEATABLE-READ

 Mengubah seting pada file konfigurasi MySQL, yang biasanya bernama


my.ini, yang terletak pada folder mysql/bin. Pada bagian mysqld,
tambahkan baris berikut:

transaction-isolation = REPEATABLE-READ

 Mendefinisikan saat runtime menggunakan statemen SET, misal:

SET GLOBAL tx_isolation='REPEATABLE-READ';

SET SESSION tx_isolation='SERIALIZABLE';

Untuk mengecek level isolasi yang sedang digunakan bisa menggunakan


variabel tx_isolation dengan format:

SELECT @@GLOBAL.tx_isolation, @@tx_isolation;

Misal:

mysql> SELECT @@GLOBAL.tx_isolation, @@tx_isolation;


+-----------------------+-----------------+
| @@GLOBAL.tx_isolation | @@tx_isolation |
+-----------------------+-----------------+
| REPEATABLE-READ | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.03 sec

Dari contoh diatas diketahui bahwa level isolasi yang digunakan adalah
REPEATABLE READ.

440 BAB 24 Transaction


BAB 25 Trigger

Trigger, seperti terjemahannya yaitu pemicu adalah sekumpulan statemen


SQL baik prosedural atau deklarasi, yang melekat pada suatu tabel, yang
akan dieksekusi jika terdapat perubahan data pada tabel tersebut.

Trigger mirip dengan stored procedure dimana di dalamnya dapat


dijalankan berbagai statemen SQL seperti CREATE, INSERT, UPDATE, IF-
ELSEIF-ELSE, dll, bedanya, trigger dijalankan otomatis oleh MySQL,
sedangkan Stored Procedure dipanggil secara manual menggunakan
statemen CALL.

Kapan MySQL menjalankan trigger? MySQL menjalankan trigger hanya jika


terjadi operasi data pada tabel yaitu: (1) penambahan baris pada tabel
(INSERT), (2) pembaharuan data (UPDATE), dan (3) penghapusan baris
(DELETE). Trigger dapat di jalankan baik sebelum atau sesudah ketiga
operasi tersebut.

25.1. Membuat Trigger


Untuk membuat trigger kita gunakan statemen CREATE TRIGGER dengan
format sebagai berikut:

1. CREATE
2. TRIGGER nama_trigger
3. {BEFORE | AFTER}
4. {INSERT | UPDATE | DELETE}
5. ON nama_tabel
6. FOR EACH ROW
7. statemen

Penjelasan:

 nama_trigger. Nama trigger mengikuti aturan penamaan objek


database. Penamaan trigger sangat disarankan menggunakan pola
sesuai fungsi trigger tersebut. Satu trigger hanya diperbolehkan

Panduan Lengkap Query MySQL 441


menggunakan salah satu dari opsi BEFORE dan AFTER dan salah satu
dari opsi INSERT, UPDATE, dan DELETE (misal BEFORE UPDATE saja atau
AFTER INSERT saja), nama trigger sebaiknya disertai dengan opsi yang
digunakan, misal nama_trigger_before_update atau cukup
nama_trigger_bu.

Sebagai tambahan, dalam satu database (schema), tidak boleh ada


nama trigger yang sama.

 BEFORE atau AFTER. Merupakan trigger_time yang menentukan kapan


trigger akan dijalankan, apakah sebelum DML (INSERT, UPDATE,
DELETE) atau sesudah DML dieksekusi.

 INSERT | UPDATE | DELETE. Merupakan trigger_event yang menentukan


DML yang akan diterapkan pada trigger.

 ON nama_tabel. Mendefinisikan nama tabel yang akan dikenai event,


artinya jika terjadi perubahan data pada tabel tersebut, trigger akan
dijalankan.

 FOR EACH ROW. Artinya trigger akan dijalankan pada setiap baris yang
dikenai operasi DML. Standar ANSI menggunakan klausa FOR EACH
STATEMEN, yang hingga saat ini belum disupport oleh MySQL.

 statemen. Merupakan statemen yang akan dieksekusi ketika trigger


dijalankan, jika statemen terdiri dari lebih dari satu baris, maka
gunakan compound statemen (statemen yang diawali dengan BEGIN
dan diakhiri dengan END ).

Keyword INSERT, UPDATE, atau DELETE menentukan kapan trigger akan


diaktifkan, perbedaan ketiganya adalah:

 INSERT berarti trigger akan aktif jika ada data ditambahkan pada tabel,
yang biasanya dilakukan melalui statemen INSERT. Selain itu, trigger
ini juga aktif pada implisit INSERT, seperti pada statemen LOAD DATA
dan REPLACE, dimana pada kedua statemen tersebut, MySQL di
belakang layar akan menjalankan statemen INSERT

 UPDATE berarti trigger akan aktif ketika ada perubahan data pada tabel
yang dilakukan melalui statemen UPDATE.

442 BAB 25 Trigger


 DELETE berarti trigger akan aktif ketika ada baris yang dihapus misal
pada statemen DELETE atau REPLACE. Khusus untuk statemen REPLACE,
jika statemen tersebut perlu untuk menghapus data, maka trigger ini
akan aktif. Statemen DROP TABLE dan TRUNCATE TABLE tidak
mengaktifkan trigger ini, karena tidak mengandung implisit DELETE.

 Sebagai tambahan, perubahan data terkait foreign key ( ON DELETE


CASCADE dan ON UPDATE CASCADE) tidak mengaktifkan trigger.

Sebagai contoh, kita akan membuat trigger dengan melibatkan tabel buku,
tabel penjualan_detail, dan tabel penjualan seperti yang kita gunakan
pada bab bab sebelumnya:

Tabel buku:

mysql> SELECT id_buku, id_kategori, judul, harga, stok FROM buku LIMIT 5;
+---------+-------------+-----------------------------------------+-------+------+
| id_buku | id_kategori | judul | harga | stok |
+---------+-------------+-----------------------------------------+-------+------+
| 1 | 3 | Pemrograman Database Menggunakan MySQL | 59000 | 5 |
| 2 | 2 | PHP dan MySQL Langkah Demi Langkah + CD | 75000 | 6 |
| 3 | 3 | MySQL Untuk Pemula | 34800 | 4 |
| 4 | 2 | Kumpulan Aplikasi PHP untuk Pemula | 34800 | 3 |
| 5 | 2 | Pemrograman PHP Dan MySQL Untuk Pemula | 69000 | 2 |
+---------+-------------+-----------------------------------------+-------+------+
5 rows in set (0.00 sec)

Tabel penjualan_detail:

mysql> SELECT * FROM penjualan_detail LIMIT 5;


+---------------+--------+---------+------------+--------------+--------+-------+
| id_trx_detail | id_trx | id_buku | jml_barang | harga_satuan | diskon | total |
+---------------+--------+---------+------------+--------------+--------+-------+
| 1 | 2 | 9 | 1 | 46800 | 0 | 46800 |
| 2 | 2 | 4 | 1 | 34800 | 0 | 34800 |
| 3 | 2 | 6 | 2 | 33800 | 0 | 67600 |
| 4 | 3 | 9 | 1 | 46800 | 0 | 46800 |
| 5 | 3 | 10 | 2 | 39800 | 0 | 79600 |
+---------------+--------+---------+------------+--------------+--------+-------+
5 rows in set (0.02 sec)

Tabel penjualan:

Panduan Lengkap Query MySQL 443


mysql> SELECT * FROM penjualan;
+--------+--------------+------------+-----------+
| id_trx | id_pelanggan | tgl_trx | total_trx |
+--------+--------------+------------+-----------+
| 2 | 3 | 2017-03-22 | 395000 |
| 3 | 2 | 2017-01-10 | 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 |
+--------+--------------+------------+-----------+
8 rows in set (0.00 sec)

Selanjutnya, kita akan membuat trigger yang akan mengubah data sebelum
data tersebut dimasukkan ke dalam tabel, dimana kita akan memberikan
diskon sebesar 10% untuk setiap penjualan buku dengan kategori 3,
trigger yang kita buat:

1. DELIMITER $
2. DROP TRIGGER IF EXISTS harga_diskon_bi$
3.
4. CREATE TRIGGER harga_diskon_bi
5. BEFORE INSERT ON penjualan_detail
6. FOR EACH ROW
7. BEGIN
8. DECLARE kategori INT;
9. SET kategori = (
10. SELECT id_kategori
11. FROM buku
12. WHERE id_buku = NEW.id_buku
13. );
14. IF kategori = 3 THEN
15. SET NEW.diskon = 0.1;
16. SET NEW.total = NEW.harga_satuan
17. - (NEW.harga_satuan*0.1);
18. END IF;
19. END $
20. DELIMITER ;

Seperti pada Stored Procedure atau Stored Function, karena pada


compound statemen kita menggunakan delimiter titik koma ( ; ), maka agar
tidak bentrok, kita ubah delimiter menjadi dollar ( $ ).

444 BAB 25 Trigger


Pada trigger diatas, kita gunakan keyword INSERT sehingga trigger akan
aktif ketika ada penambahan data pada tabel. Penjelasan statemen:

 Pertama kita cari id_kategori berdasarkan id_buku yang akan


dimasukkan, hasilnya kita simpan pada variabel kategori (baris 9),

 Selanjutnya, pada statemen IF, jika nilai kategori = 3, maka kita ubah
nilai pada kolom diskon menjadi 0.1 (10%) dan nilai pada kolom total
menjadi nilai setelah diskon.

Mari kita tes dengan memasukkan nilai berikut:

INSERT INTO penjualan_detail (id_trx, id_buku, jml_barang,


harga_satuan, diskon, total) VALUES(7, 1, 1, 59000, 0, 59000);

Perintah tersebut akan mengaktifkan trigger karena pada tabel buku, buku
dengan id_buku 1 termasuk ke dalam kategori 3, maka nilai diskon dan
total akan berubah. Jika kita buka tabel penjualan_detail, maka hasil
yang kita peroleh adalah:

mysql> SELECT * FROM penjualan_detail WHERE id_trx = 7 ORDER BY id_trx_detail


DESC;
+---------------+--------+---------+------------+--------------+--------+-------+
| id_trx_detail | id_trx | id_buku | jml_barang | harga_satuan | diskon | total |
+---------------+--------+---------+------------+--------------+--------+-------+
| 25 | 7 | 1 | 1 | 59000 | 0.1 | 53100 |
| 13 | 7 | 10 | 1 | 39800 | 0 | 39800 |
| 12 | 7 | 5 | 1 | 69000 | 0 | 69000 |
| 11 | 7 | 7 | 1 | 49800 | 0 | 49800 |
+---------------+--------+---------+------------+--------------+--------+-------+
4 rows in set (0.00 sec)

Pada tabel diatas terlihat bahwa meskipun kita memasukkan data diskon
0 dan total 59000, data tersebut akan diubah menjadi 0,1 (besaran diskon)
untuk diskon dan 53100 (59000 – 5900) untuk total.

Pada query diatas, terdapat keyword NEW yaitu pada NEW.diskon,


NEW.total, dan NEW.harga_satuan. Selain keyword NEW, terdapat
keyword OLD, perbedaannya, NEW merujuk pada data yang baru, sedangkan
OLD merujuk pada data lama, penerapan pada DML adalah:

Panduan Lengkap Query MySQL 445


 Pada statemen INSERT, karena hanya ada data baru, maka keyword
OLD tidak berfungsi.

 Pada statemen UPDATE, keyword OLD merujuk ke data lama yang akan
diupdate, sedangkan keyword NEW merujuk data baru yang
menggantikan data lama.

 Pada statemen DELETE, karena tidak ada data baru, maka hanya
digunakan keyword OLD yang merujuk ke data lama yang akan dihapus.

Selanjutnya mari kita sempurnakan trigger diatas dengan menambahkan


statemen untuk mengupdate data kolom total_trx yang ada pada tabel
penjualan, sehingga jika ada data yang ditambahkan pada tabel
penjualan_detail, maka total transaksi yang ada pada tabel penjualan
juga ikut berubah, dengan demikian integritas data tetap terjaga.

1. DELIMITER $
2. DROP TRIGGER IF EXISTS penjualan_detail_ai $
3.
4. CREATE TRIGGER penjualan_detail_ai
5. AFTER INSERT ON penjualan_detail
6. FOR EACH ROW
7. BEGIN
8. DECLARE total_transaksi INT;
9. SET total_transaksi = ( SELECT SUM(total)
10. FROM penjualan_detail
11. WHERE id_trx = NEW.id_trx
12. );
13.
14. UPDATE penjualan SET total_trx = total_transaksi
15. WHERE id_trx = NEW.id_trx;
16. END $
17. DELIMITER ;

Jika sebelumnya kita menggunakan klausa BEFORE INSERT, pada query


diatas kita menggunakan AFTER INSERT yang artinya trigger dijalankan
jika ada data yang dimasukkan (INSERT) ke dalam tabel. Selanjutnya mari
kita coba untuk memasukkan data berikut:

446 BAB 25 Trigger


INSERT INTO penjualan_detail (id_trx, id_buku, jml_barang,
harga_satuan, diskon, total)
VALUES(7, 6, 1, 33800, 0, 33800);

Data pada tabel penjualan_detail:

mysql> SELECT * FROM penjualan_detail WHERE id_trx = 7 ORDER BY id_trx_detail


DESC;
+---------------+--------+---------+------------+--------------+--------+-------+
| id_trx_detail | id_trx | id_buku | jml_barang | harga_satuan | diskon | total |
+---------------+--------+---------+------------+--------------+--------+-------+
| 26 | 7 | 6 | 1 | 33800 | 0 | 33800 |
| 25 | 7 | 1 | 1 | 59000 | 0.1 | 53100 |
| 13 | 7 | 10 | 1 | 39800 | 0 | 39800 |
| 12 | 7 | 5 | 1 | 69000 | 0 | 69000 |
| 11 | 7 | 7 | 1 | 49800 | 0 | 49800 |
+---------------+--------+---------+------------+--------------+--------+-------+
5 rows in set (0.00 sec)

Selanjutnya kita cek data yang ada pada tabel penjualan:

mysql> SELECT * FROM penjualan WHERE id_trx = 7;


+--------+--------------+------------+-----------+
| id_trx | id_pelanggan | tgl_trx | total_trx |
+--------+--------------+------------+-----------+
| 7 | 2 | 2017-03-05 | 245500 |
+--------+--------------+------------+-----------+
1 row in set (0.01 sec)

Pada tabel diatas terlihat bahwa nilai total_trx berubah sesuai dengan
jumlah total penjualan dengan id_trx 7 yang ada pada tabel
penjualan_detail

Selanjutnya, masih terkait dengan integritas data, kita juga perlu


mengupdate nilai total_trx jika ada perubahan data pada tabel
penjualan_detail, trigger yang kita buat:

1. DELIMITER $
2. DROP TRIGGER IF EXISTS penjualan_detail_au $
3.
4. CREATE TRIGGER penjualan_detail_au
5. AFTER UPDATE ON penjualan_detail
6. FOR EACH ROW

Panduan Lengkap Query MySQL 447


7. BEGIN
8. DECLARE old_total_transaksi INT;
9. DECLARE new_total_transaksi INT;
10.
11. SET old_total_transaksi = ( SELECT SUM(total)
12. FROM penjualan_detail
13. WHERE id_trx = OLD.id_trx
14. );
15.
16. SET new_total_transaksi = ( SELECT SUM(total)
17. FROM penjualan_detail
18. WHERE id_trx = NEW.id_trx
19. );
20.
21. UPDATE penjualan SET total_trx = old_total_transaksi
22. WHERE id_trx = OLD.id_trx;
23.
24. UPDATE penjualan SET total_trx = new_total_transaksi
25. WHERE id_trx = NEW.id_trx;
26. END $
27. DELIMITER ;

Pada query diatas kita menggunakan keyword OLD dan NEW karena jika
terjadi perubahan data pada tabel penjualan_detail, field id_trx maka
kita harus mengubah data total_trx pada tabel penjualan, baik untuk
id_trx lama (karena data berurang) dan id_trx baru (karena data
bertambah)

Misal pada data sebelumnya kita ubah data pada tabel penjualan_detail
dengan id_trx_detail 25 dari id_trx dari 7 menjadi 8

UPDATE penjualan_detail SET id_trx = 8 WHERE id_trx_detail = 25

Selanjutnya mari kita cek data yang ada pada tabel penjualan:

mysql> SELECT * FROM penjualan WHERE id_trx = 7 OR id_trx = 8;


+--------+--------------+------------+-----------+
| id_trx | id_pelanggan | tgl_trx | total_trx |
+--------+--------------+------------+-----------+
| 7 | 2 | 2017-03-05 | 192400 |
| 8 | 3 | 2016-12-12 | 251500 |

448 BAB 25 Trigger


+--------+--------------+------------+-----------+
2 rows in set (0.00 sec)

Dari data tersebut terlihat bahwa data total_trx pada id_trx 7 dan 8 telah
berubah sesuai dengan perubahan yang ada pada tabel
penjualan_detail.

25.2. Multiple Trigger


Pada tabel yang sama, kita dapat membuat trigger lebih dari satu seperti
yang kita lakukan pada contoh sebelumnya, dimana kita membuat
beberapa trigger pada tabel penjualan_detail, namun, pada MySQL versi
5.7.1 dan sebelumnya, kita tidak bisa membuat trigger dengan trigger_time
dan trigger_event yang sama, misal kita tidak bisa membuat dua trigger
yang sama-sama menggunakan BEFORE INSERT, jika tidak, maka akan
muncul error:

SQL Error (1235): This version of MySQL doesn't yet support


'multiple triggers with the same action time and event for
one table

Mulai versi 5.7.2, keterbatasan tersebut sudah dihilangkan, kita dapat


membuat trigger dengan trigger_time dan trigger_event yang sama dalam
satu databaase. Trigger tersebut (secara default) akan akan dijalankan
sesuai dengan urutan pembuatannya, namun demikian, kita tetap dapat
menentukan trigger mana yang akan dieksekusi terlebih dahulu, yaitu
dengan menambahkan klausa FOLLOWS atau PRECEDES diikuti dengan
nama trigger, klausa tersebut diletakkan setelah klausa FOR EACH ROW.

Klausa FOLLOWS akan membuat trigger di eksekusi setelah trigger yang


mengikuti klausa tersebut dieksekusi, sedangkan klausa PRECEDES berlaku
sebaliknya. Misal, pada trigger penjualan_detail_au, kita jalankan
terlebih dahulu trigger penjualan_detail_au2 yang akan mengecek jika
id_trx berubah dan data transaksi dengan id_trx tersebut habis, maka kita
hapus data pada tabel penjualan yang memiliki id_trx yang sama.

Panduan Lengkap Query MySQL 449


1. DELIMITER $
2. DROP TRIGGER IF EXISTS penjualan_detail_au2$
3.
4. CREATE TRIGGER penjualan_detail_au2
5. AFTER UPDATE ON penjualan_detail
6. FOR EACH ROW PRECEDES penjualan_detail_au
7. BEGIN
8. DECLARE jumlah_trx INT;
9. SET jumlah_trx = (SELECT COUNT(id_trx)
10. FROM penjualan_detail
11. WHERE id_trx = OLD.id_trx
12. );
13. IF jumlah_trx = 0 THEN
14. DELETE FROM penjualan WHERE id_trx =
OLD.id_trx;
15. END IF;
16. END $
17. DELIMITER ;

Pada query diatas, jika kita ubah data pada tabel penjualan_detail dari
id_trx 1 menjadi 2, maka data pada tabel penjualan yang memiliki id_trx
1 akan ikut terhapus, hal ini karena pada tabel penjualan_detail tidak
ada lagi data dengan id_trx 1.

Misal kita jalankan query berikut:

UPDATE penjualan_detail SET id_trx = 2 WHERE id_trx = 1

Maka jika kita cek pada tabel penjualan, data dengan id_trx 1 akan hilang

mysql> SELECT * FROM penjualan WHERE id_trx = 1;


Empty set (0.00 sec)

25.3. Error Pada Trigger


Sama seperti stored routines lainnya, yaitu Stored Procedure dan Stored
Function, jika terdapat error pada bagian statemen trigger maka semua
perubahan yang telah terjadi akan dibatalkan. Misal kita buat trigger
sebagai berikut:

450 BAB 25 Trigger


1. CREATE TRIGGER penjualan_detail_ai_tes
2. AFTER INSERT ON penjualan_detail
3. FOR EACH ROW
4. BEGIN
5. INSERT INTO penjualan (id_pelanggan, tgl_trx,
6. total_trx)
7. VALUES ( 3, "2017-04-12", 150000);
8.
9. UPDATE penjualan SET total_trd = total_transaksi;
10. END

Trigger tersebut akan aktif ketika kita memasukkan data ke tabel


penjualan_detail. Setelah data berhasil masuk, trigger akan (1)
memasukkan data ke tabel penjualan kemudian (2) mengupdate data
total_trx pada tabel penjualan sesuai dengan id_trx yang dimasukkan
pada tabel penjualan_detail.

Mari kita tes dengan memasukkan data pada tabel penjualan_detail:

mysql> INSERT INTO penjualan_detail (id_trx, id_buku,


jml_barang, harga_satuan, diskon, total)
-> VALUES(3, 6, 1, 33800, 0, 33800);
ERROR 1054 (42S22): Unknown column 'total_trd' in 'field
list'

Pada contoh terebut terdapat error dimana kolom total_trd tidak


ditemukan (seharusnya kolom total_trx) karena error, tidak ada data
yang masuk ke dalam tabel penjualan_detail maupun tabel penjualan.

25.4. Integrity Constrain Dengan Trigger


Pada tabel penjualan_detail dan tabel penjualan terdapat referential
integrity constrain dimana nilai id_trx pada tabel penjualan_detail
harus ada pada tabel penjualan disamping itu, kita buat kolom id_trx
pada tabel penjualan_detail menjadi foreign key bagi kolom id_trx
yang ada pada tabel penjualan, selain itu, kita atur jika data pada tabel
penjualan ada yang dihapus, maka data pada tabel penjualan_detail
yang memiliki id_trx sama juga akan ikut terhapus, dengan demikian
integritas data tetap terjaga.

Panduan Lengkap Query MySQL 451


Namun demikian, tidak semua integritas data bisa terjaga menggunakan
constrain foreign key, misal, jika data pada tabel penjualan_detail
dengan id_trx tertentu dihapus semua, maka data pada tabel penjualan
yang memiliki id_trx sama akan tetap ada, sehingga data menjadi tidak
relevan.

Sebagai contoh, jika pada tabel penjualan_detail, kita hapus semua data
yang memiliki id_trx 7, maka data pada tabel penjualan yang memiliki
id_trx 7 menjadi tidak relevan karena detail datanya sudah tidak ada, untuk
itu, agar integritas data tetap terjaga, kita perlu membuat trigger untuk
menghapus data pada tabel penjualan tersebut.

1. DELIMITER $
2. DROP TRIGGER IF EXISTS penjualan_detail_ad $
3. CREATE TRIGGER penjualan_detail_ad
4. AFTER DELETE ON penjualan_detail
5. FOR EACH ROW
6. BEGIN
7. DECLARE jumlah_trx INT;
8. SET jumlah_trx = ( SELECT COUNT( id_trx )
9. FROM penjualan_detail
10. WHERE id_trx = OLD.id_trx
11. );
12. IF jumlah_trx = 0 THEN
13. DELETE FROM penjualan WHERE id_trx = OLD.id_trx;
14. END IF;
15. END $
16. DELIMITER ;

Selanjutnya jika kita hapus semua data dengan id_trx tertentu pada tabel
penjualan_detail, maka data pada tabel penjualan dengan id_trx yang
sama akan ikut terhapus. Contoh kita jalankan perintah:

DELETE FROM penjualan_detail WHERE id_trx = 7

Maka data pada tabel penjualan yang memiliki id_trx 7 juga akan ikut
terhapus.

mysql> SELECT * FROM penjualan WHERE id_trx = 7;

452 BAB 25 Trigger


Empty set (0.00 sec)

25.5. Menghentikan Eksekusi Statemen


Pada Trigger
Pada kondisi tertentu, kita ingin membuat trigger untuk menghentikan
perubahan data pada database jika kondisi tertentu terpenuhi. Misal pada
contoh sebelumnya, jika kita memasukkan data ke tabel
penjualan_detail dengan nilai jml_barang lebih besar dari stok yang ada,
maka kita hentikan eksekusi statemen.

Untuk menghentikan eksekusi statemen pada trigger, kita tidak bisa


menggunakan statemen ROLLBACK, seperti yang kita gunakan pada Stored
Procedure, melainkan kita harus sedikit mengakalinya, yaitu
menggunakan statemen SIGNAL. Statemen ini digunakan untuk
membangkitkan error atau warning.

Berikut ini contoh trigger nya:

1. DELIMITER $
2. DROP TRIGGER IF EXISTS penjualan_detail_bi $
3. CREATE TRIGGER penjualan_detail_bi
4. BEFORE INSERT ON penjualan_detail
5. FOR EACH ROW
6. BEGIN
7. DECLARE jumlah_stok INT;
8. SET jumlah_stok = ( SELECT stok
9. FROM barang
10. WHERE id_barang = NEW.id_barang
11. );
12.
13. IF jumlah_stok < NEW.jml_barang THEN
14. SIGNAL SQLSTATE '02000'
15. SET MESSAGE_TEXT = 'ERROR: Jumlah stok
tidak mencukupi';
16. END IF;
17. END
18. DELIMITER ;

Panduan Lengkap Query MySQL 453


Perlu diperhatikan bahwa statemen SIGNAL harus diikuti dengan
SQLSTATE. Pada contoh diatas, angka setelah SQLSTATE yaitu 02000
merupakan kode SQLSTATE, minimal diisi 02 atau lebih tinggi untuk
menghasilkan error. Selanjutnya, mari kita tes dengan memasukkan data
pada tabel penjualan_detail:

mysql> INSERT INTO penjualan_detail (id_trx, id_buku,


jml_barang, harga_satuan, diskon, total) VALUES(7, 6, 5,
33800, 0, 33800);
ERROR 1644 (04000): ERROR: Jumlah stok tidak mencukupi

Sebagai tambahan, selain ROLLBACK, pada trigger, kita juga tidak bisa
menggunakan statemen untuk memulai atau mengakhiri Stored
Procedure, yaitu: START PROCEDURE, COMMIT, atau ROLLBACK to
SAVEPOINT.

25.6. Menampilkan Semua Trigger


Untuk menampilkan semua trigger yang ada pada database, kita gunakan
perintah dengan format sebagai berikut:

SHOW TRIGGERS

Perintah diatas akan menampilkan semua trigger pada database yang


sedang digunakan. Jika kita ingin menampilkan trigger pada database
tertentu, kita perlu menambahkan klausa FROM atau IN disertai nama
database.

SHOW TRIGGERS {FROM | IN} nama_database

Misal SHOW TRIGGERS FROM toko_buku yang akan menampilkan semua


trigger yang ada pada database toko_buku.

Lebih lanjut, kita juga dapat menampilkan data trigger yang ada pada tabel
tertentu. Untuk keperluan tersebut, kita gunakan klausa LIKE sebagai
berikut:

454 BAB 25 Trigger


SHOW TRIGGERS LIKE "%nama_tabel%"

Perhatikan bahwa yang kita gunakan adalah nama tabel, bukan nama
trigger, karena sekali lagi, trigger melekat pada tabel.

Misal kita akan menampilkan data trigger yang telah kita buat sebagai
berikut:

mysql> SHOW TRIGGERS LIKE "%penjualan%"\G;


*************************** 1. row ***************************
Trigger: harga_diskon_bi
Event: INSERT
Table: penjualan_detail
Statement: BEGIN
DECLARE kategori INT;
SET kategori = (
SELECT id_kategori
FROM buku
WHERE id_buku = NEW.id_buku
);
IF kategori = 3 THEN
SET NEW.diskon = 0.1;
SET NEW.total = NEW.harga_satuan-(NEW.harga_satuan*0.1);
END IF;
END
Timing: BEFORE
Created: 2017-03-04 15:26:03.39
sql_mode: STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
Definer: root@localhost
character_set_client: utf8mb4
collation_connection: utf8mb4_general_ci
Database Collation: latin1_swedish_ci

Sebagai tambahan, jika terdapat banyak trigger dan kita ingin


menampilkan hanya beberapa diantaranya, kita bisa menambahkan klausa
WHERE, misal kita ingin menampilkan trigger dengan nama tertentu:

SHOW TRIGGERS WHERE kolom LIKE "%kondisi%"

Misal pada contoh diatas, kita tampilkan trigger yang mengandung kata
diskon, query yang kia jalankan adalah SHOW TRIGGERS WHERE `trigger`
LIKE "%diskon%"; Perlu diperhatikan bahwa kita tidak bisa
menggunakan WHERE bersama dengan LIKE.

Panduan Lengkap Query MySQL 455


25.7. Mengubah Trigger
Untuk mengubah trigger yang telah kita buat, kita tidak bisa menggunakan
statemen ALTER seperti yang kita gunakan pada Stored Procedure,
melainkan kita harus menghapus trigger tersebut terlebih dahulu
(menggunakan statemen DROP) kemudian membuat trigger baru dengan
nama yang sama.

25.8. Menghapus Trigger


Untuk menghapus trigger, gunakan statemen DROP TRIGGER diikuti nama
trigger sebagai berikut:

DROP TRIGGER hitung_diskon_bi

Sebagai tambahan, kita dapat mendefinisikan nama database dimana


trigger tersebut berada, misal:

DROP TRIGGER toko_buku.hitung_diskon_bi

Jika tidak didefinisikan, maka MySQL akan secara implisit menambahkan


nama database yang sekarang sedang digunakan.

Jika kita menghapus tabel dimana trigger tersebut berada, maka semua
trigger yang melekat pada tabel tersebut akan ikut terhapus.

Sebagai tambahan, kita dapat menambahkan klausa IF EXISTS untuk


mengetes apakah trigger tersebut ada, misal:

DROP TRIGGER IF EXISTS nama_trigger

Jika tidak menggunakan IF EXISTS, maka jika nama trigger tidak


ditemukan, akan muncul pesan ERROR ERROR 1360 (HY000): Trigger
does not exist Hal ini mengakibatkan query berikutnya tidak akan
dieksekusi, untuk itu sebaiknya selalu gunakan klausa IF EXISTS

456 BAB 25 Trigger


BAB 26 EVENT

Event adalah objek database yang akan dieksekusi sesuai jadwal yang telah
ditetapkan bisa sekali saja atau rutin pada periode tertentu. Event ini dapat
dianalogikan seperti aplikasi Schedule Task yang ada pada windows atau
Cron job pada UNIX. Seperti halnya event pada umumnya, pada MySQL kita
dapat membuat lebih dari satu event yang berjalan pada waktu yang
bersamaan.

Beberapa kegunaan dari Event Scheduler ini adalah:

 Berguna untuk menghapus data lama yang tidak digunakan lagi.

 Membuat rekap laporan baik harian atau bulanan secara otomatis.

 Otomatis mengupdate kolom suatu tabel. Misal pada database


penjualan online, kita akan menutup diskon pada pukul 14.00, kita
dapat menggunakan event scheduler untuk mengupdate tabel diskon
tepat pukul 14:00, sehingga status diskon menjadi close.

26.1. Mengaktifkan Event Schedule


Event Scheduler merupakan modul yang akan memonitor event yang ada
apakah sudah saatnya dijalankan atau tidak. Beberapa event dapat berjalan
secara simultan (bersama sama) tanpa ada masalah.

Secara default, Event Scheduler ini tidak aktif, untuk dapat


menggunakannya, kita harus mengaktifkannya terlebih dahulu. Untuk
mengaktifkan event scheduler, kita lakukan dengan cara mengubah system
variabel event_scheduler menjadi ON menggunakan perintah SET
GLOBAL event_scheduler = ON atau SET @@global.event_scheduler
= ON, untuk mematikannya, tinggal kita ganti ON menjadi OFF.

Panduan Lengkap Query MySQL 457


Untuk melihat status Event Scheduler dapat menggunakan perintah SHOW
PROCESSLIST, jika Event Scheduler aktif maka kolom Command akan
bernilai Daemon.

mysql> SHOW PROCESSLIST\G;


*************************** 1. row ***************************
Id: 30
User: root
Host: localhost:54058
db: tutorial_buku
Command: Query
Time: 0
State: starting
Info: SHOW PROCESSLIST
*************************** 2. row ***************************
Id: 31
User: event_scheduler
Host: localhost
db: NULL
Command: Daemon
Time: 2
State: Waiting on empty queue
Info: NULL

2 rows in set (0.00 sec)

Pada contoh diatas, event_scheduler telah aktif seperti tampak pada


baris 2. Status event scheduler juga dapat dilihat menggunakan perintah
berikut:

mysql> SHOW GLOBAL VARIABLES LIKE 'event_scheduler';


+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| event_scheduler | ON |
+-----------------+-------+
1 row in set (0.07 sec)

Pada tabel diatas terlihat bahwa event_scheduler bernilai ON yang artinya


telah aktif.

Perlu diperhatikan bahwa untuk dapat mengubah variabel global (dengan


statemen SET GROBAL) kita harus memiliki hak akses (privileges) SUPER

458 BAB 26 EVENT


Selain ON dan OFF, Event Scheduler juga dapat bernilai DISABLED
(nonaktif). Penonaktifan Event Scheduler harus dilakukan pada saat server
dijalankan, untuk melakukannya, kita dapat menambahkan opsi pada file
konfigurasi (biasanya my.ini) atau menambahkan opsi ketika menjalankan
server dengan command prompt, contoh sebagai berikut:

mysql> mysqld --event_scheduler=DISABLED

Ketika statusnya non aktif maka kita tidak bisa mengubahnya menjadi ON
atau OFF, jika kita mencoba mengubahnya maka kita akan mendapati error
sebagai berikut:

mysql> SET GLOBAL event_scheduler='ON';


ERROR 1290 (HY000): The MySQL server is running with
the --event-scheduler=DISABLED or --skip-grant-tables
option so it cannot execute this statement

Namun demikian, pada kondisi nonaktif, kita masih tetap bisa membuat,
mengubah, dan menghapus event.

1.7.2. Membuat Event


Untuk membuat event, kita gunakan perintah sebagai berikut:

CREATE EVENT nama_event


ON SCHEDULE waktu_eksekusi
DO statemen;

Terkait penamaan event, terdapat beberapa hal yang perlu diperhatikan:

 Dalam satu database, tidak boleh ada event dengan nama yang sama.

 Nama event bersifat case insensitive yang artinya tidak membedakan


huruf besar atau kecil, sehingga kita tidak bisa membuat dua event
dengan nama Evt_Report dan evt_report.

 Aturan penamaan event sama seperti aturan penamaan tabel dengan


panjang karakter maksimal 64 karakter.

Panduan Lengkap Query MySQL 459


Untuk waktu_eksekusi dapat didefinisikan apakah hanya sekali yaitu
menggunakan klausa AT waktu_eksekusi atau berulang kali dengan
menggunakan klausa EVERY INTERVAL. Beberapa hal yang perlu
diperhatikan terkait waktu eksekusi:

 Opsi INTERVAL yang dapat kita gunakan adalah:

Interval Waktu Eksekusi Interval Waktu Eksekusi

Setiap tahun pada


YEAR Setiap n tahun YEAR_MONTH
bulan ke n

Setiap n setengah Setiap hari pada


QUARTER DAY_HOUR
tahun jam ke n

Setiap hari pada


MONTH Setia n bulan DAY_MINUTE
menit ke n

Setiap haris pada


DAY Setiap n hari DAY_SECOND
detik ke n

Setiap jam pada


HOUR Setiap n jam HOUR_MINUTE
menit ke n

Setiap jam pada


MINUTE Setiap n menit HOUR_SECOND
detik ke n

Setiap menit pada


WEEK Setiap n minggu MINUTE_SECOND
detik ke n

SECOND Setiap n detik

Tabel 26.1 Opsi Interval Pada Event

 Pada AT, setelah waktu eksekusi, kita juga dapat menambahkan


interval, misal AT CURRENT_TIMESTAMP + INTERVAL 1 MINUTE yang
berarti event akan dijalankan pada waktu: saat event dibuat ditambah
1 menit

 Pada waktu eksekusi yang menggunakan klausa EVERY, kita dapat


menambahkan klausa STARTS dan ENDS yang akan mengatur kapan

460 BAB 26 EVENT


EVENT akan mulai dijalankan dan kapan event tersebut berakhir
(dibahas pada sub bab berikutnya).

Misal kita buat tabel dengan nama event_log dengan struktur sebagai
berikut:

1. CREATE TABLE `event_log` (


2. `id_event` INT(11) NOT NULL AUTO_INCREMENT,
3. `nama_event` VARCHAR(50) NULL DEFAULT NULL,
4. `waktu_eksekusi` DATETIME NULL DEFAULT NULL,
5. PRIMARY KEY (`id_event`)
6. )
7. ENGINE=InnoDB

Struktur pada Heidi SQL:

Gambar 26.1 Struktur tabel event_log

Selanjutnya mari kita buat event dengan nama test yang akan dijalankan
pada tanggal 11 Maret 2017 pukul 19.59, waktu pembuatan event ini
adalah 11 Maret 2017 pukul 19.56

1. CREATE EVENT `test`


2. ON SCHEDULE AT '2017-03-11 19:59:00'
3. DO INSERT INTO event_log (nama_event,
4. waktu_eksekusi)
VALUES ('evt_test', NOW());

Pada event diatas, pukul 19:59 MySQL akan menambahkan data ke tabel
event_log dengan nilai test dan tanggal saat data dimasukkan.

mysql> SELECT * FROM event_log;


+----------+------------+---------------------+
| id_event | nama_event | waktu_eksekusi |

Panduan Lengkap Query MySQL 461


+----------+------------+---------------------+
| 1 | test | 2017-03-11 19:59:00 |
+----------+------------+---------------------+
1 row in set (0.00 sec)

Selanjutnya mari kita ubah event dengan menambahkan INTERVAL pada


waktu eksekusi event

1. TRUNCATE TABLE event_log;


2. DROP EVENT IF EXISTS test;
3. CREATE EVENT `test`
4. ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 MINUTE
5. DO INSERT INTO event_log (nama_event, waktu_eksekusi)
6. VALUES ('evt_test', NOW());

Pada query diatas, terlebih dahulu kita kosongkan tabel event_log dan
kita hapus event test, selanjutnya kita buat event dengan nama yang sama.
Event akan dijalankan satu kali yaitu 1 menit setelah event dibuat. Event
dibuat dibuat pukul 20.17, sehingga akan dijalankan pada pukul 20.18

mysql> SELECT * FROM event_log;


+----------+------------+---------------------+
| id_event | nama_event | waktu_eksekusi |
+----------+------------+---------------------+
| 1 | test | 2017-03-11 20:18:11 |
+----------+------------+---------------------+
2 rows in set (0.00 sec)

Contoh lain, kita buat event yang akan dijalankan 1 minggu setelah tanggal
11 Maret 2017.

1. CREATE EVENT `test_int_1_week`


2. ON SCHEDULE AT '2017-03-11 00:00:00' + INTERVAL 1 WEEK
3. DO INSERT INTO event_log (nama_event, waktu_eksekusi)
4. VALUES ('evt_test_1_week', NOW());

Lebih jauh, mari kia buat event yang mengandung interval waktu, misal
kita buat event dengan nama test_interval yang akan dieksekusi setiap
tiga menit, sebagai berikut:

462 BAB 26 EVENT


1. TRUNCATE TABLE event_log;
2. CREATE EVENT `test_every_3_minutes`
3. ON SCHEDULE EVERY 3 MINUTE
4. DO INSERT INTO event_log (nama_event, waktu_eksekusi)
5. VALUES ('evt_test_3_minutes', NOW());

Perhatikan bahwa pada query diatas, kita menggunakan klausa EVERY


bukan AT seperti pada contoh sebelumnya. Event tersebut penulis buat
pada pukul 21:27. Mari kita lihat hasilnya pada tabel event_log

mysql> SELECT * FROM event_log;


+----------+-------------------+---------------------+
| id_event | nama_event | waktu_eksekusi |
+----------+-------------------+---------------------+
| 1 | evt_test_3_minute | 2017-03-11 21:27:35 |
| 2 | evt_test_3_minute | 2017-03-11 21:30:35 |
| 3 | evt_test_3_minute | 2017-03-11 21:33:35 |
+----------+-------------------+---------------------+
5 rows in set (0.02 sec)

Ternyata waktu_eksekusi pertama kali adalah pukul 21:27. Hal ini


menunjukkan bahwa ketika kita membuat event yang berjalan setiap
periode tertentu maka event tersebut akan langsung dijalankan ketika
event selesai dibuat, selanjutnya dijalankan setiap periode yang telah
ditentukan.

Ketika kita membuat event, terkadang nama event bentrok dengan nama
event yang sudah ada, sehingga memunculkan pesan error:

SQL Error (1537): Event 'evt_test_preserve' already exists

Untuk menghindari error tersebut, kita dapat menambahkan klausa IF


NOT EXISTS, misal:

1. CREATE EVENT IF NOT EXISTS evt_test_every_3_minute


2. ON SCHEDULE ...
3. DO ...

Panduan Lengkap Query MySQL 463


Jika nama event tersebut sudah ada pada database, maka MySQL tidak akan
memunculkan warning bahwa nama event telah ada.

mysql> SHOW WARNINGS;


+-------+------+------------------------------------------+
| Level | Code | Message |
+-------+------+------------------------------------------+
| Note | 1537 | Event 'evt_test_preserve' already exists |
+-------+------+------------------------------------------+
1 row in set (0.00 sec)

26.2. Event Dengan Multi Statemen


Seperti pada stored routines, pada event, kita juga dapat menjalankan lebih
dari satu statemen (compound statement). Seperti yang telah disampaikan
pada bab sebelumnya bahwa untuk membuat compound statement kita
awali dengan klausa BEGIN dan kita akhiri dengan klausa END, dan jangan
lupa untuk mengubah delimiter. Misal kita buat event sebagai berikut:

1. DELIMITER $
2. DROP EVENT IF EXISTS rekap_penjualan$
3. CREATE EVENT rekap_penjualan
4. ON SCHEDULE EVERY 1 DAY
5. STARTS '2017-03-12 00:59:55'
6. DO
7. BEGIN
8. DECLARE total_penjualan INT;
9. SET total_penjualan = (
10. SELECT SUM(total_trx)
11. FROM penjualan
12. WHERE tgl_trx = DATE(NOW())
13. );
14. INSERT INTO penjualan_rekap
15. (tgl_trx, tgl_rekap, total_trx)
16. VALUES(DATE(NOW()), NOW(),
total_penjualan);
17. END$
18. DELIMITER ;

464 BAB 26 EVENT


Event diatas akan membuat rekap penjualan setiap pukul 12 malam
(00:00). Data direkap dari tabel penjualan kemudian hasilnya disimpan ke
dalam tabel penjualan_rekap

Perlu diperhatikan bahwa hampir semua statemen SQL dapat digunakan


pada klausa DO, namun, seperti pada stored routine, terdapat beberapa
statemen yang tidak bisa digunakan yaitu: ALTER VIEW, LOCK TABLES,
UNLOCK TABLES, LOAD DATA, LOAD TABLE, BACKUP DATABASE, RESTORE,
INSERT DELAYED

26.3. Menentukan Waktu Awal dan Akhir


Event
Pada contoh sebelumnya, pada event yang dijalankan setiap periode
tertentu, event akan langsung dieksekusi ketika dibuat. Pada kondisi
tertentu, kita tidak ingin hal itu terjadi, untuk itu kita dapat mengatur
kapan event pertama kali dijalankan yaitu dengan menambahkan klausa
STARTS

1. DROP EVENT IF EXISTS test_every_3_minute2;


2. CREATE EVENT `test_every_3_minute2`
3. ON SCHEDULE EVERY 3 MINUTE
4. STARTS NOW() + INTERVAL 5 MINUTE
5. DO INSERT INTO event_log (nama_event, waktu_eksekusi)
6. VALUES ('evt_test_every_3_minute2', NOW());

Pada contoh diatas, event dibuat pukul 21:42 dan akan dijalankan pertama
kali pukul 21:47 (+ INTERVAL 5 MINUTE) dan selanjutnya akan dijalankan
setiap 3 menit.

mysql> SELECT * FROM event_log;


+----------+--------------------------+---------------------+
| id_event | nama_event | waktu_eksekusi |
+----------+--------------------------+---------------------+
| 1 | evt_test | 2017-03-11 19:59:00 |
| 2 | evt_test | 2017-03-11 20:18:11 |
| 3 | evt_test_3_minute | 2017-03-11 21:27:35 |
| 4 | evt_test_3_minute | 2017-03-11 21:30:35 |
| 5 | evt_test_3_minute | 2017-03-11 21:33:35 |

Panduan Lengkap Query MySQL 465


| 6 | evt_test_every_3_minute2 | 2017-03-11 21:47:36 |
| 7 | evt_test_every_3_minute2 | 2017-03-11 21:50:36 |
| 8 | evt_test_every_3_minute2 | 2017-03-11 21:53:36 |
+----------+--------------------------+---------------------+
8 rows in set (0.00 sec)

Pada tabel diatas terlihat bahwa event test_every_3_minute2 dijalankan


pertama kali pukul 21:47:36 selanjutnya di eksekusi setiap 3 menit.

Selain menentukan kapan event dieksekusi pertama kali, kita juga dapat
menentukan kapan event akan berakhir, yaitu dengan menambahkan
klausa ENDS. Misal kita buat event sebagai berikut:

1. CREATE EVENT `test_every_1_minute`


2. ON SCHEDULE EVERY 1 MINUTE
3. STARTS NOW() + INTERVAL 3 MINUTE
4. ENDS '2017-03-11 22:03:00'
5. DO INSERT INTO event_log (nama_event,
6. waktu_eksekusi)
VALUES ('evt_test_every_1_minute', NOW());

Event tersebut dibuat pukul 21:56, yang berarti akan dieksekusi pertama
kali pada 3 menit berikutnya yaitu pukul 21:59, selanjutnya akan
dieksekusi setiap 1 menit dan berhenti pada pukul 22:03

mysql> SELECT * FROM event_log;


+----------+--------------------------+---------------------+
| id_event | nama_event | waktu_eksekusi |
+----------+--------------------------+---------------------+
| 1 | evt_test | 2017-03-11 19:59:00 |
| 2 | evt_test | 2017-03-11 20:18:11 |
| 3 | evt_test_3_minute | 2017-03-11 21:27:35 |
| 4 | evt_test_3_minute | 2017-03-11 21:30:35 |
| 5 | evt_test_3_minute | 2017-03-11 21:33:35 |
| 6 | evt_test_every_3_minute2 | 2017-03-11 21:47:36 |
| 7 | evt_test_every_3_minute2 | 2017-03-11 21:50:36 |
| 8 | evt_test_every_3_minute2 | 2017-03-11 21:53:36 |
| 9 | evt_test_every_1_minute | 2017-03-11 21:59:38 |
| 10 | evt_test_every_1_minute | 2017-03-11 22:00:38 |
| 11 | evt_test_every_1_minute | 2017-03-11 22:01:38 |
| 12 | evt_test_every_1_minute | 2017-03-11 22:02:38 |
+----------+--------------------------+---------------------+
12 rows in set (0.00 sec)

466 BAB 26 EVENT


Pada contoh diatas, event terakhir dieksekusi pukul 22:02:38, karena event
berhenti pukul 22:03:00, maka eksekusi event berikutnya (22:03:38) tidak
dijalankan karena melewati batas akhir event.

26.3. Auto Delete Event


Secara default ketika event selesai dan tidak dieksekusi lagi, maka otomatis
akan dihapus oleh MySQL. Event yang hanya dijalankan sekali
(menggunakan keyword AT) eksekusi pertamanya sekaligus menjadi
waktu eksekusi terakhir.

Jika kita ingin event tersebut tetap ada, kita dapat lakukan dengan
menggunakan klausa ON COMPLETION yang ditulis diantara klausa ON dan
DO tetapi setelah klausa ENDS atau STARTS (jika ada). Gunakan klausa ON
COMPLETION PRESERVE agar event tersebut tidak dihapus oleh MySQL.
Nilai default adalah NOT PRESERVE, yang artinya event akan otomatis
dihapus. Misal:

1. -- Kosongkan tabel event_log


2. TRUNCATE TABLE event_log
3.
4. -- Buat EVENT
5. CREATE EVENT `evt_test_preserve`
6. ON SCHEDULE EVERY 10 SECOND
7. STARTS '2017-03-12 05:04:00'
8. ENDS '2017-03-12 05:04:30'
9. ON COMPLETION PRESERVE
10. DO INSERT INTO event_log (nama_event, waktu_eksekusi)
11. VALUES ('evt_test_preserve', NOW());

Isi tabel event_log setelah pukul 05:04:30

mysql> SELECT * FROM event_log;


+----------+-------------------+---------------------+
| id_event | nama_event | waktu_eksekusi |
+----------+-------------------+---------------------+
| 1 | evt_test_preserve | 2017-03-12 05:04:00 |
| 2 | evt_test_preserve | 2017-03-12 05:04:10 |

Panduan Lengkap Query MySQL 467


| 3 | evt_test_preserve | 2017-03-12 05:04:20 |
| 4 | evt_test_preserve | 2017-03-12 05:04:30 |
+----------+-------------------+---------------------+
4 rows in set (0.00 sec)

Selanjutnya mari kita cek status event tersebut:

mysql> SHOW EVENTS \G;


*************************** 1. row ***************************
Db: tutorial
Name: evt_test_preserve
Definer: root@localhost
Time zone: SYSTEM
Type: RECURRING
Execute at: NULL
Interval value: 10
Interval field: SECOND
Starts: 2017-03-12 05:04:00
Ends: 2017-03-12 05:04:30
Status: DISABLED
Originator: 1
character_set_client: utf8mb4
collation_connection: utf8mb4_general_ci
Database Collation: latin1_swedish_ci
1 row in set (0.01 sec)

Pada data diatas, terlihat bahwa status event adalah DISABLED, untuk
mengaktifkannya kembali kita harus menggunakan perintah ALTER yang
dibahas pada bagian Mengubah EVENT

26.4. Status EVENT dan Comment


Secara default, event yang telah kita buat akan langsung aktif, yang artinya
akan langsung dieksekusi sesuai dengan waktu yang telah ditentukan. Pada
kondisi tertentu, kita ingin membuat event yang telah kita buat kita
eksekusi di lain waktu, untuk keperluan terebut kita bisa membuat event
tersebut nonaktif terlebih dahulu.

Untuk membuat event tidak langsung aktif ketika dibuat, kita dapat
menggunakan klausa DISABLE yang kita tulis setelah waktu eksekusi

468 BAB 26 EVENT


(termasuk klausa STARTS atau ENDS) dan setelah klausa ON COMPLETION
(jika ada), misal:

1. CREATE EVENT `test_disabled`


2. ON SCHEDULE EVERY 10 SECOND
3. STARTS '2017-03-12 05:04:00'
4. ENDS '2017-03-12 05:04:30'
5. ON COMPLETION PRESERVE
6. DISABLE
7. DO INSERT INTO event_log (nama_event, waktu_eksekusi)
8. VALUES ('evt_test_disabled', NOW());

Selain DISABLE, kita juga dapat menggunakan klausa ENABLE yang artinya
event tersebut aktif. Klausa ini sifatnya opsional karena ketika event dibuat
statusnya langsung aktif (ENABLE). Untuk mengubah DISABLE menjadi
ENABLE kita harus menggunakan statemen ALTER

Sebagai tambahan, kita dapat menambahkan comment pada event.


Comment ini berguna salah satunya untuk mengetahui apa yang dilakukan
event. Untuk membuat comment, kita gunakan klausa COMMENT yang
terletak tepat diatas klausa DO, misal:

1. CREATE EVENT `test`


2. ON SCHEDULE EVERY 10 SECOND
3. COMMENT 'Event untuk memasukkan data setiap 10 detik'
4. DO INSERT INTO event_log (nama_event, waktu_eksekusi)
5. VALUES ('evt_test', NOW());

26.5. Menampilkan Semua EVENT


Untuk menampilkan semua event yang ada pada database, kita gunakan
statemen SHOW EVENTS.

SHOW EVENTS;

Selain itu seperti pada query untuk menampilkan tabel, kita dapat
memfilter hasil yang kita inginkan menggunakan klausa WHERE, misal:

Panduan Lengkap Query MySQL 469


1. SHOW EVENTS
2. WHERE status
3. LIKE "%disable%"\G;

Hasil:

mysql> SHOW EVENTS WHERE status LIKE "%disable%"\G;


*************************** 1. row ***************************
Db: toko_buku
Name: test_disabled
Definer: root@localhost
Time zone: SYSTEM
Type: RECURRING
Execute at: NULL
Interval value: 10
Interval field: SECOND
Starts: 2017-03-12 05:04:00
Ends: 2017-03-12 05:04:30
Status: DISABLED
Originator: 1
character_set_client: utf8mb4
collation_connection: utf8mb4_general_ci
Database Collation: latin1_swedish_ci
*************************** 2. row ***************************
Db: tutorial_buku
Name: test_preserve
Definer: root@localhost
Time zone: SYSTEM
Type: RECURRING
Execute at: NULL
Interval value: 10
Interval field: SECOND
Starts: 2017-03-12 05:04:00
Ends: 2017-03-12 05:04:30
Status: DISABLED
Originator: 1
character_set_client: utf8mb4
collation_connection: utf8mb4_general_ci
Database Collation: latin1_swedish_ci
2 rows in set (0.00 sec)

470 BAB 26 EVENT


26.6. Mengubah EVENT
Event yang telah kita buat dapat kita ubah dengan menggunakan statemen
ALTER EVENT dengan format sebagai berikut:

ALTER
EVENT event_name
[ON SCHEDULE schedule]
[ON COMPLETION [NOT] PRESERVE]
[RENAME TO new_event_name]
[ENABLE | DISABLE]
[COMMENT 'comment']
[DO event_body]

Pada syntax diatas, statemen ALTER EVENT diikuti oleh nama event,
kemudian kita pilih bagian yang ingin kita ubah, klausa yang ada di dalam
tanda kurung siku semuanya opsional. Misal kita ingin mengubah nama
event test_disabled menjadi test dan kita ubah statusnya menjadi
ENABLE

1. ALTER
2. EVENT test_disabled
3. RENAME TO test
4. ENABLE

Jika kita jalankan pada command prompt:

mysql> ALTER
-> EVENT test_disabled
-> RENAME TO test
-> ENABLE;
Query OK, 0 rows affected (0.06 sec)

mysql> SHOW EVENTS WHERE status LIKE "%enabled%"\G;


*************************** 1. row ***************************
Db: toko_buku
Name: test
Definer: root@localhost
Time zone: SYSTEM
Type: RECURRING
Execute at: NULL

Panduan Lengkap Query MySQL 471


Interval value: 10
Interval field: SECOND
Starts: 2017-03-12 05:04:00
Ends: 2017-03-12 05:04:30
Status: ENABLED
Originator: 1
character_set_client: cp850
collation_connection: cp850_general_ci
Database Collation: latin1_swedish_ci
1 row in set (0.00 sec)

26.7. Menghapus Event


Untuk menghapus event, gunakan statemen DROP. Jika event tidak
ditemukan maka akan terjadi error yang mengakibatkan statemen
berikutnya tidak dieksekusi, sehingga, sebaiknya tambahkan klausa IF
EXISTS

DROP EVENT IF EXIST nama_event

Dengan klausa IF EXISTS, MySQL hanya akan menampilkan pesan


warning, tidak sampai menghentikan eksekusi statemen berikutnya. Misal

mysql> DROP EVENT IF EXISTS test_fiktif;


Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> SHOW WARNINGS;


+-------+------+--------------------------------------+
| Level | Code | Message |
+-------+------+--------------------------------------+
| Note | 1305 | Event test_fiktif does not exist |
+-------+------+--------------------------------------+
1 row in set (0.00 sec)

26.8. Log Event


Untuk keperluan tertentu kita ingin mengecek apakah terjadi error pada
event yang sedang berjalan. Error tersebut tidak bisa di ketahui melalui log

472 BAB 26 EVENT


yang kita catat pada tabel event_log karena pada tabel tersebut hanya
event yang sukses yang akan dicatat. Untuk itu, kita dapat mengeceknya
melalui mysqld error log

Mysqld error log ini secara default disimpan pada file [nama_user].err
yang ada di dalam folder data, yaitu folder tempat file database disimpan.
Nama file tersebut dapat berbeda beda tergantung konfigurasi awal ketika
kita menginstall MySQL, pada buku ini error log disimpan pada file
mysql_error.log. Contoh isi file error log terkait event:

...
2017-03-11T12:59:00.091967Z 32 [Note] Event Scheduler: Last
execution of toko_buku.test. Dropping.
2017-03-11T12:59:00.216969Z 34 [Note] Event Scheduler:
Dropping toko_buku.test
2017-03-11T13:18:11.676224Z 32 [Note] Event Scheduler: Last
execution of toko_buku.test. Dropping.
2017-03-11T13:18:11.772972Z 35 [Note] Event Scheduler:
Dropping toko_buku.test
...
2017-03-11T14:18:00.207087Z 32 [Note] Event Scheduler: Last
execution of toko_buku.test_int_1_week. Dropping.
2017-03-11T14:18:00.316435Z 36 [Note] Event Scheduler:
Dropping toko_buku.test_int_1_week
2017-03-11T15:02:38.210757Z 32 [Note] Event Scheduler: Last
execution of toko_buku.test_every_1_minute. Dropping.
2017-03-11T15:02:38.335755Z 48 [Note] Event Scheduler:
Dropping toko_buku.test_every_1_minute
2017-03-11T21:45:43.152299Z 0 [Note] InnoDB: page_cleaner:
1000ms intended loop took 23938700ms. The settings might
not be optimal. (flushed=0 and evicted=0, during the time.)
2017-03-11T22:04:30.307807Z 32 [Note] Event Scheduler: Last
execution of toko_buku.test_preserve.

Pada contoh diatas terlihat bahwa setelah event dieksekusi, event tersebut
langsung di hapus: 2017-03-12T13:18:11.676224Z 32 [Note] Event
Scheduler: Last execution of toko_buku.test. Dropping.

Semua error dan warning yang terjadi juga dicatat pada file tersebut. Misal
terjadi kesalahan ketika melakukan penulisan nama tabel yang seharusnya
event_log menjadi event_logs

Panduan Lengkap Query MySQL 473


mysql> CREATE EVENT `test_error`
-> ON SCHEDULE EVERY 1 SECOND
-> ENDS NOW() + INTERVAL 1 SECOND
-> DO INSERT INTO event_logs (nama_event, waktu_eksekusi)
-> VALUES ('evt_test', NOW());
Query OK, 0 rows affected (0.00 sec)

Ketika kita buka file mysql_error.log, kita dapatkan pesan error sebagai
berikut:

2017-03-11T22:38:06.092762Z 61 [ERROR] Event Scheduler:


[root@localhost][toko_buku.test_error] Table
toko_buku.event_logs' doesn't exist
2017-03-12T22:38:06.092762Z 61 [Note] Event Scheduler:
[root@localhost].[toko_buku.test_error] event execution
failed.
2017-03-12T22:38:07.092912Z 32 [Note] Event Scheduler: Last
execution of toko_buku.test_error. Dropping.
2017-03-12T22:38:07.092912Z 62 [Note] Event Scheduler:
Dropping toko_buku.test_error

Dari log diatas, terdapat pesan error bahwa tabel event_logs tidak ada
(Table 'toko_buku.event_logs' doesn't exist) meskipun error,
event tersebut tetap dihapus (Event Scheduler: Dropping
toko_buku.test_error)

Penting diperhatikan bahwa event yang berhasil dieksekusi, tidak di


catat pada file log, hanya eksekusi terakhir dari event yang dicatat.
Sebagai solusinya, kita dapat membuat file log sendiri, seperti yang kita
buat pada pembahasan sebelumnya menggunakan tabel event_log

26.9. Backup Event


Event yang telah kita buat akan disimpan MySQL pada database
information_schema, tabel events, sehingga untuk menampilkan event
tersebut, kita dapat menggunakan statemen SELECT pada tabel events
yang ada pada database information_schema seperti umumnya kita
menampilkan data pada tabel

474 BAB 26 EVENT


mysql> use information_schema;
Database changed
mysql> SELECT * FROM events WHERE status="DISABLED" \G;
*************************** 1. row ***************************
EVENT_CATALOG: def
EVENT_SCHEMA: toko_buku
EVENT_NAME: test_preserve
DEFINER: root@localhost
TIME_ZONE: SYSTEM
EVENT_BODY: SQL
EVENT_DEFINITION: INSERT INTO event_log (nama_event,
waktu_eksekusi)
VALUES ('evt_test_preserve', NOW())
EVENT_TYPE: RECURRING
EXECUTE_AT: NULL
INTERVAL_VALUE: 10
INTERVAL_FIELD: SECOND
SQL_MODE: STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
STARTS: 2017-03-12 05:04:00
ENDS: 2017-03-12 05:04:30
STATUS: DISABLED
ON_COMPLETION: PRESERVE
CREATED: 2017-03-12 05:03:28
LAST_ALTERED: 2017-03-12 05:03:28
LAST_EXECUTED: 2017-03-12 05:04:30
EVENT_COMMENT:
ORIGINATOR: 1
CHARACTER_SET_CLIENT: utf8mb4
COLLATION_CONNECTION: utf8mb4_general_ci
DATABASE_COLLATION: latin1_swedish_ci
1 row in set (0.00 sec)

Karena disimpan di dalam tabel event pada database


information_schema, maka untuk membackup event, ekspor tabel
tersebut menggunakan aplikasi database management atau command
prompt. Contoh dengan command prompt:

mysql> exit;
Bye
E:\mysql-5.7.17\bin>mysqldump -u root information_schema events >
"E:\mysql-5.7.17\backup_event.sql"

Pada contoh diatas, tabel event akan diekspor ke file backup_event.sql


yang berada di folder E:\mysql-5.7.17

Panduan Lengkap Query MySQL 475


Halaman ini sengaja dikosongkan
Jagowebdev.com

476 BAB 26 EVENT


BAB 27 DATA DICTIONARY

Pada database, data dictionary menyimpan semua data terkait struktur


yang ada pada database dan tabel, data dictionary juga disebut sebagai
metadata. Pada MySQL, metadata disimpan pada sebuah database
bernama information_schema, nama tersebut menyesuaikan standar SQL
2003.

Sama seperti tabel pada umumnya, metadata juga disimpan dalam bentuk
tabel, dengan demikian, untuk memperoleh data tersebut, kita juga dapat
menggunakan perintah sql seperti yang umum kita gunakan untuk
melakukan query pada tabel.

Information_schema merupakan system_view yang bersifat read-only


dan in-memory, yang artinya data pada database tersebut hanya dapat
dilihat, tidak dapat ditulis, disamping itu, data pada database tersebut tidak
disimpan dalam bentuk file, melainkan dalam memory komputer
(menggunakan storage engine MEMORY), dan semua tabel bersifat
temporary, sehingga ketika koneksi mysql terputus, semua tabel akan
terhapus dan terbentuk lagi ketika server (mysqld) dijalankan.

Beberapa hal yang perlu diperhatikan terkait database


information_schema:

 Perintah mysqldump tidak dapat digunakan untuk mengekspor


informasi (data, schema) dari database view information_schema.

 Information_schema tidak memiliki data directory (file yang berada


pada direktori data)

 Information_schema tidak memiliki file .frm, definisi tabel langsung


ditulis pada database dan diload ketika server MySQL (mysqld)
dijalankan.

 Metadata yang ada di database information_schema dapat


ditampilkan dengan statemen SHOW, namun data pada database

Panduan Lengkap Query MySQL 477


information_schema lebih lengkap dibanding data yang ditampilkan
oleh perintah SHOW

Database information_schema berisi lebih dari 50 tabel, tabel tersebut


dapat dikelompokkan menjadi:

 Object Catalog seperti database, table, views, columns, indexes,


partitions, stored routines, triggers, dan events

 System information seperti character set, collation, variable, statistik,


available options, dll

 Informasi Permission.
 Informasi Storage Engine.

Melakukan berbagai query pada database information_schema dapat


menghasilkan berbagai informasi penting seperti melihat tipe data kolom
suatu tabel, mengidentifikasi foreign key, index, dll. Pada BAB ini, kita akan
melakukan query pada beberapa tabel saja, Anda dapat meng-explore lebil
jauh untuk memperoleh berbagai informasi lainnya.

27.1. Tabel Schemata


Database information_schema memiliki sebuah tabel yang bernama
schemata yang berisi semua database yang ada pada server beserta
strukturnya. Sebagai catatan istilah schema merupakan nama lain dari
database.

Untuk melihat semua kolom beserta yang ada pada tabel schemata, kita
gunakan statemen yang umum kita gunakan untuk mengambil data pada
tabel:

SELECT * FROM schemata

Hasil yang kita peroleh:


+--------------+--------------------+----------------------------+
| CATALOG_NAME | SCHEMA_NAME | DEFAULT_CHARACTER_SET_NAME |
+--------------+--------------------+----------------------------+

478 BAB 27 DATA DICTIONARY


| def | information_schema | utf8 |
| def | gammu | latin1 |
| def | mysql | latin1 |
| def | penjualan | utf8 |
| def | performance_schema | utf8 |
| def | sakila | latin1 |
| def | sys | utf8 |
| def | toko_buku | latin1 |
+--------------+--------------------+----------------------------+

Lanjutan tabel:
+------------------------+----------+
| DEFAULT_COLLATION_NAME | SQL_PATH |
+------------------------+----------+
| utf8_general_ci | NULL |
| latin1_swedish_ci | NULL |
| latin1_swedish_ci | NULL |
| utf8_general_ci | NULL |
| utf8_general_ci | NULL |
| latin1_swedish_ci | NULL |
| utf8_general_ci | NULL |
| latin1_swedish_ci | NULL |
+------------------------+----------+

Untuk melihat kolom beserta strukturnya, kita gunakan perintah SHOW


COLUMNS

SHOW COLUMNS FROM information_schema.schemata

Hasil:
+----------------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------------------+--------------+------+-----+---------+-------+
| CATALOG_NAME | varchar(512) | NO | | | |
| SCHEMA_NAME | varchar(64) | NO | | | |
| DEFAULT_CHARACTER_SET_NAME | varchar(32) | NO | | | |
| DEFAULT_COLLATION_NAME | varchar(32) | NO | | | |
| SQL_PATH | varchar(512) | YES | | NULL | |
+----------------------------+--------------+------+-----+---------+-------+

27.2. Tabel Tables


Tabel tables menyimpan semua informasi tentang tabel yang ada pada
semua database. Seperti query sebelumnya, kita dapat melihat semua data

Panduan Lengkap Query MySQL 479


menggunakan perintah SELECT *, karena tabel dikelompokkan
berdasarkan nama database, maka untuk melihat spesifik tabel yang ada
pada database tertentu, kita gunakan klausa WHERE

1. SELECT table_name
2. FROM information_schema.tables
3. WHERE table_schema = "toko_buku";

Hasil:
+----------------------+------------+
| table_name | table_type |
+----------------------+------------+
| buku | BASE TABLE |
| pelanggan | BASE TABLE |
| penerbit | BASE TABLE |
| pengarang | BASE TABLE |
| retur | BASE TABLE |
| diskon | BASE TABLE |
| event_log | BASE TABLE |
| kategori | BASE TABLE |
| penjualan | BASE TABLE |
| penjualan_detail | BASE TABLE |
| penjualan_rekap | BASE TABLE |
+----------------------+------------+

27.3. Tabel Columns


Tabel columns menyimpan semua informasi tentang kolom yang ada pada
semua tabel, view, dan system view yang ada pada semua database. Data
kolom ini dikelompokkan berdasarkan nama tabel dan nama database,
sehingga untuk melihat data semua kolom pada tabel tertentu, maka kita
harus memfilter nya berdasarkan nama database dan nama tabel. Misal
kita ingin menampilkan semua informasi tentang kolom yang ada pada
tabel buku di dalam database toko_buku

1. SELECT column_name, column_type,


2. character_maximum_length max_len,
3. ordinal_position AS urutan
4. FROM information_schema.columns
5. WHERE table_schema = "toko_buku" AND table_name = "buku";

480 BAB 27 DATA DICTIONARY


Hasil:
+--------------+--------------+---------+--------+
| column_name | column_type | max_len | urutan |
+--------------+--------------+---------+--------+
| id_buku | int(11) | NULL | 1 |
| isbn | char(13) | 13 | 2 |
| judul | varchar(255) | 255 | 3 |
| deskripsi | text | 65535 | 4 |
| id_pengarang | tinyint(4) | NULL | 5 |
| id_penerbit | tinyint(4) | NULL | 6 |
| tgl_terbit | date | NULL | 7 |
| harga | int(11) | NULL | 8 |
| status | tinyint(1) | NULL | 9 |
| stok | tinyint(4) | NULL | 10 |
| id_kategori | smallint(6) | NULL | 11 |
| url | varchar(255) | 255 | 12 |
+--------------+--------------+---------+--------+

27.4. Tabel Routines


Tabel ini menyimpan informasi tentang routines (stored procedure dan
stored function) yang ada pada semua database. Untuk melihat informasi
routines yang ada pada database tertentu, lakukan pencarian berdasarkan
nama database.

Misal kita akan mencari informasi tentang semua routines yang ada di
database toko_buku.

1. SELECT routine_name, routine_type


2. FROM information_schema.routines
3. WHERE routine_schema = 'toko_buku';

Hasil:

Panduan Lengkap Query MySQL 481


+----------------------+--------------+
| routine_name | routine_type |
+----------------------+--------------+
| harga_neto | PROCEDURE |
| penjualan | PROCEDURE |
| penjualan_akumulatif | PROCEDURE |
| penjualan_perbulan | PROCEDURE |
| penjualan_total | PROCEDURE |
| status_stok | FUNCTION |
| total_perbulan | FUNCTION |
+----------------------+--------------+

482 BAB 27 DATA DICTIONARY


BAB 28 Identifikasi Error Pada Query

Ketika menuliskan berbagai perintah SQL, kita pasti akan menemui


berbagai pesan kesalahan (error), banyak diantaranya yang berupa
kesalahan yang simpel, namun pada query yang kompleks, kesalahan
tersebut susah diidentifikasi. BAB ini akan membahas berbagai pesan
kesalahan yang sering terjadi dengan harapan dapat memberikan ide
bagaimana mengatasi error tersebut.

Beberapa error yang sering terjadi:

 Error karena kesalahan penulisan SQL. Kesalahan ini terjadi ketika


MySQL mem-parse SQL dan menemukan ada SQL yang tidak sesuai
dengan standar yang ada. Contoh ketika menjalankan query:

1. SELECT id_trx,
2. tgl_trx,
3. FROM penjualan

Muncul pesan error sebagai berikut:

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 'FROM
penjualan' at line 3

Untuk mencari letak kesalahannya, perhatikan sql setelah kata-kata


near, biasanya kesalahan penulisan berada tepat sebelum SQL
tersebut, selain itu juga perhatikan baris terjadinya error. Pada
contoh diatas, kesalahan terjadi karena terdapat tanda koma sebelum
FROM ( near 'FROM penjualan' ) yang berada pada baris 3 (at
line 3)

 Terdapat struktur tabel yang tidak sesuai. Kesalahan ini terjadi ketika
MySQL berhasil mem-parse query SQL yang kita tulis, namun gagal

Panduan Lengkap Query MySQL 483


mengeksekusi nya karena terdapat struktur yang tidak sesuai, contoh
ketika menjalankan query:

1. SELECT id_barang,
2. Tgl_trx
3. FROM penjualan

Muncul pesan error:

SQL Error (1054): Unknown column 'id_barang' in 'field list'

Pada contoh diatas, error terjadi karena kolom id_barang tidak


ditemukan. Sebagai tambahan petunjuk, terdapat pesan in 'field
list' yang berarti pada daftar nama kolom, petunjuk ini bermanfaat
ketika query yang kita buat kompleks.

Dari penjelasan diatas, diharapkan Anda dapat mengidentifikasi dengan


mudah error yang sering terjadi ketika men-eksekusi perintah SQL.

Berikut ini disajikan berbagai contoh berbagai pesan kesalahan yang


terjadi ketika men-eksekusi perintah SQL

1. Terdapat koma setelah klausa FROM

Ketika menulis statemen yang panjang, terkadang kita tidak sengaja


menambahkan karakter yang tidak pada tempatnya, misal kita
menambahkan koma pada nama tabel yang ada pada klausa FROM, contoh:

1. SELECT id_buku,
2. judul,
3. id_trx
4. FROM penjualan_detail,
5. LEFT JOIN buku USING (id_buku)
6. WHERE id_trx IN (SELECT id_trx
7. FROM penjualan_detail
8. GROUP BY id_trx
9. HAVING COUNT(*) > 2
10. )

Ketika query dijalankan, akan muncul pesan error:

484 BAB 28 Identifikasi Error Pada Query


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 'LEFT JOIN buku
USING (id_buku)
WHERE id_trx IN (SELECT id_trx
' at line 5

Kesalahan tersebut karena terdapat koma setelah klausa FROM penjualan

2. Terdapat Fungsi Yang Tidak Dikenal

Ketika kita menggunakan fungsi pada query, terkadang kita merasa bahwa
kita telah menuliskannya dengan benar, namun ternyata mendapati pesan
error, seperti contoh pada query berikut:

1. SELECT id_buku,
2. judul,
3. id_trx,
4. COUNT (id_trx) AS jml_trx
5. FROM penjualan_detail
6. LEFT JOIN buku USING (id_buku)
7. WHERE id_trx IN (SELECT id_trx
8. FROM penjualan_detail
9. GROUP BY id_buku
10. HAVING count(*) > 2
11. )

Ketika dijalankan, kita mendapati pesan error:

SQL Error (1630): FUNCTION toko_buku.COUNT does not exist.


Check the 'Function Name Parsing and Resolution' section in
the Reference Manual

Pesan tersebut menyebutkan bahwa fungsi COUNT tidak dikenal, padahal


kita ketahui bersama bahwa MySQL memiliki fungsi COUNT. Kenapa
demikian? Ternyata, pada MySQL terdapat beberapa fungsi yang dalam
penulisannya tidak boleh ada spasi antara nama fungsi dan kurung buka,
sehingga, pada contoh diatas, error terjadi karena terdapat spasi antara
fungsi COUNT dan kurung buka (baris 4).

Panduan Lengkap Query MySQL 485


3. Tidak ada klausa ON atau USING setelah klausa JOIN

Pada query yang menggunakan JOIN, maka kita perlu mendefinisikan


hubungan antar tabel dengan klausa ON atau USING, jika tidak, maka akan
muncul 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 'WHERE id_trx
ISNULL
GROUP BY id_buku' at line 5

Adapun query yang dijalankan adalah:

1. SELECT id_buku,
2. judul
3. FROM penjualan_detail
4. RIGHT JOIN buku
5. WHERE id_trx IS NULL
6. GROUP BY id_buku

Pada contoh error diatas, hanya ada pemberitahuan tentang error saja,
tidak diberi tahu penyebabnya apa, untuk itu, kita harus mencari sendiri.
Ketika dilakukan penelitian diketahui bahwa belum ada klausa ON atau
USING setelah JOIN.

Error yang sama juga terjadi pada query berikut:

1. SELECT bagian,
2. COUNT(
3. CASE WHEN status = "P" AND gaji = 1 AND kab = "Melawi"
4. THEN id_kar
5. END
6. ) AS hr_melawi
7. FROM data_karyawan
8. LEFT JOIN data_pekerjaan

486 BAB 28 Identifikasi Error Pada Query


4. Error Minim Petunjuk

Ketika terjadi error, terkadang MySQL tidak memberikan petunjuk yang


jelas, di query bagian mana error terjadi, contoh pesan error nya adalah
sebagai berikut:

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 '' at line 8

Sedangkan query yang dijalankan adalah:

1. SELECT id_buku,
2. judul
3. FROM penjualan_detail
4. LEFT JOIN buku USING (id_buku)
5. WHERE id_trx IN (SELECT id_trx
6. FROM penjualan_detail
7. GROUP BY id_buku
8. HAVING count(*) > 2

Pada contoh error diatas, satu satu nya petunjuk adalah line 8, sehingga
kita cari kesalahan sql di akhir line 7. Setelah diteliti, penyebab error
adalah kurang kurung tutup di bagian akhir line 7, seharusnya line 7 adalah
GROUP BY id_buku)

5. Argumen Fungsi Tidak Lengkap

Fungsi yang kita gunakan pada SQL memiliki argumen dengan jumlah
tertentu, jika jumlah argumen tersebut kurang, maka akan muncul 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 ') AS tahun_terbit
FROM buku' at line 3

Query yang kita jalankan:

Panduan Lengkap Query MySQL 487


1. SELECT judul,
2. LEFT (tgl_terbit) AS tahun_terbit
3. FROM buku

Pesan tersebut juga tidak secara jelas menyebutkan bahwa jumlah


argumen pada fungsi LEFT masih kurang, untuk mengetahui penyebab
error tersebut, kita hanya bisa mengira-ira saja. Query yang benar adalah:

1. SELECT judul,
2. LEFT (tgl_terbit, 4) AS tahun_terbit
3. FROM buku

6. Error Minim Petunjuk #2

Lagi lagi, ketika menjalankan query, pesan error yang muncul tidak secara
jelas menyebutkan kesalahan apa yang ada pada SQL, jika sudah demikian,
maka kita harus mampu mengidentifikasi sendiri, misal:

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 '' at line 13

Adapun query yang kita jalankan adalah:

1. ( SELECT id_pelanggan,
2. tgl_trx AS tanggal,
3. 'order' AS jenis_trx
4. FROM penjualan_detail
5. LEFT JOIN penjualan USING (id_trx)
6. ORDER BY tgl_trx DESC
7. LIMIT 5
8. )
9. UNION ALL
10. SELECT id_pelanggan,
11. tgl_retur,
12. 'retur' AS jenis_trx
13. FROM retur

488 BAB 28 Identifikasi Error Pada Query


Jika kita menjalankan query sendiri sendiri secara terpisah (tanpa UNION
ALL), maka query dapat berjalan dengan baik tanpa error. Pesan kesalahan
hanya menyebutkan error terjadi pada baris 13, tidak ada petunjuk lain.

Setelah dilakukan penelitian, diketahui bahwa ketika menggunakan UNION


atau UNION ALL, kedua query harus identik, karena query pertama diawali
dengan kurung buka dan diakhiri dengan kurung tutup, maka query kedua
juga harus sama, sehingga query yang benar adalah:

1. ( SELECT id_pelanggan,
2. tgl_trx AS tanggal,
3. 'order' AS jenis_trx
4. FROM penjualan_detail
5. LEFT JOIN penjualan USING (id_trx)
6. ORDER BY tgl_trx DESC
7. LIMIT 5
8. )
9. UNION ALL
10. ( SELECT id_pelanggan,
11. tgl_retur,
12. 'retur' AS jenis_trx
13. FROM retur
14. )

Catatan: error ini hanya terjadi pada MySQL versi 5.6 dan sebelumnya,
ketika menggunakan MySQL versi 5.7, query dapat berjalan dengan baik
tanpa tanda kurung pada query kedua

7. Kurang koma pada list kolom

Pada query yang kompleks, terkadang kesalahan kecil susah ditemukan,


misal ketiadaan koma dalam daftar kolom pada statemen SELECT, misal
terdapat query berikut:

1. SELECT bagian,
2. COUNT(
3. CASE WHEN status = "p" AND status_gaji = 1 AND
kab = "Melawi"
4. THEN id_kar
5. END
6. ) AS hr_melawi
7. COUNT(

Panduan Lengkap Query MySQL 489


8. CASE WHEN status = "p" AND status_gaji = 2 AND
kab = "Melawi"
9. THEN id_kar
10. END
11. ) AS hr_melawi
12. FROM karyawan
13. LEFT JOIN pekerjaan USING (id_kar)
14. GROUP BY bagian

Ketika dijalankan, akan muncul 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 'COUNT(
CASE
WHEN status = "p" AND status_gaji = 2 AND kab = "Melawi"
' at line 8

Error tersebut terjadi karena tidak ada koma setelah hr_melawai (baris
nomor 6), hr_melawai adalah kolom alias yang disusun dari fungsi yang
cukup kompleks. Baris 6 seharusnya seharusnya ) AS hr_melawi,

8. Kurang kurung tutup

Lagi lagi pada query yang kompleks, kesalahan kecil akan cukup
merepotkan, misal ketika menjalankan query berikut:

1. SET lc_time_names = 'id_ID';


2. SELECT judul,
3. DATE_FORMAT(
4. STR_TO_DATE(tgl_sewa, '%d/%m/%Y')
5. , '%d %M %Y'
6. ) AS tgl_sewa,
7. '2017-04-02' AS tgl_sekarang,
8. DATEDIFF('2017-04-02', STR_TO_DATE(tgl_sewa,
9. '%d/%m/%Y') AS hari
10. FROM persewaan

Muncul pesan error:

SQL Error (1064): You have an error in your SQL syntax;


check the manual that corresponds to your MySQL server

490 BAB 28 Identifikasi Error Pada Query


version for the right syntax to use near 'FROM persewaan'
at line 8

Ketika dilakukan penelitian diketahui bahwa pada baris 8, fungsi DATEDIFF


kurang kurung tutup.

9. Statemen Kurang Lengkap

Pada query yang mengandung ekspresi logika, seperti penggunaan


statemen IF ELSE pada pembuatan STORED PROCEDURE (bukan fungsi IF
pada statemen SELECT) terkadang kita lupa mengakhiri statemen tersebut,
misal:

1. DELIMITER $
2. DROP PROCEDURE IF EXISTS transaksi;
3. CREATE PROCEDURE transaksi ()
4. BEGIN
5. DECLARE sql_error BOOL DEFAULT 0;
6.
7. DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
8. BEGIN
9. SET sql_error = 1;
10. END;
11.
12. START TRANSACTION;
13. INSERT INTO user VALUES ('nitro');
14. INSERT INTO user VALUES ('alfa'); -- error: duplikasi data
15. INSERT INTO user VALUES ('zebra');
16.
17. IF sql_error = 0
18. THEN COMMIT;
19. ELSE
20. ROLLBACK;
21. END $
22. DELIMITER ;

Ketika dijalankan muncul pesan error:

SQL Error (1064) in statement #2: 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 '' at line
19

Panduan Lengkap Query MySQL 491


Setelah dilakukan penelitian diketahui bahwa error tersebut disebabkan
karena statemen IF yang dimulai pada baris 17 tidak diakhiri dengan
klausa END IF.

10. Query yang mengandung keyword MySQL

Terkadang, ketika menjalankan query yang terdapat nama tabel atau


kolom yang juga merupakan keyword yang digunakan MySQL, muncul
error seperti ini:

ERROR 1064 (42000): 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 'trigger LIKE
"%diskon%"' at line 1

Adapun query yang dijalankan adalah:

SHOW TRIGGERS WHERE trigger LIKE "%diskon%";

Error tersebut terjadi karena nama kolom, yaitu trigger merupakan


keyword yang digunakan oleh MySQL, untuk mengatasi error tersebut,
nama kolom harus diapit backtick (`). Sehingga, query yang benar adalah:

1. SHOW TRIGGERS WHERE `trigger` LIKE "%diskon%";

11. Penggunaan klausa DISTINCT lebih dari satu kali

Dalam satu query, klausa DISTINCT hanya boleh digunakan satu kali, jika
tidak, maka akan terjadi error, misal kita jalankan query:

1. SELECT DISTINCT id_pengarang, DISTINCT id_penerbit


2. FROM buku

Maka akan muncul pesan error sebagai berikut:

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_penerbit

492 BAB 28 Identifikasi Error Pada Query


FROM buku' at line 1

Untuk mengatasinya, kita pilih salah satu kolom yang ingin kita terapkan
klausa distinct, misal:

1. SELECT DISTINCT id_pengarang, id_penerbit


2. FROM buku

12. Tidak ada delimiter pada akhir statemen

Seperti yang telah kita pelajari bahwa setiap statemen pada SQL harus
diakhiri dengan delimiter, yang biasanya adalah karakter titik koma ( ; ),
pada SQL yang kompleks, terkadang kita lupa menutup statemen dengan
delimiter, misal ketika membuat trigger:

1. DELIMITER $
2. DROP TRIGGER IF EXISTS penjualan_detail_ai$
3.
4. CREATE TRIGGER penjualan_detail_ai
5. AFTER INSERT ON penjualan_detail
6. FOR EACH ROW
7. BEGIN
8. DECLARE total INT;
9. SET total = ( SELECT SUM(total)
10. FROM penjualan_detail
11. WHERE id_trx = NEW.id_trx
12. );
13.
14. UPDATE penjualan SET total_trx = total_trx
15. WHERE id_trx = NEW.id_trx
16. END $
17. DELIMITER ;

Ketika query tersebut dijalankan, akan muncul 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 'END' at line 15

Panduan Lengkap Query MySQL 493


Pada contoh diatas, error terjadi karena statemen UPDATE, yang dimulai
pada baris 14 dan berakhir pada baris 15 tidak diakhiri dengan titik koma,
seharusnya pada baris 15, querynya adalah WHERE id_trx = NEW.id_trx;

13. Kolom Ambigu

Ketika kita menjalankan query yang melibatkan beberapa tabel, maka jika
ada nama kolom yang sama, kita harus definisikan nama tabel didepannya,
jika tidak, maka akan muncul pesan error bahwa nama kolom ambigu
(ambiguous) yang artinya tidak jelas, misal kita memiliki query sebagai
berikut:

1. SELECT id_pelanggan,
2. tgl_trx,
3. tgl_retur
4. FROM penjualan
5. LEFT JOIN retur USING (id_trx)

Ketika query dijalankan, akan muncul pesan error:

SQL Error (1052): Column 'id_pelanggan' in field list is


ambiguous

Error tersebut terjadi karena MySQL tidak tahu harus menggunakan kolom
id_pelanggan dari tabel yang mana penjualan atau retur, untuk
mengatasi hal tersebut, kita tambahkan nama tabel pada nama kolom
id_pelanggan, misal: SELECT penjualan.id_pelanggan

14. Kolom tidak terdefinisi

Ketika query yang kita jalankan mengandung subquery, maka harus


dipastikan hawa pada subquery tersebut kita telah mendefinisikan semua
kolom yang diperlukan, misal kita memiliki query:

1. SELECT id_pelanggan,
2. nama,
3. jml_trx,
4. total_trx
5. FROM pelanggan

494 BAB 28 Identifikasi Error Pada Query


6. LEFT JOIN (SELECT COUNT(*) AS jml_trx, SUM(total_trx)
AS total_trx
7. FROM penjualan
8. GROUP BY id_pelanggan
9. HAVING jml_trx > 1
10. ) AS penjualan
11. USING (id_pelanggan)

Ketika query dijalankan, maka akan muncul pesan error:

SQL Error (1054): Unknown column 'id_pelanggan' in 'from


clause'

Error tersebut terjadi pada bagian klausa FROM. Pada query yang
mengandung JOIN, semua tabel yang ada pada klausa join dianggap bagian
dari klausa FROM, sehingga ketika terjadi error, MySQL menyebutnya error
pada klausa FROM.

Ketika melakukan JOIN, kita harus mendefinisikan hubungan antar tabel


menggunakan klausa USING atau ON. Pada contoh diatas, kita
mendefinisikan hubungan antar tabel menggunakan kolom id_pelanggan.
Seperti kita ketahui bahwa tabel penjualan (yang kita join kan) sudah
memiliki kolom id_pelanggan tetapi kenama masih muncul error?

Pada query diatas, kita membuat tabel baru hasil query dari tabel
penjualan untuk digabungkan dengan tabel pelanggan, nah karena tabel
baru tersebut tidak memiliki kolom id_pelanggan, maka muncul pesan
error, jika kita pisah, bentuk tabel baru tersebut adalah:

mysql> SELECT COUNT(*) AS jml_trx, SUM(total_trx) AS


total_trx
-> FROM penjualan
-> GROUP BY id_pelanggan
-> HAVING jml_trx > 1;
+---------+-----------+
| jml_trx | total_trx |
+---------+-----------+
| 2 | 575000 |
| 4 | 1246000 |

Panduan Lengkap Query MySQL 495


+---------+-----------+
2 rows in set (0.00 sec)

Untuk mengatasi error tersebut, maka kita tambahkan kolom id_pelanggan


pada subquery, sehingga query yang benar adalah:

1. SELECT id_pelanggan,
2. nama,
3. jml_trx,
4. total_trx
5. FROM pelanggan
6. LEFT JOIN (SELECT id_pelanggan, COUNT(*) AS jml_trx,
SUM(total_trx) AS total_trx
7. FROM penjualan
8. GROUP BY id_pelanggan
9. HAVING jml_trx > 1
10. ) AS penjualan
11. USING (id_pelanggan)

Hasil:
+--------------+--------------------+---------+-----------+
| id_pelanggan | nama | jml_trx | total_trx |
+--------------+--------------------+---------+-----------+
| 1 | Anton | NULL | NULL |
| 2 | Braskie | 2 | 575000 |
| 3 | Charlie | 4 | 1246000 |
| 4 | Deni | NULL | NULL |
| 5 | Erdhi | NULL | NULL |
| 6 | Ferry | NULL | NULL |
| 7 | PT. Manunggal Jaya | NULL | NULL |
| 8 | CV. Riang Gembira | NULL | NULL |
| 9 | Deni | NULL | NULL |
+--------------+--------------------+---------+-----------+

15. Kolom tidak ditemukan

Setiap query select, kolom yang kita definisikan harus ada pada tabel yang
kita pilih, pada query yang kompleks, hal ini terkadang susah diidentifikasi,
misal kita memiliki query sebagai berikut:

496 BAB 28 Identifikasi Error Pada Query


1. SELECT id_pelanggan, nama, jml_trx
2. , tgl_trx, tgl_retur, total_trx
3. FROM pelanggan
4. LEFT JOIN (SELECT id_pelanggan
5. COUNT(*) AS jml_trx,
6. SUM(total_trx) AS total_trx
7. FROM penjualan
8. GROUP BY id_pelanggan
9. HAVING jml_trx > 1
10. ) AS penjualan
11. USING (id_pelanggan)
12. LEFT JOIN retur USING (id_pelanggan)

Ketika query dijalankan, maka akan muncul pesan error:

SQL Error (1054): Unknown column 'tgl_trx' in 'field list'

Pada query diatas, kita menggabungkan tiga tabel, yaitu tabel pelanggan,
tabel penjualan (subquery), dan tabel retur. Error terjadi karena kita ingin
menampilkan data pada kolom tgl_trx, namun kolom tersebut tidak
ditemukan pada ketiga tabel tersebut. Maksud dari query diatas adalah
menampilkan tgl_trx pada tabel penjualan, untuk itu kita perlu
menambahkan kolom tersebut pada subquery:

1. ...
2. LEFT JOIN (SELECT id_pelanggan
3. COUNT(*) AS jml_trx, MAX(tgl_trx)
4. AS tgl_trx,
5. SUM(total_trx) AS total_trx
6. FROM penjualan
7. GROUP BY id_pelanggan
8. HAVING jml_trx > 1
9. ) AS penjualan
10. USING (id_pelanggan)
11. ...

Panduan Lengkap Query MySQL 497


16. Setiap Tabel Termasuk Tabel Turunan (hasil Subquery) Harus
Memiliki Nama

Jika query yang kita jalankan mengandung subquery pada klausa FROM
baik pada klausa FROM secara langsung maupun klausa JOIN, maka
subquery tersebut akan membentuk tabel, sehingga harus diberi nama, jika
tidak, maka akan muncul pesan error. Misal, kita memiliki query:

1. SELECT id_pelanggan, nama, jml_trx, tgl_trx, tgl_retur,


2. (SELECT SUM(total_trx) FROM penjualan)
3. , total_trx
4. FROM pelanggan
5. LEFT JOIN (SELECT id_pelanggan,
6. COUNT(*) AS jml_trx, MAX(tgl_trx)
7. AS tgl_trx,
8. SUM(total_trx) AS total_trx
9. FROM penjualan
10. GROUP BY id_pelanggan
11. ) USING (id_pelanggan)
12. LEFT JOIN retur USING (id_pelanggan)
13. WHERE jml_trx IS NOT NULL

Ketika dijalankan, maka akan muncul pesan error:

SQL Error (1248): Every derived table must have its own
alias

Error tersebut terjadi karena pada klausa JOIN kita menggunakan


subquery, namun kita tidak mendefinisikan nama tabel hasil subquery
tersebut. Untuk mengatasinya, kita buat nama tabel hasil query tersebut,
misal

... ...
8. GROUP BY id_pelanggan
9. ) AS penjualan USING (id_pelanggan)
10. LEFT JOIN retur USING (id_pelanggan)
... ...

Nama tabel tersebut dapat menggunakan keyword AS atau cukup nama


saja.

498 BAB 28 Identifikasi Error Pada Query


Perhatikan: ERROR tidak terjadi pada subquery yang ada pada daftar
kolom yang ada pada statemen SELECT (baris 2), hal ini dikarenakan
subquery tersebut tidak membentuk tabel, melainkan langsung
membentuk kolom.

Panduan Lengkap Query MySQL 499


Halaman ini sengaja dikosongkan
Jagowebdev.com

500 BAB 28 Identifikasi Error Pada Query


BAB 29 MySQL dan PHP

Hampir semua aplikasi yang ditulis dengan berbagai jenis bahasa


pemrograman dapat dipastikan menggunakan database untuk menyimpan
data. MySQL sendiri sering dipasangkan dengan aplikasi berbasis web yang
80% nya didominasi oleh bahasa pemrograman PHP, untuk itu, pada BAB
ini, kita akan membahas berbagai contoh program yang ditulis
menggunakan bahasa pemrograman PHP.

PHP berkembang dengan cepat, banyak fitur yang ditambahkan, yang akan
dihilangkan (deprecated), dan sudah dihilangkan (removed). Pada
pembahasan kali ini, penulis menggunakan PHP versi 5.3.0, yang
membawa perubahan cukup signifikan terutama mulai dikenalkannya
ekstensi mysqli (mysql improved) dan memberikan peringatan jika masih
menggunakan ekstensi lama, yaitu mysql.

Penulis berasumsi Anda sudah cukup familiar dengan PHP, Penulis


membuat contoh sesimpel mungkin dengan penekanan pada berbagai
fungsi yang digunakan untuk mengakses database MySQL. Disini kita tidak
membahas segala hal tentang PHP, karena buku ini tentang MySQL, bukan
PHP. Untuk referensi lebih lengkap tentang PHP, Anda dapat membaca
berbagai buku yang membahas khusus tentang PHP.

29.1. Install PHP


Untuk Menginstall PHP, dapat menggunakan paket web server seperti
XAMPP, WAMP, atau Easy PHP yang minimal sudah terdiri dari Apache,
PHP, dan MySQL, Hal ini akan memudahkan dibanding menginstall PHP
dan server Apache secara manual. Khusus, untuk XAMPP, mulai versi 5.x
paket ini tidak lagi menggunakan MySQL, melainkan MariaDB. MariaDB
menggunakan model SQL yang sama persis dengan yang digunakan oleh
MySQL.

Panduan Lengkap Query MySQL 501


Semua file PHP disimpan dalam folder htdocs, untuk mengaksesnya, buka
browser dan buka alamat http://localhost/file.php

29.2. Menulis Script PHP


Script PHP merupakan file teks, ya hanya file teks, yang berisi script PHP
itu sendiri dan/atau script lain seperti kode HTML. Ketika kita membuka
file PHP, misal dengan browser, maka PHP Interpreter akan membaca kode
yang ada di dalam file tersebut kemudian memproses hanya kode PHP
yang ada di dalamnya dan membiarkan kode non PHP apa adanya,
selanjutnya hasil pengolahan tersebut akan dikirim ke browser dalam
format HTML.

Pada file PHP, untuk membedakan kode PHP dengan kode lain, diperlukan
tag khusus sebagai pembuka dan penutup kode PHP. Setidaknya terdapat
empat tag yang dapat digunakan, namun secara default hanya dua yang
dapat digunakan, untuk menggunakan lainnya, kita harus mengubah
setting pada file php.ini

Secara default tag yang dapat digunakan adalah:

 Default tag, dengan tag pembuka <?php dan tag penutup ?>, misal:

<?php echo 'Memulai PHP' ?>

 Shorthand tag

<?='Memulai PHP'?>

Shorthand tag ini hanya digunakan untuk mencetak output


(menggantikan statemen echo).

502 BAB 29 MySQL dan PHP


29.3. Koneksi Database MySQL
Sebelum mengakses database MySQL, terlebih dahulu, kita harus
membuka koneksi ke database tersebut.

Nama File: 01_koneksi.php

1. <html>
2. <head>
3. <title>Koneksi MySQL</title>
4. </head>
5. <body>
6. <?php
7. $host = 'localhost';
8. $user = 'root';
9. $pass = '';
10. $conn = mysqli_connect($host, $user, $pass);
11.
12. if (!$conn) {
13. die ('Gagal terhubung dengan MySQL');
14. }
15.
16. echo 'Berhasil terhubung dengan MySQL';
17. ?>
18. </body>
19. </html>

Penjelasan:

 Script diatas terdiri dari script HTML dan PHP. Ketika file tersebut
dibuka melalui browser http://localhost/01_koneksi.php maka PHP
hanya akan memproses script yang ada di antara tag <?php dan ?>,
sedangkan script HTML akan dibiarkan apa adanya.

 Fungsi mysqli_connect merupakan fungsi yang disediakan PHP


untuk login ke database MySQL. Jika server MySQL belum aktif, maka
akan muncul pesan warning

Panduan Lengkap Query MySQL 503


Warning: mysqli_connect(): (HY000/2002): No connection
could be made because the target machine actively refused
it. in E:\xampp-1.8.3.2\htdocs\tes_dates.php on line 10

Untuk memerintahkan PHP agar tidak menampilkan pesan warning,


kita dapat menggunakan tanda @ di depan fungsi, misal
@mysqli_connect

 Jika koneksi gagal, maka variabel $conn akan kosong, sehingga pada
statemen if (baris 12) variabel tersebut kita uji dengan !$conn yang
artinya jika variabel $conn kosong maka telah terjadi error dan dengan
fungsi die(), kita hentikan script (PHP tidak membaca script
setelahnya).

 Hasil pengolahan script PHP kemudian dikirim kembali ke browser


dalam bentuk file HTML, sehingga, jika koneksi berhasil, maka
dokumen HTML yang dikirim adalah:

1. <html>
2. <head>
3. <title>Koneksi MySQL</title>
4. </head>
5. <body>
6. <p>Berhasil terhubung dengan MySQL</p>
7. </body>
8. </html>

Sedangkan tampilan pada browser hanya teks Berhasil terhubung


dengan MySQL

29.4. Memilih Database


Langkah selanjutnya, setelah berhasil menghubungkan PHP dengan
MySQL, kita perlu untuk memilih database. Seperti di bahas pada BAB awal
buku ini, dengan memilih database, akan memudahkan kita menulis query,
dimana kita tidak perlu menulis nama database untuk setiap tabel yang ada
pada query.

504 BAB 29 MySQL dan PHP


Untuk memilih database, kita gunakan fungsi mysqli_select_db().
Contoh:

File: 02_memilih_database.php

1. <html>
2. <head>
3. <title>Koneksi MySQL</title>
4. </head>
5. <body>
6. <?php
7. $host = 'localhost';
8. $user = 'root';
9. $pass = '';
10. $conn = mysqli_connect($host, $user, $pass);
11.
12. if (!$conn) {
13. die ('Gagal terhubung dengan MySQL');
14. }
15.
16. echo 'Berhasil terhubung dengan MySQL';
17.
18. mysqli_select_db($conn, 'toko_buku') OR
die('Database toko_buku tidak ditemukan');
19.
20. echo 'Database toko_buku berhasil dipilih';
21. ?>
22. </body>
23. </html>

Penjelasan:

 Fungsi mysqli_connect_db(), yang ada pada baris 18, harus berisi 2


argumen. Yang pertama adalah koneksi, yang kedua adalah nama
database.

 Dengan memilih database, kita tidak perlu menulis nama database


pada setiap query yang kita jalankan, contoh query tabel pelanggan
dan penjualan_detail pada database toko_buku, sebelum memilih
database: 'SELECT * FROM toko_buku.pelanggan,
toko_buku.penjualan_detail' setelah memilih database, cukup
menuliskan 'SELECT * FROM pelanggan, penjualan_detail'.

Panduan Lengkap Query MySQL 505


 Setiap fungsi mysqli_select_db() dijalankan, maka default database
yang digunakan akan berubah.

29.5. Statemen SELECT Dengan Hasil Satu


Baris
Untuk menjalankan query SQL, kita gunakan fungsi mysqli_query().
Fungsi ini selalu kita gunakan setiap kali kita menjalankan query, baik pada
statemen SELECT, INSERT, UPDATE, maupun DELETE. Contoh
penggunaannya adalah:

File: 03_query_select.php

1. <html>
2. <head>
3. <title>Koneksi MySQL</title>
4. </head>
5. <body>
6. <?php
7. $host = 'localhost';
8. $user = 'root';
9. $pass = '';
10. $conn = mysqli_connect($host, $user, $pass);
11.
12. if (!$conn) {
13. die ('Gagal terhubung dengan MySQL');
14. }
15.
16. mysqli_select_db($conn, 'toko_buku') OR
die('Database toko_buku tidak ditemukan');
17.
18. $query = mysqli_query($conn, 'SELECT COUNT(*) AS
jumlah FROM pelanggan');
19. $row = mysqli_fetch_assoc($query);
20. echo $row['jumlah'];
21. ?>
22. </body>
23. </html>

Hasil pada browser: 9

506 BAB 29 MySQL dan PHP


Penjelasan:

 Fungsi mysqli_query() harus berisi dua argumen, yang pertama


adalah resource koneksi dan yang kedua adalah statemen SQL. Ketika
fungsi tersebut dijalankan, php akan menyimpan hasilnya di tempat
tertentu (biasanya file temporary).

 Selanjutnya dengan fungsi mysqli_fetch_assoc(), kita ambil data


tersebut, hasilnya kita simpan pada variabel $row. Untuk mengambil
hasil query dalam bentuk array, kita dapat menggunakan fungsi
mysqli_fetch_array(), mysqli_fetch_assoc(), dan
mysqli_fetch_row(). Perbedaan ketiganya adalah:

1. $row = mysqli_fetch_assoc($query);
2. print_r($row);
3. /* Array
4. (
5. [jumlah] => 9
6. )*/
7.
8. $row = mysqli_fetch_array($query);
9. print_r($row);
10. /* Array
11. (
12. [0] => 9
13. [jumlah] => 9
14. )*/
15.
16. $row = mysqli_fetch_row($query);
17. print_r($row);
18. /*Array
19. (
20. [0] => 9
21. )*/

 Setiap kali fungsi tersebut dijalankan, maka akan mengambil baris


berikutnya, karena hasil pada query diatas hanya satu baris, maka jika
kita memanggil lagi fungsi mysqli_fetch_assoc(), maka tidak ada
output yang dihasilkan.

Panduan Lengkap Query MySQL 507


29.6. Statemen SELECT Dengan Hasil Banyak
Baris
Untuk mengolah data hasil dari statemen SELECT yang menghasilkan baris
lebih dari satu, maka kita perlu menggunakan cara berbeda. Contoh:

File: 04_query_select_multi.php

1. <html>
2. <head>
3. <title>Koneksi MySQL</title>
4. </head>
5. <body>
6. <?php
7. $host = 'localhost';
8. $user = 'root';
9. $pass = '';
10. $conn = mysqli_connect($host, $user, $pass);
11.
12. if (!$conn) {
13. die ('Gagal terhubung dengan MySQL');
14. }
15.
16. mysqli_select_db($conn, 'toko_buku') OR
die('Database toko_buku tidak ditemukan');
17.
18. $query = mysqli_query($conn, 'SELECT * FROM buku
ORDER BY tgl_terbit DESC LIMIT 5');
19.
20. if (mysqli_num_rows($query) == 0)
21. {
22. echo 'Data tidak ditemukan';
23. }
24. else
25. {
26. while ($row = mysqli_fetch_assoc($query))
27. {
28. echo 'Judul: ' . $row['judul'] . ',
29. Terbit: ' . $row['tgl_terbit'] . '<br/>';
30.
31. }
32. }

508 BAB 29 MySQL dan PHP


33. mysqli_free_result($query);
34. mysqli_close($conn);
35. ?>
36. </body>
37. </html>

Hasil pada browser:

Judul: Desain Grafis dengan Powerpoint, Terbit: 2016-08-29


Judul: Otodidak Membuat Blog dengan Blogger, Terbit: 2016-02-29
Judul: Kumpulan Aplikasi PHP untuk Pemula, Terbit: 2016-02-25
Judul: Pemrograman Database Menggunakan MySQL, Terbit: 2016-00-00
Judul: PHP dan MySQL Langkah Demi Langkah + CD, Terbit: 2016-00-00

Penjelasan:

 Setelah menjalankan statemen SELECT, dengan fungsi


mysqli_num_rows kita tes apakah statemen tersebut menghasilkan
data, jika tidak, maka akan mencetak output "Data tidak ditemukan",
jika ada data, maka cetak data tersebut.

 Pada contoh sebelumnya, kita telah membahas bahwa ketika fungsi


mysqli_fetch_assoc() dijalankan, maka fungsi tersebut akan
mengambil data hasil query baris per baris, pada contoh kali ini, agar
tidak melakukan pengulangan secara manual, kita jalankan fungsi
mysqli_fetch_assoc() di dalam loop while (baris 26), jika baris
sudah habis, maka fungsi tersebut bernilai null, sehingga loop while
akan berhenti.

 Selama program masih berjalan, maka hasil query akan tetap


tersimpan dalam memory komputer, untuk menghapusnya (agar
ruang memory bertambah) kita gunakan fungsi
mysqli_free_result(), fungsi ini tidak harus dijalankan, karena
setelah eksekusi script berakhir, PHP otomatis akan menghapus semua
hasil query yang ada di memory. Gunakan fungsi ini hanya jika banyak
query yang dijalankan yang menghasilkan data dalam jumlah besar.

 Hal ini juga berlaku untuk koneksi mysql, selama program masih
berjalan, koneksi tersebut akan terus terbuka, untuk menutupnya, kita

Panduan Lengkap Query MySQL 509


gunakan fungsi mysqli_close(). Fungsi ini juga tidak harus
dijalankan, karena, pada akhir eksekusi, PHP akan menutup semua
koneksi yang ada.

Contoh: mengambil data pada urutan tertentu.

File: 05_query_select_tertentu.php

1. <html>
2. <head>
3. <title>Koneksi MySQL</title>
4. </head>
5. <body>
6. <?php
7. $host = 'localhost';
8. $user = 'root';
9. $pass = '';
10. $conn = mysqli_connect($host, $user, $pass);
11.
12. if (!$conn) {
13. die ('Gagal terhubung dengan MySQL');
14. }
15.
16. mysqli_select_db($conn, 'toko_buku') OR
die('Database toko_buku tidak ditemukan');
17.
18. $query = mysqli_query($conn, 'SELECT * FROM buku
ORDER BY tgl_terbit DESC LIMIT 5');
19.
20. mysqli_data_seek($query, 2);
21. $row = mysqli_fetch_assoc($query);
22. echo $row['judul'];
23. ?>
24. </body>
25. </html>

Hasil: Kumpulan Aplikasi PHP untuk Pemula

Penjelasan:

Pada data hasil query, kita dapat mengambil data pada baris tertentu, yaitu
menggunakan fungsi mysqli_data_seek(). Baris tersebut diurutkan

510 BAB 29 MySQL dan PHP


mulai dari index 0, sehingga, pada contoh diatas, jika kita ingin mengambil
data ketiga, kita gunakan index 2.

Selain menggunakan fungsi mysqli_data_seek(), untuk memperoleh


hasil yang sama, kita dapat menggunakan klausa LIMIT

SELECT * FROM buku ORDER BY tgl_terbit DESC LIMIT 2, 1

Query diatas akan mengambi data mulai index 2 sebanyak 1 data.

29.7. Tes Nilai NULL


Pada database, suatu kolom dapat memiliki nilai NULL dan bisa juga string
kosong "". Berikut ini contoh bagaimana menguji nilai tersebut
menggunakan PHP

File: 06_tes_null.php

1. <html>
2. <head>
3. <title>Koneksi MySQL</title>
4. </head>
5. <body>
6. <?php
7. $host = 'localhost';
8. $user = 'root';
9. $pass = '';
10. $conn = mysqli_connect($host, $user, $pass);
11.
12. if (!$conn) {
13. die ('Gagal terhubung dengan MySQL');
14. }
15.
16. mysqli_select_db($conn, 'toko_buku') OR
17. die('Database toko_buku tidak ditemukan');

18. $sql = 'SELECT * FROM penerbit';


19. $query = mysqli_query($conn, $sql);
20. while($row = mysqli_fetch_assoc($query))
21. {
22. $no_telp = $row['telp'] ?: 'belum ada';

Panduan Lengkap Query MySQL 511


23. echo 'Nama: ' . $row['nama'] . ', telp: '
24. . $no_telp . '<br/>';
}
25. ?>
26. </body>
27. </html>
28.

Hasil:

Nama: Andi Publisher, telp: 0274-561881


Nama: Informatika, telp: 0813-2220-1946
Nama: PT. Elex Media Komputindo, telp: belum ada
Nama: Jubilee, telp: belum ada
Nama: Lokomedia, telp: 0274-9515000
Nama: Maxikom, telp: 0711-7336565

Penjelasan:

 Pada query diatas, kita tes nilai pada kolom telp (baris 22), jika ada
nilainya, maka variabel $no_telp akan bernilai $row['telp'],
sedangkan jika kosong, akan bernilai 'belum ada'. Pada contoh diatas,
kita melakukan pengujian menggunakan ternary operator yang
diperpendek, yang dalam bentuk panjangnya

$no_telp = $row['telp'] != '' ? $row['telp'] : 'belum ada';

atau

if ($row['telp'] == '') {
$no_telp = 'belum ada';
} else {
$no_telp = $row['telp'];

 Pada PHP, jika kita menggunakan tanda sama dengan sebanyak dua (
== ) maka, baik nilai NULL maupun string kosong ( "" ) akan bernilai
sama. Jika kita ingin membedakan nilai NULL dengan string kosong,

512 BAB 29 MySQL dan PHP


kita gunakan tanda sama dengan sebanyak tiga ( === ), tanda ini akan
membedakan baik nilai maupun tipe data, misal:

if ($row['telp'] === NULL) {


$no_telp = 'NULL';
} elseif ($row['telp'] === '') {
$no_telp ='belum ada';
} else {
$no_telp = $row['telp'];
}

29.8. Membuat Stored Procedure


Query yang digunakan untuk membuat MySQL Stored Procedure melalui
PHP agak berbeda dengan ketika menggunakan aplikasi database manager.
Pada pembahasan kita pada bab Stored Procedure, kita harus mengubah
delimiter dengan statemen DELIMITER, pada PHP, kita tidak bisa
menggunakan statemen ini.

Misal pada contoh kali ini kita akan membuat Stored Procedure dengan
nama penjualan_perbulan yang berfungsi untuk menampilkan total nilai
penjualan pada suatu bulan dan banyaknya transaksi yang terjadi pada
bulan tersebut

File: 07_stored_procedure_buat.php

1. <html>
2. <head>
3. <title>Koneksi MySQL</title>
4. </head>
5. <body>
6. <?php
7. $host = 'localhost';
8. $user = 'root';
9. $pass = '';
10. $conn = mysqli_connect($host, $user, $pass);
11.
12. if (!$conn) {
13. die ('Gagal terhubung dengan MySQL');
14. }

Panduan Lengkap Query MySQL 513


15.
16. mysqli_select_db($conn, 'toko_buku') OR
die('Database toko_buku tidak ditemukan');
17.
18. $sql = 'CREATE PROCEDURE penjualan_bulanan (
19. bulan INT,
20. OUT total INT,
21. OUT jml_trx INT
22. )
23. BEGIN
24. SELECT SUM(total_trx), COUNT(total_trx)
25. INTO total, jml_trx
26. FROM penjualan
27. WHERE MONTH(tgl_trx) = bulan;
28. END';
29.
30. if (!mysqli_query($conn, $sql) )
31. {
32. echo mysqli_error($conn);
33. } else {
34. echo 'Procedure penjualan_bulanan berhasil
dibuat';
35. }
36. ?>
37. </body>
38. </html>

Jika tidak terjadi error, output yang dihasilkan: Procedure


penjualan_perbulan berhasil dibuat

Penjelasan:

 Pada baris 29, pada statemen if(!mysqli_query()), pertama tama


PHP akan menjalankan fungsi mysqli_query, selanjutnya dengan
statemen if, kita cek apakah fungsi tersebut menghasilkan nilai, jika
tidak, maka telah terjadi error, error tersebut kita tampilkan
menggunakan fungsi mysqli_error().

 Jika kita jalankan script tersebut dua kali, maka yang kedua akan
menghasilkan output: PROCEDURE penjualan_perbulan already exists

514 BAB 29 MySQL dan PHP


Selanjutnya, untuk memanggil stored procedure tadi, kita gunakan fungsi
yang biasa kita gunakan untuk memanggil query, yaitu mysqli_query()

1. <html>
2. <head>
3. <title>Koneksi MySQL</title>
4. </head>
5. <body>
6. <?php
7. $host = 'localhost';
8. $user = 'root';
9. $pass = '';
10. $conn = mysqli_connect($host, $user, $pass);
11.
12. if (!$conn) {
13. die ('Gagal terhubung dengan MySQL');
14. }
15.
16. mysqli_select_db($conn, 'toko_buku') OR
die('Database toko_buku tidak ditemukan');
17.
18. $sql = 'CALL penjualan_bulanan(3,
@total_penjualan, @jumlah_penjualan)';
19. mysqli_query($conn, $sql);
20.
21. $sql = 'SELECT @total_penjualan AS total,
@jumlah_penjualan AS jumlah';
22. $query = mysqli_query($conn, $sql);
23. $row = mysqli_fetch_assoc($query);
24. print_r($row);
25. ?>
26. </body>
27. </html>

Hasil: Array ( [total] => 1135000 [jumlah] => 4 )

Penjelasan:

 Dengan statemen CALL, kita panggil stored procedure (sp)


penjualan_bulanan. Pada contoh diatas, kita ambil total penjualan
pada bulan 3, output dari sp tersebut kita simpan pada variabel
@total_penjualan dan @jumlah_penjualan

Panduan Lengkap Query MySQL 515


 Selanjutnya, pada query berikutnya, kita panggil variabel
@total_penjualan dan @jumlah_penjualan

29.9. Membuat Transaksi


Pembuatan transaksi menggunakan PHP telah dibahas pada BAB
Transaction. Untuk memahami lebih jauh penerapan transaksi pada PHP,
berikut ini disajikan contoh lain dari transaksi:

1. <html>
2. <head>
3. <title>Koneksi MySQL</title>
4. </head>
5. <body>
6. <?php
7. $host = 'localhost';
8. $user = 'root';
9. $pass = '';
10. $conn = mysqli_connect($host, $user, $pass);
11.
12. if (!$conn) {
13. die ('Gagal terhubung dengan MySQL');
14. }
15.
16. mysqli_select_db($conn, 'toko_buku') OR die('Database
toko_buku tidak ditemukan');
17. mysqli_begin_transaction($conn);
18.
19. $sql_error = 0;
20. $query = mysqli_query($conn, 'DELETE FROM user' );
21. if (!$query)
22. $sql_error = 1;
23.
24. $query = mysqli_query($conn, 'INSERT INTO user VALUES
("sandi", "' . md5('sandi123') . '", "yola@email.com")' );
25. if (!$query)
26. $sql_error = 1;
27.
28. $query = mysqli_query($conn, 'INSERT INTO user VALUES
("zoga", "' . md5('zoga123') . '", "yola@email.com")' );
29. if (!$query)
30. $sql_error = 1;

516 BAB 29 MySQL dan PHP


31.
32. if ($sql_error) {
33. echo 'Transaksi Gagal. ERROR:'
.mysqli_error($conn);
34. mysqli_rollback($conn);
35. } else {
36. echo 'Data berhasil ditambahkan';
37. mysqli_commit($conn);
38. }
39.
40. ?>
41. </body>
42. </html>

Pada query diatas kita membuat transaksi

Ketika dijalankan, hasil yang kita peroleh: Transaksi Gagal. ERROR:


Duplicate entry 'yola@email.com' for key 'email'

Penjelasan:

 Pada transaksi diatas, kita menjalankan 3 proses manipulasi data,


yaitu menghapus semua data pada tabel user (baris 20) dan
memasukkan dua data ke tabel user (baris 24 dan baris 28)

 Kolom email bersifat unik, sehingga tidak boleh ada data yang sama,
pada contoh diatas, karena pada data kedua, data email sama dengan
yang pertama, maka muncul pesan error. Karena terjadi error, maka
variabel $sql_error bernilai 1. Ketika kita tes nilai variabel tersebut
(baris 33), maka akan bernilai true, sehingga transaksi dibatalkan dan
data dikembalikan seperti semula.

29.10. Lintas Database


Ketika memilih database menggunakan fungsi mysqli_select_db(), kita
hanya mendefinisikan default database sehingga ketika menjalankan
statemen SELECT, kita tidak perlu menuliskan nama database, MySQL
otomatis menambahkannya pada nama tabel yang kita gunakan, pada
kondisi ini, kita tetap dapat menggunakan database lain, sepanjang masih
dalam satu koneksi yang sama. Misal:

Panduan Lengkap Query MySQL 517


1. <html>
2. <head>
3. <title>Koneksi MySQL</title>
4. </head>
5. <body>
6. <?php
7. $host = 'localhost';
8. $user = 'root';
9. $pass = '';
10. $conn = mysqli_connect($host, $user, $pass);
11.
12. if (!$conn) {
13. die ('Gagal terhubung dengan MySQL');
14. }
15.
16. mysqli_select_db($conn, 'toko_buku') OR
die('Database toko_buku tidak ditemukan');
17.
18. $sql = 'SELECT nama, koordinat
19. FROM pelanggan
20. LEFT JOIN webmap.data USING (id_marker)
21. WHERE id_pelanggan = 1';
22.
23. $query = mysqli_query($conn, $sql);echo '<pre>';
24. while($row = mysqli_fetch_assoc($query))
25. {
26. echo 'Nama : ' . $row['nama'] . '.
Koordinat Lokasi : ' . $row['koordinat'];
27. }
28. ?>
29. </body>
34. </html>

Hasil: Nama : Anton. Koordinat Lokasi : -6.805117,110.849133

Penjelasan:

Pada contoh diatas, dengan klausa LEFT JOIN, kita gabungkan data pada
tabel pelanggan yang ada pada database toko_buku dan tabel data yang
ada pada database webmap, pada penulisan tabel data, harus kita dahului
dengan menuliskan nama database yaitu webmap, karena database yang
sedang aktif adalah database toko_buku

518 BAB 29 MySQL dan PHP


DAFTAR PUSTAKA
Arie D. Jones, Ron D. Plew, Ryan Stephens, 2011, Sams Teach Yourself SQL
in 24 Hours, Fifth Edition. USA: Sams

Ben Forta, 2012. Sams Teach Yourself SQL in 10 Minutes, Fourth Edition.
USA: Sams

Djoni Darmawikarta, 2014. SQL for MySQL: A Beginner's Tutorial. Canada:


Brainy Software

Keith Murphy, Sheeri K. Cabral, 2009. MySQL® Administrator's Bible. USA:


John Wiley & Sons

Larry Rockoff, 2016, The Language of SQL. USA: Pearson Education, Inc

Paul DuBois, 2013. MySQL, Fifth Edition. USA: Addison-Wesley


Professional

Rick F. van der Lans, 2007. SQL for MySQL Developers: A Comprehensive
Tutorial and Reference. USA: Addison-Wesley

Timothy Boronczyk, 2015, Jump Start MySQL: Master the Database That
Powers the Web. USA: Sitepoint

URL:

http://mysql.com

http://safaribookonline.com

http://jagowebdev.com

http://www.mysqltutorial.org

Panduan Lengkap Query MySQL 519

Anda mungkin juga menyukai