1. Cepat. Kecepatan ini didapat dari pengurangan network traffic, dikarenakan stored procedures
memanfaatkan caching. Jika ada repetitive task yang memerlukan banyak proses seperti checking,
looping, multiple statements, lebih baik dilakukan dengan pemanggilan stored procedure yang
disimpan di server.
2. Portable. Menuliskan logika pemrograman di MySQL dirasa lebih portable dibandingkan
menuliskan statement tersebut di bahasa pemrograman seperti Java, C, atau PHP.
3. Availability. Stored procedures selalu tersedia sebagai 'source code' di database itu sendiri.
1. Resource usage. Penggunaan stored procedure yang membutuhkan banyak operasi lojik akan
meningkatkan CPU usage.
2. Troubleshooting. Cukup sulit untuk melakukan debugging terhadap stored procedure pada
MySQL.
3. Maintenance. Menggunakan stored procedure membutuhkan specialized skill set terhadap
application developer, sehingga berkemungkinan menimbulkan masalah saat proses develop dan
maintenance.
Pada modul ini, kita akan melihat penggunaan dari stored procedure pada sample database yang
digunakan juga di modul sebelumnya. Database ini bernama classicmodels.
1.1.1. Stored Procedure
Syntax umum dari stored procedure adalah
DELIMITER $$
DELIMITER ;
Stored procedure memiliki berbagai berbagai statement lojik yang setiap statement tersebut dipisahkan
dengan titik koma. Akan tetapi, walaupun memiliki berbagai statement, stored procedure adalah 1
kesatuan. Sehingga, diperlukan pengubahan default delimiter yang tadinya berupa semicolon menjadi
karakter yang lain. Karakter yang biasanya digunakan adalah “$$” atau “//”. Sehingga, pada penulisan
sebelum stored procedure terdapat keyword “DELIMITER $$” yang mengubah bentuk default dari
delimiter, dan di akhir penulisan terdapat pengubahan delimiter kembali ke mode default, yaitu
semicolon.
Pada DBeaver, store procedure dapat dilihat pada bagian Procedures dari database.
Kali ini kita akan membuat store procedure yang memperlihatkan 7 data di table product dengan
quantityInStock terbanyak. Untuk mendapatkan hasil tersebut, biasanya kita menuliskan query:
SELECT productName,
productVendor,
quantityInStock
FROM products
ORDER BY quantityInStock DESC
LIMIT 7;
Tapi sekarang kita tuliskan dalam stored procedure. Pada DBeaver, untuk menambahkan stored
procedure, klik kanan pada bagian yang kosong dan pilih “Create New Procedure”.
Berikutnya, muncul pop-up window untuk meminta nama procedure. Masukkan “getTop7StockProduct”
sebagai nama procedure. Nama ini boleh bebas, tapi sebaiknya ringkas dan deskriptif terhadap lojik
statement-nya. Lalu, pada bagian source, masukkan query yang sebelumnya sudah dipastikan
menampilkan 7 produk dengan stok terbanyak. Dan tekan save.
Setelah menekan save, akan muncul pop-up window untuk memperlihatkan syntax dari stored procedure.
Klik “Open Editor” jika masih ada perubahan yang harus dilakukan, atau klik “Persist” jika sudah sesuai
dengan yang diinginkan.
Stored procedure sudah tersimpan setelah menekan tombol “Persist”. Untuk menggunakannya, dapat
dilakukan dengan menggunakan syntax:
CALL nama_procedure(argumen);
Query di atas juga dapat dipanggil dari bahasa pemrograman. Pada Java, query ini dipanggil menggunakan
CallableStatement.
Kembali pada procedure “” yang telah kita buat sebelumnya, untuk mengeksekusi query berikut bisa
dilakukan dengan cara mengeksekusi query
CALL getTop7StockProduct();
a) IN: merupakan mode default dari stored procedure. Parameter ini sama sifatnya seperti
parameter di bahasa pemrograman yang pernah dipelajari seperti Java.
b) OUT: parameter yang nilainya akan diberikan kepada syntax pemanggil melalui annotasi @. Tidak
ada nilai awal yang dilewatkan pada saat pemanggilan procedure.
c) INOUT: parameter kombinasi antara IN dan OUT.
Contoh penggunaan parameter IN dapat dilihat pada kasus ketika ingin menampilkan data office
berdasarkan country name-nya.
DELIMITER $$
$$
CREATE PROCEDURE classicmodels.GetOfficeByCountry(IN countryName VARCHAR(255))
BEGIN
SELECT *
FROM offices
WHERE country = countryName;
END $$
DELIMITER ;
CALL classicmodels.GetOfficeByCountry('USA');
Contoh penggunaan parameter OUT dapat dilihat pada kasus ketika ingin menampilkan jumlah data pada
table office.
DELIMITER $$
$$
CREATE PROCEDURE classicmodels.getCountOffice(OUT total INT)
BEGIN
SELECT COUNT(officeCode)
INTO total
FROM offices;
END$$
DELIMITER ;
CALL classicmodels.getCountOffice(@jumlah);
SELECT @jumlah;
Contoh penggunaan parameter INOUT dapat dilihat pada kasus berikut yang memperlihatkan counter
(penghitung dari nilai masukan pengguna).
DELIMITER $$
$$
CREATE PROCEDURE classicmodels.SetCounter(INOUT counter INT, IN inc INT)
BEGIN
SET counter = counter + inc;
END
$$
DELIMITER ;
SET @counter = 1;
CALL SetCounter(@counter,1);
CALL SetCounter(@counter,1);
CALL SetCounter(@counter,5);
SELECT @counter;
Pada eksekusi di atas, awalnya kita memberikan nilai 1 untuk counter. Setelahnya dilakukan pemanggilan
SetCounter dengan penambahan 1 untuk counter yang bernilai 1, sehingga sekarang counter bernilai 2.
Pada eksekusi berikutnya, counter bernilai 3, dan bernilai 8 pada pemanggilan procedure ke-3. Nilai 8 akan
ditampilkan ketika dilakukan SELECT dari variable counter.
1.1.2. Stored Procedure – Conditional
Stored Procedure dapat mengandung lojik pemrograman seperti kondisional. Terdapat beberapa
kondisional yang bisa digunakan, yaitu IF-THEN; IF-THEN-ELSE; IF-THEN-ELSEIF-ELSE; CASE-WHEN; CASE-
WHEN-ELSE. Masing-masing syntax dituliskan sebagai berikut:
CASE-WHEN CASE-WHEN-ELSE
CASE case_value CASE case_value
WHEN when_value1 THEN statements WHEN when_value1 THEN ...
WHEN when_value2 THEN statements WHEN when_value2 THEN ...
... ELSE
END CASE; BEGIN
END;
END CASE;
Contohnya, pada kasus di bawah ini digunakan IF-THEN-ELSEIF-ELSE untuk menentukan tipe level dari
customer berdasarkan credit limit-nya.
DELIMITER $$
$$
CREATE PROCEDURE classicmodels.GetCustomerLevel(
IN pCustomerNumber INT,
OUT pCustomerLevel VARCHAR(20))
BEGIN
DECLARE credit DECIMAL DEFAULT 0;
SELECT creditLimit
INTO credit
FROM customers
WHERE customerNumber = pCustomerNumber;
Contoh kasus berikut menampilkan lama pengiriman berdasarkan customerNumber yang diberikan.
DELIMITER $$
$$
CREATE PROCEDURE classicmodels.GetCustomerShipping(
IN pCustomerNUmber INT,
OUT pShipping VARCHAR(50)
)
BEGIN
DECLARE customerCountry VARCHAR(100);
SELECT
country
INTO customerCountry FROM
customers
WHERE
customerNumber = pCustomerNUmber;
CASE customerCountry
WHEN 'USA' THEN
SET pShipping = '2-day Shipping';
WHEN 'Canada' THEN
SET pShipping = '3-day Shipping';
ELSE
SET pShipping = '5-day Shipping';
END CASE;
END
$$
DELIMITER ;
CALL GetCustomerShipping(112,@shipping);
SELECT @shipping;
DELIMITER $$
$$
CREATE PROCEDURE classicmodels.LoopDemo()
BEGIN
DECLARE x INT;
DECLARE str VARCHAR(255);
SET x = 1;
SET str = '';
loop_label: LOOP
IF x > 10 THEN
LEAVE loop_label;
END IF;
SET x = x + 1;
IF (x mod 2) THEN
ITERATE loop_label;
ELSE
SET str = CONCAT(str,x,',');
END IF;
END LOOP;
SELECT str;
END
$$
DELIMITER ;
CALL LoopDemo();
DROP PROCEDURE IF EXISTS classicmodels.WhileDemo;
DELIMITER $$
$$
CREATE PROCEDURE classicmodels.WhileDemo()
BEGIN
DECLARE counter INT DEFAULT 1;
DECLARE str VARCHAR(100) DEFAULT '';
CALL classicmodels.WhileDemo()
DELIMITER $$
$$
CREATE PROCEDURE classicmodels.RepeatDemo()
BEGIN
DECLARE counter INT DEFAULT 1;
DECLARE result VARCHAR(100) DEFAULT '';
REPEAT
SET result = CONCAT(result,counter,',');
SET counter = counter + 1;
UNTIL counter >= 10
END REPEAT;
SELECT result;
END
$$
DELIMITER ;
CALL classicmodels.RepeatDemo()
a) Mendeklarasikan cursor pada blok stored procedure & penanganannya jika result NOT FOUND
b) Memberikan statement untuk membuka cursor
c) Menuliskan statement FETCH yang bermaksud memberikan hasil cursor kepada variable yang
ditentukan. Statement ini erat berkaitan dengan klausa INTO
d) Memberikan statement untuk menutup cursor
Pada kasus berikut, terdapat pengambilan nilai email dari tabel employees menjadi 1 string utuh yang
dipisah dengan simbol semicolon (;).
DELIMITER $$
$$
CREATE PROCEDURE classicmodels.CreateEmailList(
INOUT emailList varchar(4000)
)
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE emailAddress varchar(100) DEFAULT "";
-- open cursor
OPEN curEmail;
-- close cursor
CLOSE curEmail;
END
$$
DELIMITER ;
DELIMITER $$
DELIMITER ;
Pada stored function, hanya terdapat IN parameter. Kita tidak dapat memberikan klausa IN, OUT, atau
INOUT pada parameter. Setiap function mengembalikan nilai yang ditentukan tipe datanya pada klausa
RETURNS. Sedangkan nilai yang dikembalikan dituliskan setelah keyword RETURN.
Di dalam stored function, kita dapat menuliskan keyword DETERMINISTIC yang function selalu
mengembalikan returns hasil yang sama untuk input parameters yang sama. Sedangkan jika tidak
dituliskan, artinya bersifat NOT DETERMINISTIC yang berarti sebaliknya, mengembalikan hasil yang
berbeda untuk input yang sama. Hal ini terkait dengan replikasi database. Modul ini tidak membahas lebih
lanjut tentang keyword ini.
Pada kasus di bawah ini, kita membuat sebuah function yang akan menentukan level dari customer
tergantung credit yang dimiliki. Jika credit > 50.000, termasuk ke kategori Platinum; credit antara 10.000-
50.000 termasuk ke dalam kategori GOLD; credit < 10.000 merupakan kategori SILVER.
Dengan menggunakan DBeaver, klik kanan pada Procedures, pilih “Create New Procedure”. Masukkan
informasi berikut:
Setelah menekan OK, tuliskan kode berikut, diikuti dengan aksi save:
Terdapat pemanggilan stored function CustomerLevel pada bagian SELECT. Hasil dari eksekusi query di
atas terlihat sebagai berikut:
1.1.6. Stored Object Access Control
Stored procedure dapat diatur agar hanya dapat diakses oleh beberapa user tergantung privilege-nya. Hal
ini diatur pada keyword SQL SECURITY terhadap keyword DEFINER yang ditulis sebelum pendefenisian
stored procedure atau stored function.
Akses untuk “getTop7StockProduct” akan dieksekusi sesuai privilege dari definer-nya, yaitu root dengan
ALL privileges.
DELIMITER $$
$$
CREATE DEFINER = root@localhost PROCEDURE classicmodels.getTop7StockProduct()
SQL SECURITY DEFINER
BEGIN
SELECT productName, productVendor, quantityInStock
FROM products
ORDER BY quantityInStock DESC
LIMIT 7;
END
$$
DELIMITER ;
User “adminsbd” masih dapat melakukan eksekusi dari procedure di atas karena statement “SQL
SECURITY DEFINER” artinya, user account apapun yang memanggil stored procedure akan dieksekusi
menggunakan privileges dari definer-nya yaitu root.
Akan tetapi ketika kita ubah kode menjadi
DELIMITER $$
$$
CREATE DEFINER = root@localhost PROCEDURE classicmodels.getTop7StockProduct()
SQL SECURITY INVOKER
BEGIN
SELECT productName, productVendor, quantityInStock
FROM products
ORDER BY quantityInStock DESC
LIMIT 7;
END
$$
DELIMITER ;
Maka eksekusi akan dilakukan sesuai dengan privilege yang dimiliki oleh pemanggil/invoker. Dalam hal
ini, user “adminsbd” akan mendapatkan error sebagai berikut:
User “adminsbd” akan mengalami kegagalan karena tidak memiliki privilege yang sesuai terhadap
statement yang terkandung pada stored procedure getTop7StockProduct(), yaitu privilege untuk
melakukan SELECT. Jika privilege ini ditambahkan, maka adminsbd tetap dapat mendapatkan result
walaupun SQL SECURITY INVOKER yang dituliskan pada stored procedure.
1.2. Referensi
Referensi yang digunakan pada modul kali ini berupa materi dan contoh diambil dari laman berikut:
Materi Referensi
Stored Procedure Full https://www.mysqltutorial.org/mysql-stored-procedure-tutorial.aspx/
https://www.w3resource.com/mysql/mysql-procedure.php
1.3. Assignment
Assignment Modul Minggu 4: Stored Procedure
Tuliskan kode stored procedure/function, cara pemanggilan, & hasil untuk menampilkan data yang
diminta pada kasus di bawah ini. Gunakan screenshot layar full yang terdapat identitas di dalamnya
untuk menampilkan hasil. Pastikan hasil dapat dibaca dengan baik.
Contoh screenshot:
1. Buatlah stored function untuk menentukan tipe buku berdasarkan jumlah halaman buku.
Jumlah halaman <200 termasuk ke dalam buku tipis; 200-400 adalah buku ketebalan normal;
>400 adalah buku tebal.
2. Buatlah stored procedure untuk menampilkan 3 buku termahal yang ditulis dengan bahasa
English. Data buku yang ditampilkan terdiri dari: book_name, book_price, dan cate_descript)
3. Buatlah stored procedure yang menurunkan harga buku sebanyak 10% dari harga normal untuk
categori (cate_id) yang diberikan dari input parameter. Gunakan bantuan cursor, perulangan,
& query update pada stored procedure ini.
4. Buatlah stored procedure yang menaikkan harga buku sebanyak 10% dari harga normal untuk
categori (cate_id) yang diberikan dari input parameter.
1.4. Penutup
Pada modul kali ini kita telah mengetahui materi tentang stored procedure dan juga stored function. Pada
stored procedure kita dapat membuat logika pemrograman seperti yang dimiliki bahasa pemrograman.