• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
PostgreSQL Stored-procedure
 

PostgreSQL Stored-procedure

on

  • 6,071 views

 

Statistics

Views

Total Views
6,071
Views on SlideShare
6,070
Embed Views
1

Actions

Likes
1
Downloads
346
Comments
0

1 Embed 1

http://ammarshadiq.web.id 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    PostgreSQL Stored-procedure PostgreSQL Stored-procedure Document Transcript

    • 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 CHARACT ER(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'); 1|S tored Proc edure
    • 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> 2|S tored Proc edure
    • 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. 3|S tored Proc edure
    • 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 $$.......... 4|S tored Proc edure
    • 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. 5|S tored Proc edure
    • 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; 6|S tored Proc edure
    • 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) 7|S tored Proc edure
    • 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. 8|S tored Proc edure
    • 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 9|S tored Proc edure
    • 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). 10 | 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. 11 | 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; ... 12 | 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 13 | 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 : (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. 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'); 14 | 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'; 15 | S t o r e d P r o c e d u r e
    • Contoh 10 : (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) 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 16 | 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'; 17 | S t o r e d P r o c e d u r e
    • Tahun/Customer 2000 2001 2002 Bulan 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 18 | 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 19 | 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”)”); } } 20 | 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); 21 | 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. 22 | S t o r e d P r o c e d u r e