PostgreSQL Stored-procedure

22
1 | Stored Procedure 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');

Transcript of PostgreSQL Stored-procedure

Page 1: PostgreSQL Stored-procedure

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');

Page 2: PostgreSQL Stored-procedure

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>

Page 3: PostgreSQL Stored-procedure

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.

Page 4: PostgreSQL Stored-procedure

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 $$..........

Page 5: PostgreSQL Stored-procedure

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.

Page 6: PostgreSQL Stored-procedure

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;

Page 7: PostgreSQL Stored-procedure

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)

Page 8: PostgreSQL Stored-procedure

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.

Page 9: PostgreSQL Stored-procedure

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

Page 10: PostgreSQL Stored-procedure

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).

Page 11: PostgreSQL Stored-procedure

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.

Page 12: PostgreSQL Stored-procedure

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;

...

Page 13: PostgreSQL Stored-procedure

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

Page 14: PostgreSQL Stored-procedure

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.

Page 15: PostgreSQL Stored-procedure

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';

Page 16: PostgreSQL Stored-procedure

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)

Page 17: PostgreSQL Stored-procedure

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';

Page 18: PostgreSQL Stored-procedure

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

Page 19: PostgreSQL Stored-procedure

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

Page 20: PostgreSQL Stored-procedure

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”)”);

}

}

Page 21: PostgreSQL Stored-procedure

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);

Page 22: PostgreSQL Stored-procedure

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.