postgresql stored-procedure
Post on 20-Jun-2015
6.180 Views
Preview:
TRANSCRIPT
1 | S t o r e d P r o c e d u r e
Stored Procedure Function (pada PostgreSQL)
M. Ammar Shadiq
Ilmu Komputer Universitas Pendidikan Indonesia, Bandung
5 Mei 2008
Pertama-tama anda harus menginisiasikan procedural language (bahasa prosedural) pada
postgreSQL yang dinamakan PL/pgsql, perintahnya : CREATE LANGUAGE plpgsql;
TABEL YANG DIGUNAKAN :
DERET1 : (NILAI INTEGER)
CREATE TABLE deret1 (nilai integer);
DERET2 : (NILAI INTEGER, KOMENTAR CHARACTER(8))
CREATE TABLE deret2 (nilai integer, komentar character(8));
Dengan Dummy Data : (1), (2), (3), (4),(5)
INSERT INTO deret2 (nilai) VALUES (1),(2),(3),(4),(5);
ACCOUNT : (NAMA CHARACTER(50), SALDO INTEGER, CABANG CHARACTER(50))
CREATE TABLE account (nama character(50),saldo integer,cabang
character(50);
Dengan Dummy Data : (shadiq, Rp. 100.000, Bogor), (Alice, Rp. 1.000.000, Bogor), (Bob, Rp. 700.000,
Bandung), (Wally, Rp. 500.000, Bandung)
INSERT INTO account VALUES
('shadiq',100000,'Bogor'),
('Alice',1000000,'Bogor'),
('Bob',700000,'Bandung'),
('Wally',500000,'Bandung');
2 | S t o r e d P r o c e d u r e
PENDAHULUAN
Contoh 1 :
Fungsi untuk mengisi field nim pada tabel deret1 dengan nilai deret 0, 2, 4, ... , 100.
CREATE OR REPLACE FUNCTION isi_deret1() RETURNS void AS $$
DECLARE
counter integer;
BEGIN
counter := 0;
loop
insert into deret1(nilai) values (counter);
counter := counter + 2;
if (counter > 100) then
exit;
end if;
end loop;
return;
END;
$$ LANGUAGE 'plpgsql';
Eksekusi fungsi diatas :
SELECT isi_deret1();
isi_deret1
---------
(1 row)
Cek isi tabel deret1 yang sudah di modifikasi :
SELECT * FROM deret1;
Untuk melihat fungsi yang ada pada PostgreSQL anda dapat menuliskan perintah berikut :
Melihat semua fungsi
\df
Melihat fungsi tertentu
\df <nama_fungsi>
Melihat isi fungsi
\df+ <nama_fungsi>
3 | S t o r e d P r o c e d u r e
STRUKTUR FUNGSI PADA PL/PGSQL
CREATE [OR REPLACE] FUNCTION nama_fungsi ( [ argtype [, ...] ] )
RETURNS return_type
AS $$definition$$
LANGUAGE langname
[ WITH ( attribute [, ...] ) ]
MENGHAPUS FUNGSI
DROP FUNCTION nama_fungsi(paramater[, parameter[, parameter ... );
Ex :
DROP FUNCTION isi_deret11();
BADAN FUNGSI
DECLARE
/* deklarasi variabel, type dan subprogram lokal */
BEGIN
/* prosedural dan SQL masuk disini */
/ blok ini yang wajib */
END;
DEKLARASI VARIABEL :
Contoh :
DECLARE
v_counter INTEGER;
v_nim CHAR(5);
v_nama VARCHAR(2);
v_nilai NUMBER;
v_nim_2 mahasiswa.nim%TYPE /* tipe variabel mengikuti tipe field mahasiswa.nim */
mengapa menggunakan huruf depan v_? Supaya tidak bentrok dengan nama field. Contoh :
INSERT INTO mahasiswa (nim, nama) VALUES (v_nim, v_nama);
Nilai variabel juga dapat diinisiasikan saat pembuatannya. Contoh :
v_nilai_minimum INTEGER := 30;
Deklarasi Variabel pada Pembuatan Fungsi :
Pendeklarasian variabel dapat juga dilakukan pada pembuatan fungsi, dengan konsekuensi varibel
tersebut HARUS menjadi parameter input atau output.
4 | S t o r e d P r o c e d u r e
Contoh 2 :
Fungsi untuk mengisi field nim pada tabel deret1 dengan nilai deret 0 s/d nilai yang di
tentukan dengan penambahan nilai +2 tiap iterasi.
CREATE OR REPLACE FUNCTION isi_deret2(sampai_dengan integer) RETURNS void
AS $$
DECLARE
counter integer;
BEGIN
counter := 0;
loop
insert into deret1(nilai) values (counter);
counter := counter + 2;
if (counter>sampai_dengan) then
exit;
end if;
end loop;
return;
END;
$$ LANGUAGE 'plpgsql';
Pengeksekusian dilakukan dengan memasukkan parameter.
SELECT isi_deret2(60);
isi_deret2
---------
(1 row)
Fungsi diatas akan memasukkan nilai 0, 2, 4, ..., 60 pada tabel deret1.
Untuk menghapus fungsi dengan parameter masukan menggunakan perintah :
DROP FUNCTION isi_deret2(integer);
JENIS-JENIS VARIABEL PARAMETER FUNGSI.
Ada tiga jenis parameter :
IN : variabel input (default)
OUT : variabel output
INOUT : variabel input dan output
Jika anda memperhatikan contoh-contoh fungsi diatas, pada waktu pendeklarasian fungsi ada
parameter output yang ditandakan dengan RETURNS tipe_data.
CREATE OR REPLACE FUNCTION isi_deret2(sampai_dengan integer) RETURNS void
AS $$..........
5 | S t o r e d P r o c e d u r e
Pada contoh diatas karena fungsi tersebut tidak menghasilkan suatu nilai, maka parameter
outputnya diisikan dengan tipe data VOID*.
* Fungsi dengan parameter output void artinya tidak menghasilkan suatu nilai (tidak mengembalikan nilai) atau biasa disebut fungsi
kosong. void : kekosongan, kehampaan (Kamus Inggris-Indonesia, John M. Echoles)
Untuk lebih jelasnya, perhatikan contoh-contoh fungsi dibawah ini :
Contoh 3 : CREATE FUNCTION contoh_parameter_1 (IN sampai_dengan integer) RETURNS void AS $$
DECLARE
counter integer;
BEGIN
counter := 0;
loop
insert into deret1(nilai) values (counter);
counter := counter + 2;
if (counter>sampai_dengan) then
exit;
end if;
end loop;
return;
END;
$$ LANGUAGE 'plpgsql';
Fungsi ini sama dengan fungsi isi_deret2(integer) namun dengan penulisan yang berbeda.
Karena sebenarnya IN adalah parameter default, sebenarnya tidak perlu di tuliskan, hal ini
dimaksudkan agar dapat dimengerti.
Contoh 4 : CREATE FUNCTION contoh_parameter_2 (IN sampai_dengan integer) RETURNS integer AS $$
DECLARE
counter integer;
BEGIN
counter := 0;
loop
insert into deret1(nilai) values (counter);
counter := counter + 2;
if (counter>sampai_dengan) then
exit;
end if;
end loop;
RETURN counter;
END;
$$ LANGUAGE 'plpgsql';
Fungsi ini memberi nilai keluaran yaitu counter dengan tipe data integer. Saat ada nilai keluaran,
konsekwensinya harus ada deklarasi RETURN yang menentukan nilai apa yang di keluarkan.
6 | S t o r e d P r o c e d u r e
Contoh 5 : CREATE FUNCTION contoh_parameter_3 (IN sampai_dengan integer, OUT keluaran_sd integer) AS $$
DECLARE
counter integer;
BEGIN
counter := 0;
loop
insert into deret1(nilai) values (counter);
counter := counter + 2;
if (counter>sampai_dengan) then
exit;
end if;
end loop;
keluaran_sd := counter;
END;
$$ LANGUAGE 'plpgsql';
Fungsi ini sama dengan fungsi contoh_parameter_2, namun tanpa deklarasi RETURNS pada awal
deklarasi fungsi, juga tanpa deklarasi RETURN pada badan fungsi. Sebagai ganti RETURN, digunakan
pengisian nilai variabel keluaran_sd dengan nilai variabel counter. Kita tetap dapat
menggunakan statement RETURN pada badan fungsi, namun hal ini akan menyebabkan redudansi.
Pilih salah satu saja.
Catatan : perhatikan perbedaan RETURN pada badan fungsi dan RETURNS pada deklarasi fungsi.
Dengan fungsi seperti ini, pemanggilannya dilakukan dengan hanya memasukkan nilai variabel
input saja.
SELECT contoh_parameter_3(60);
contoh_parameter_3
------------------
62
(1 row)
Pertanyaan : Kenapa hasil yang dikeluarkan 62 ? Jawaban : perhatikan bahwa fungsi diatas melakukan proses tiap iterasi dengan membandingkan variabel counter. Saat iterasi
sebelum terakhir (misal 60) fungsi membandingkan jika variabel counter > 60, karena nilai variabel counter belum melebihi 60 (tetapi sama dengan) maka iterasi dilakukan sekali lagi dan nilai variabel counter bertambah menjadi 62. Saat fungsi melakukan perbandingan kembali (counter > 60 [62>60]), maka kondisi tidak terpenuhi, tetapi nilai variabel counter adalah 62. Oleh karena itu hasil yang dikeluarkan adalah 62 bukan 60.
Contoh 6 :
Fungsi yang menghasilkan dua keluaran : CREATE FUNCTION contoh_parameter_4 (IN sampai_dengan integer, OUT keluaran_sd integer, OUT banyaknya_data integer) AS $$
DECLARE
counter1 integer;
counter2 integer;
BEGIN
counter1 := 0;
7 | S t o r e d P r o c e d u r e
counter2 := 0;
loop
insert into deret1(nilai) values (counter1);
counter1 := counter1 + 2; -- memasukkan nilai genap
counter2 := counter2 + 1; -- menghitung banyaknya iterasi
if (counter1>sampai_dengan) then
exit;
end if;
end loop;
keluaran_sd := counter1;
banyaknya_data := counter2;
END;
$$ LANGUAGE 'plpgsql';
Jika anda mengeksekusi fungsi ini dengan Variabel masukan sampai_dengan = 60, maka nilai
variabel keluarannya adalah keluaran_sd = 62, dan variabel banyaknya_data = 31 (0...60).
SELECT contoh_parameter_4(60);
contoh_parameter_4
------------------
(62,31)
(1 row)
Contoh 7 : CREATE FUNCTION contoh_parameter_5 (INOUT sampai_dengan integer) AS $$ DECLARE
counter integer;
BEGIN
counter := 0;
loop
insert into deret1(nilai) values (counter);
counter := counter + 2;
if (counter>sampai_dengan) then
exit;
end if;
end loop;
sampai_dengan := counter;
END;
$$ LANGUAGE 'plpgsql';
Dapat di perhatikan pada fungsi diatas, variabel input dan outputnya sama yaitu variabel
sampai_dengan.
SELECT contoh_parameter_5(60);
contoh_parameter_5
------------------
62
(1 row)
8 | S t o r e d P r o c e d u r e
BATASAN-BATASAN
Variabel input : tidak dapat diubah
Variabel output : tidak dapat di jadikan nilai referensi pada variabel lain.
Contoh :
CREATE FUNCTION contoh_parameter_salah (IN p_in integer, OUT p_out integer, INOUT p_inout integer) AS $$
DECLARE
local integer;
BEGIN
local := p_in;
local := p_inout;
p_out := p_in;
p_out := local
p_out := 5;
p_inout := p_in;
p_inout := local;
p_inout := 5;
p_in := 5; -- ERROR, INPUT tidak boleh diisi
p_in := local; -- ERROR, INPUT tidak boleh diisi
p_in := p_inout; -- ERROR, INPUT tidak boleh diisi
local := p_out; -- ERROR, OUTPUT tidak boleh digunakan
p_inout := p_out; -- ERROR, OUTPUT tidak boleh digunakan
p_in := p_out -- PARAH
END;
$$ LANGUAGE 'plpgsql';
Parameter output adalah parameter yang bernilai NULL, dan harus diisikan nilainya pada saat
eksekusi fungsi. Nilai akhir dari parameter adalah nilai yang di hasilkan(yang di RETURN) oleh fungsi
tersebut.
Oleh karena itu parameter output tidak boleh digunakan, karena bernilai NULL.
9 | S t o r e d P r o c e d u r e
ILUSTRASI VARIABEL PARAMETER FUNGSI
1. Fungsi yang menggunakan 1 parameter masukan IN dan parameter keluaran VOID (tidak ada
parameter
keluarnya)
2. Fungsi yang menggunakan 1 parameter masukan IN dan 2 parameter keluaran
OUT
3. Fungsi yang menggunakan 2 parameter masukan IN, 1 parameter keluaran OUT dan 2
parameter masuk keluar
INOUT
10 | S t o r e d P r o c e d u r e
CONTROL FLOW : LOOP
LOOP 1
LOOP
<loop_body>
EXIT WHEN kondisi_keluar
END LOOP;
Contoh : ...
counter := 0;
loop
insert into deret1(NILAI) values (counter);
counter := counter + 2;
EXIT WHEN counter > 100;
end loop;
...
LOOP 2
WHILE <condition> LOOP
<loop_body>
END LOOP;
Contoh : ...
counter := 0;
WHILE counter<= 100 LOOP
insert into deret1(NILAI) values (counter);
counter := counter + 2;
end loop;
...
LOOP 3
FOR <variabel> IN <start> .. <FINISH> LOOP
<loop_body>
END LOOP;
Contoh 1 : ...
counter := 0;
FOR counter IN 0 .. 100 LOOP
insert into deret1(NILAI) values (counter);
end loop;
...
Fungsi ini akan memasukkan nilai 0, 1, 2, 3, 4, ..., 100 (bilangan real).
11 | S t o r e d P r o c e d u r e
Catatan : variabel yang di pergunakan sebagai acuan LOOP FOR harus bertipe integer.
Contoh 2 : ...
counter := 0;
FOR counter IN 0 .. 100 BY 2 LOOP
insert into deret1(NILAI) values (counter);
end loop;
...
Fungsi ini akan memasukkan nilai 0, 2, 4, ..., 100 (bilangan genap). Karena nilai variabel counter di
tambah 2 tiap iterasi.
Contoh 3 : ...
counter := 0;
FOR counter IN REVERSE 0 .. 100 BY 2 LOOP
insert into deret1(NILAI) values (counter);
end loop;
...
Fungsi ini akan memasukkan nilai 100, 98, 96, ..., 0 (bilangan genap). Karena urutan LOOP di balik.
12 | S t o r e d P r o c e d u r e
CONDITIONAL
IF-THEN
IF <kondisi> THEN <statement> END IF;
Contoh : ...
if (counter > 100) then
exit;
end if;
...
IF - THEN - ELSE
IF <kondisi> THEN <statement>
ELSE <statement>
END IF;
Contoh : ...
IF posisi = 80 THEN komentar := „bagus‟
ELSE komentar := „biasa‟
END IF;
...
IF – THEN – ELSEIF – ELSE
IF <kondisi_1> THEN ...
ELSEIF <kondisi_2> THEN ... ...
ELSEIF <kondisi_3> THEN ... ... ...
ELSE ... ... ... ...
END IF;
Contoh : ...
IF number = 0 THEN
result := „enol‟;
ELSIF number > 0 THEN
result := „bilangan positif‟;
ELSIF number < 0 THEN
result := „bilangan negatif‟;
ELSE
-- hmm, satu-satunya kemungkinan lain adalah angka tersebut NULL
result := „NULL‟;
END IF;
...
13 | S t o r e d P r o c e d u r e
CURSOR
MENDEKLARASIKAN CURSOR
DECLARE
curs1 refcursor;
curs2 CURSOR FOR SELECT nilai FROM deret1;
curs3 CURSOR (key integer) IS SELECT * FROM deret1 WHERE nilai = key;
ketiga variabel ini bertipe data refcursor, tetapi curs1 dapat digunakan untuk semua query,
sedangkan yang kedua sudah memiliki query, dan yang terakhir memiliki query yang ber parameter
(key akan digantikan dengan nilai bertipe integer saat cursor di open).
Catatan :
curs2 CURSOR FOR SELECT * FROM deret1;
dengan curs2 CURSOR IS SELECT * FROM deret1;
memiliki fungsi yang sama
MEMBUKA CURSOR
Untuk curs2 diatas, perintah untuk membukanya : OPEN curs2;
Untuk curs3 diatas, perintah untuk membukanya :
OPEN curs3(23);
Untuk curs1 diatas, perintah untuk membukanya :
OPEN curs1 FOR SELECT * FROM mahasiswa;
MENGGUNAKAN CURSOR
Setelah cursor dibuka, nilainya dapat di manipulasi dengan perintah yang di deskripsikan disini :
Untuk curs2, curs3 dan curs4 diatas, perintah untuk menggunakannya adalah :
FETCH curs2 INTO v_nilai;
FECTH curs3 INTO v_nilai;
FETCH curs1 INTO v_nilai;
Atau jika curs1 memiliki lebih dari satu kolom, anda dapat menggunakannya dengan cara :
FETCH curs1 INTO v_nilai1, v_nilai2, v_nilai3;
Setelah digunakan sebaiknya cursor ditutup untuk menghemat memory yang digunakan
14 | S t o r e d P r o c e d u r e
CLOSE <nama_cursor>;
Ex :
CLOSE curs1;
Contoh 8 : CREATE OR REPLACE FUNCTION isi_komentar1() RETURNS VOID AS
$$
DECLARE
v_nilai deret2.nilai%type;
v_komentar deret2.komentar%type;
c_nilai CURSOR IS SELECT nilai FROM deret2;
BEGIN
OPEN c_nilai;
LOOP
FETCH c_nilai INTO v_nilai;
EXIT WHEN NOT FOUND;
IF v_nilai>3 THEN
v_komentar := 'BAGUS';
ELSE
v_komentar := 'BIASA';
END IF;
UPDATE deret2 SET komentar = v_komentar WHERE nilai = v_nilai;
END LOOP;
CLOSE c_nilai;
END;
$$ LANGUAGE 'plpgsql';
Contoh 9 :
Tabel Jawaban :
CREATE TABLE jawaban (nim char(6), no_soal integer, jawaban char(1));
Dummy data : INSERT INTO jawaban VALUES
-- MAHASISWA 1, NIM : 123456
('123456',1,'A'),('123456',2,'A'),('123456',3,'A'),('123456',4,'A'),('123456',5,'A'),
('123456',6,'A'),('123456',7,'A'),('123456',8,'A'),('123456',9,'A'),('123456',10,'A'),
-- MAHASISWA 2, NIM : 234567
('234567',1,'A'),('234567',2,'B'),('234567',3,'C'),('234567',4,'D'), ('234567',5,'B'),
('234567',6,'D'),('234567',7,'B'),('234567',8,'C'),('234567',9,'D'),('234567',10,'E'),
-- MAHASISWA 3, NIM : 345678
('345678',1,'A'), ('345678',2,'A'), ('345678',3,'C'), ('345678',4,'E'),('345678',5,'B'),
('345678',6,'D'),('345678',7,'E'),('345678',8,'A'),('345678',9,'D'),('345678',10,'A'),
-- MAHASISWA 4, NIM 999999
('999999',1,'B'), ('999999',2,'B'), ('999999',3,'D'), ('999999',4,'A'),('999999',5,'C'),
('999999',6,'A'),('999999',7,'C'),('999999',8,'B'),('999999',9,'A'),('999999',10,'A');
(Dari Presentasi Bpk Yudi Wbs)
Diketahui:
Tabel JAWABAN (NIM char, NO_SOAL int, JAWAB char)
Tabel KUNCI (NO_SOAL int, KUNCI char)
Isilah tabel SKOR (NIM char,SKOR int) dengan aturan: jawaban benar 4 point, jawaban salah -1.
15 | S t o r e d P r o c e d u r e
Tabel kunci : CREATE TABLE kunci (no_soal integer, kunci char(1));
Dummy Data :
INSERT INTO kunci VALUES
(1,'A'), (2,'A'), (3,'C'), (4,'E'), (5,'B'), (6,'D'), (7,'E'), (8,'A'), (9,'D'), (10,'C');
Dengan Summary skor dari Dummy Data jawaban mahasiswa adalah seperti berikut :
Mahasiswa 1, NIM 123456 : benar (3), salah (7) = (4*3) – (1*7) = 5
Mahasiswa 2, NIM 234567 : benar(5), salah (5) = (4*5) – (1*5) =15
Mahasiswa 3, NIM 345678 : benar(9), salah(1) = (4*9) – (1*1) = 35
Mahasiswa 4, NIM 999999 : benar(0), salah(10) = (4*0) – (1*10) = -10
Tabel Skor :
CREATE TABLE skor (nim char(6), skor integer);
Prosedur : CREATE OR REPLACE FUNCTION isi_skor() RETURNS VOID AS
$$
DECLARE
v_nim skor.nim%TYPE;
v_skor skor.skor%TYPE;
v_no_soal jawaban.no_soal%TYPE;
v_jawaban jawaban.jawaban%TYPE;
v_kunci kunci.kunci%TYPE;
c_mahasiswa CURSOR IS SELECT DISTINCT nim FROM jawaban;
c_jawaban CURSOR (v_nim_mhs jawaban.nim%TYPE)FOR SELECT no_soal, jawaban FROM jawaban WHERE
nim = v_nim_mhs;
c_kunci REFCURSOR;
BEGIN
OPEN c_mahasiswa;
LOOP
FETCH c_mahasiswa INTO v_nim;
RAISE NOTICE 'nim : %', v_nim;
EXIT WHEN NOT FOUND;
v_skor := 0;
OPEN c_jawaban(v_nim);
LOOP
FETCH c_jawaban INTO v_no_soal,v_jawaban;
EXIT WHEN NOT FOUND;
RAISE INFO 'no soal : %, jawaban : %', v_no_soal, v_jawaban;
OPEN c_kunci FOR SELECT kunci FROM kunci WHERE no_soal = v_no_soal;
FETCH c_kunci INTO v_kunci;
RAISE INFO 'kunci : %', v_kunci;
CLOSE c_kunci;
IF v_jawaban <> v_kunci THEN
RAISE INFO 'SALAH, %-1', v_skor;
v_skor := v_skor-1;
ELSE
RAISE INFO 'BENAR, %+4', v_skor;
v_skor := v_skor + 4;
END IF;
RAISE INFO 'skor : %', v_skor;
END LOOP;
INSERT INTO skor VALUES (v_nim, v_skor);
CLOSE c_jawaban;
END LOOP;
CLOSE c_mahasiswa;
END;
$$ LANGUAGE 'plpgsql';
16 | S t o r e d P r o c e d u r e
Contoh 10 :
Tabel Trans_Harian:
CREATE TABLE trans_harian (tgl timestamp, jum_trans integer, id_cust integer);
Dummy data : INSERT INTO trans_harian VALUES
(to_timestamp('05 01 2000','DD MM YYYY'),12,1),(to_timestamp('06 01 2000','DD MM YYYY'),3,1),(to_timestamp('05 02 2000','DD
MM YYYY'),4,2),(to_timestamp('07 01 2000','DD MM YYYY'),9,3),(to_timestamp('12 04 2000','DD MM YYYY'),1,1),(to_timestamp('05
01 2000','DD MM YYYY'),15,2),(to_timestamp('05 09 2000','DD MM YYYY'),21,1),(to_timestamp('05 10 2000','DD MM
YYYY'),80,3),(to_timestamp('05 01 2001','DD MM YYYY'),8,1),(to_timestamp('05 02 2001','DD MM YYYY'),6,2),(to_timestamp('05 03
2001','DD MM YYYY'),9,3),(to_timestamp('05 04 2001','DD MM YYYY'),12,3),(to_timestamp('05 05 2001','DD MM
YYYY'),13,3),(to_timestamp('05 06 2001','DD MM YYYY'),80,1),(to_timestamp('05 07 2001','DD MM YYYY'),19,2),(to_timestamp('05
08 2001','DD MM YYYY'),67,1),(to_timestamp('05 09 2001','DD MM YYYY'),999,2),(to_timestamp('05 10 2001','DD MM
YYYY'),87,1),(to_timestamp('05 11 2001','DD MM YYYY'),90,2),(to_timestamp('05 12 2001','DD MM YYYY'),56,2),(to_timestamp('01
1 2002','DD MM YYYY'),76,1),(to_timestamp('15 1 2002','DD MM YYYY'),6,2),(to_timestamp('20 1 2002','DD MM
YYYY'),96,3),(to_timestamp('05 2 2002','DD MM YYYY'),45,1),(to_timestamp('17 2 2002','DD MM YYYY'),67,2),(to_timestamp('13 2
2002','DD MM YYYY'),23,3),(to_timestamp('25 2 2002','DD MM YYYY'),84,1),(to_timestamp('21 2 2002','DD MM
YYYY'),42,2),(to_timestamp('18 3 2002','DD MM YYYY'),45,3),(to_timestamp('12 3 2002','DD MM YYYY'),12,1),(to_timestamp('16 3
2002','DD MM YYYY'),67,2),(to_timestamp('19 3 2002','DD MM YYYY'),86,3),(to_timestamp('22 3 2002','DD MM
YYYY'),56,1),(to_timestamp('23 3 2002','DD MM YYYY'),43,2),(to_timestamp('24 3 2002','DD MM YYYY'),90,3),(to_timestamp('01 4
2002','DD MM YYYY'),75,1),(to_timestamp('02 4 2002','DD MM YYYY'),45,2),(to_timestamp('11 4 2002','DD MM
YYYY'),65,3),(to_timestamp('13 4 2002','DD MM YYYY'),57,1),(to_timestamp('14 5 2002','DD MM YYYY'),43,2),(to_timestamp('17 5
2002','DD MM YYYY'),93,3),(to_timestamp('28 5 2002','DD MM YYYY'),34,1),(to_timestamp('26 6 2002','DD MM
YYYY'),67,2),(to_timestamp('21 7 2002','DD MM YYYY'),32,3),(to_timestamp('22 7 2002','DD MM YYYY'),43,1),(to_timestamp('23 7
2002','DD MM YYYY'),56,2),(to_timestamp('24 7 2002','DD MM YYYY'),97,3),(to_timestamp('01 8 2002','DD MM
YYYY'),91,1),(to_timestamp('01 9 2002','DD MM YYYY'),23,2),(to_timestamp('05 12 2002','DD MM YYYY'),576,3);
Tabel Trans_bulanan CREATE TABLE trans_bulanan(thn integer, bulan integer, jum_trans integer, id_cust integer);
Tabel Trans_tahunan CREATE TABLE trans_tahunan(thn integer, jum_trans integer, id_cust integer);
Prosedur-Prosedur :
Cust_per_tahun CREATE OR REPLACE FUNCTION cust_per_tahun (v_tahun INTEGER) RETURNS REFCURSOR AS
$$
DECLARE
v_curs_thn REFCURSOR;
BEGIN
OPEN v_curs_thn FOR SELECT DISTINCT id_cust FROM trans_harian WHERE EXTRACT (year
FROM tgl) = v_tahun;
RETURN (v_curs_thn);
END;
$$ LANGUAGE 'plpgsql';
Trans_thn_cust CREATE OR REPLACE FUNCTION trans_thn_cust (v_tahun INTEGER, v_id_cust INTEGER)
RETURNS INTEGER AS
$$
DECLARE
(Dari Presentasi Bpk Yudi Wbs)
Tabel input:
TRANS_HARIAN
(TGL date, JUM_TRANS int,ID_CUST int)
Buatlah SP untuk mengisi tabel output:
TRANS_BULANAN
(THN int,BULAN int, JUM_TRANS int, ID_CUST int)
TRANS_TAHUNAN
(TAHUN int, JUM_TRANS int, ID_CUST int)
17 | S t o r e d P r o c e d u r e
jmlh_trans INTEGER;
BEGIN
SELECT INTO jmlh_trans SUM(jum_trans) FROM trans_harian WHERE id_cust = v_id_cust
AND EXTRACT (YEAR FROM tgl) = v_tahun;
RETURN (jmlh_trans);
END;
$$ LANGUAGE 'plpgsql';
Trans_bln_cust CREATE OR REPLACE FUNCTION trans_bln_cust (v_tahun INTEGER, v_bulan INTEGER,
v_id_cust INTEGER) RETURNS INTEGER AS
$$
DECLARE
jmlh_trans INTEGER;
BEGIN
SELECT INTO jmlh_trans SUM(jum_trans) FROM trans_harian WHERE id_cust = v_id_cust
AND EXTRACT (MONTH FROM tgl) = v_bulan AND EXTRACT (YEAR FROM tgl) = v_tahun;
RETURN (jmlh_trans);
END;
$$ LANGUAGE 'plpgsql';
Isi_summary_trans jalankan fungsi ini untuk mengisi tabel trans bulanan dan tahunan. CREATE OR REPLACE FUNCTION isi_summary_trans() RETURNS VOID AS
$$
DECLARE
v_tahun INTEGER;
v_bulan INTEGER;
v_id_cust INTEGER;
v_trans_cust_thn INTEGER;
v_trans_cust_bln INTEGER;
c_tahun CURSOR IS SELECT DISTINCT EXTRACT (YEAR FROM tgl) FROM trans_harian;
c_cust_thn REFCURSOR;
BEGIN
OPEN c_tahun;
LOOP
FETCH c_tahun INTO v_tahun;
EXIT WHEN NOT FOUND;
c_cust_thn := cust_per_tahun(v_tahun);
LOOP
FETCH c_cust_thn INTO v_id_cust;
EXIT WHEN NOT FOUND;
v_trans_cust_thn := trans_thn_cust (v_tahun,v_id_cust);
INSERT INTO trans_tahunan VALUES (v_tahun,v_trans_cust_thn,v_id_cust);
v_bulan := 1;
FOR v_bulan IN 1..12 LOOP
v_trans_cust_bln := trans_bln_cust(v_tahun,v_bulan,v_id_cust);
INSERT INTO trans_bulanan
VALUES(v_tahun,v_bulan,v_trans_cust_bln,v_id_cust);
END LOOP;
END LOOP;
CLOSE c_cust_thn;
END LOOP;
CLOSE c_tahun;
END;
$$ LANGUAGE 'plpgsql';
18 | S t o r e d P r o c e d u r e
Tahun/Customer Bulan
2000 2001 2002 1 2 3 1 2 3 1 2 3
1 15 15 9 8 76 6 96 2 4 6 129 109 23 3 9 68 110 221 4 12 132 45 65 5 13 34 43 93 6 80 67 7 19 43 56 129 8 67 91 9 21 999 23
10 80 87 11 90 12 56 576
Total 37 19 89 242 1170 34 573 459 1203
19 | S t o r e d P r o c e d u r e
<(Pengayaan)>
DEKLARASI VARIABEL
nama_variabel [ CONSTANT ] type_data [ NOT NULL ] [ { DEFAULT | := } nilai_awal ];
CONSTANT : nilai variabel tidak dapat di ubah.
NOT NULL : nilai variabel tidak boleh bernilai null.
DEFAULT :
Nilai default selalu di evaluasi tiap suatu block di masuki. Sebagai contoh, menggunakan
now() sebagai nilai default akan membuat variabel memiliki nilai waktu saat fungsi tersebut di
eksekusi. Jika menggunakan := now(), akan membuat variabel memiliki nilai waktu saat fungsi
tersebut di compile.
Contoh : quantity integer DEFAULT 32;
url varchar := „http://mysite.com‟;
user_id CONSTANT integer := 10;
ALIAS UNTUK PARAMETER FUNGSI
Parameter yang di kirimkan ke fungsi secara default di identifikasikan dengan $1, $2, etc.
Untuk memudahkan pembacaan fungsi, nama alias dapat di pergunakan(ini yang di pergunakan
sebagai contoh-contoh diatas). Namun parameter yang di beri nama alias masih tetap dapat
direferensikan dengan nama default $1, $2, ect.
Ada dua cara untuk membuat alias. Cara yang sering digunakan adalah dengan memberi
nama alias pada pembuatan fungsi. Contoh :
CREATE FUNCTION sales_tax(subtotal real) RETURNS real AS $$
BEGIN
RETURN subtotal * 0.06;
END;
$$ LANGUAGE plpgsql;
Cara kedua, adalah satu-satunya cara yang di perbolehkan pada versi sebelum 8.0 :
CREATE FUNCTION sales_tax(real) RETURNS real AS $$
DECLARE
subtotal ALIAS FOR $1;
BEGIN
RETURN subtotal * 0.06;
END;
$$ LANGUAGE plpgsql;
Alias untuk Parameter Output
Saat fungsi PL/pgSQL mendeklarasikan parameter output, parameter output tersebut juga
diidentifikasikan dengan $n, paramaeter output ini dapat juga di beri nama alias sama seperti
parameter input. Parameter output adalah parameter yang bernilai NULL, dan harus diisikan
nilainya pada saat eksekusi fungsi. Nilai akhir dari parameter adalah nilai yang di hasilkan(yang di
20 | S t o r e d P r o c e d u r e
RETURN) oleh fungsi tersebut. Bentuk lain dari output parameter RETURNS pada deklarasi fungsi
adalah dengan mendefinisikan OUT pada parameter fungsi. Contoh : CREATE FUNCTION sales_tax(subtotal real, OUT tax real) AS $$
BEGIN
tax := subtotal * 0.06;
END;
$$ LANGUAGE plpgsql;
Dapat dilihat pada fungsi diatas, tidak ada pendeklarasian RETURN, anda dapat mendeklarasikan
RETURN, namun hal tersebut akan menghasilkan redudansi pada badan fungsi.
Parameter output seperti ini akan sangat berguna saat fungsi menghasilkan lebih dari satu variabel
hasil. Contoh : CREATE FUNCTION sum_n_product(x int, y int, OUT sum int, OUT prod int) AS
$$
BEGIN
sum := x + y;
prod := x * y;
END;
$$ LANGUAGE plpgsql;
VARIABEL BERTIPE DATA COMPOSITE (CAMPURAN)
Pada lingkungan programming, tipe data campuran seringkali digunakan untuk menangani berbagai
masalah seperti Lingked List, Stack, Queue, Tree, Graph dll.
Contoh : Tipe data titik dengan dua variabel (x, y)
PADA LINGKUNGAN PEMROGRAMAN JAVA
Deklarasi variabel ini dapat di lakukan dengan cara membuat kelas baru yang dinamakan kelas titik
public class titik
{
public int x = 0;
public int y = 0;
}
Anda dapat menggunakan kelas ini dengan membuat objek baru dengan properties kelas, misalkan
anda ingin menggambar garis dari titik A ke titik B, maka anda harus membuat objek titik A dan
objek titik B. public class garis
{
Public static void main (String[] args)
{
public titik A = new titik();
public titik B = new titik();
/* gambar garis dari titik (4, 5) dan (9, 8) */
A.x = 4; A.y = 5;
B.x = 9; B.y = 8;
System.out.println(“ garis dari (“+A.x+”,”+A.y”) ke (“+B.x+”,”+B.y”)”);
}
}
21 | S t o r e d P r o c e d u r e
PADA LINGKUNGAN PEMROGRAMAN C/C++
Deklarasi variabel dilakukan dengan cara membuat tipe data baru, yang lalu di pergunakan dalam
badan fungsi. #include <stdio.h>
main()
{
struct titik { int x; int y; }
titik A;
titik B;
/* gambar garis dari titik (4, 5) dan (9, 8) */
A.x = 4; A.y = 5;
B.x = 9; B.y = 8;
printf(“ garis dari (%d,%d) ke (%d,%d)”, A.x, A.y, B.x, B.y);
}
PADA LINGKUNGAN POSTGRESQL
Pada contoh-contoh sebelumnya fungsi-fungsi hanya menggunakan tipe data bawaan dari
postgreSQL, sebenarnya kita dapat membuat tipe data sendiri dengan cara
CREATE TYPE <nama_tipe> AS (
<nama_variabel> <tipe_data_variabel>
);
Contoh : CREATE TYPE titik AS
(
x integer,
y integer
);
Tipe data baru ini dapat anda pergunakan untuk berbagai keperluan, misalkan membuat tabel
dengan kolom dengan tipe data ini, maupun menggunakan tipe data ini pada fungsi.
Contoh : CREATE TABEL garis (a titik, b titik);
INSERT INTO garis VALUES ((2,3),(4,5));
INSERT INTO garis VALUES ((3,9),(8,5));
INSERT INTO garis VALUES ((2,6),(4,6));
SELECT (a).x FROM garis;
-- atau jika anda menggunakan nama tabel untuk operasi multi tabel
SELECT (garis.a).x FROM garis;
SELECT * FROM garis WHERE (a).x = 2;
SELECT * FROM garis WHERE (b).y = 5;
-- pada operasi update, kita tidak boleh menggunakan tanda kurung setelah SET
UPDATE garis SET (b).y = 99 WHERE (b).y = 5; -- ERROR
UPDATE garis SET b.y = 99 WHERE (b).y = 5;
-- tetapi tanda kurung harus digunakan saat mereferensi kolom yang sama pada
-- ekspresi di sebelah kanan tanda sama dengan
UPDATE garis SET a.x = (a).x + 1 WHERE (a).x = 3;
-- kita juga dapat menggunakan sub-field ini sebagai sasaran operasi insert
INSERT INTO garis (a.x, b.y) VALUES (99, 55);
22 | S t o r e d P r o c e d u r e
Seperti telah disebutkan diatas, kita juga dapat membuat fungsi dengan tipe data campuran ini. CREATE FUNCTION masukkan_titik_a_ke_garis (v_a_x integer, v_a_y integer) RETURNS VOID AS
$$
BEGIN
INSERT INTO garis (a.x, a.y) VALUES (v_a_x, v_a_y);
END;
$$ LANGUAGE 'plpgsql';
Anda dapat mengeksekusi fungsi diatas dengan cara :
select masukkan_titik_a_ke_garis(25,67);
dengan tipe data campuran ini, anda diberikan kebebasan dalam pemrograman dengan hanya
mengeluarkan satu variabel yang mengandung isi lebih dari satu variabel.
top related