# Relasi Table Dengan Kasus Absensi Pondok Melalui PostgreSQL

Assalamualaikum, pada kesempatan kali ini kita akan melanjutkan sesi latihan kita, yaitu tentang absensi kelas

# 1\. Masalah

Pondok "PPQITA" ingin menertibkan absensi santri per **pertemuan** berdasarkan **jadwal** tetap. Selama ini absensi di kertas/WA menyulitkan rekap harian/bulanan. Sistem yang dibangun harus:

* Mencatat **kehadiran** setiap santri pada **tanggal** tertentu untuk **jadwal** tertentu.
    
* Mendukung status: `HADIR | TERLAMBAT | SAKIT | IZIN | ALPHA`.
    
* Memastikan **tidak ada duplikasi** catatan untuk santri yang sama pada kombinasi (tanggal, jadwal).
    
* Menyediakan rekap sederhana (per jadwal/per bulan).
    

# 2\. Praktik

## 2.1 Membuat Table

* pertama kita akan membuat tablenya
    

```pgsql
--table ustadz
create table ustadz (
 id_ustadz   serial primary key,
 nama_ustadz varchar(50)
 );
--table kelas
 create table kelas (
 id_kelas    serial primary key,
 nama_kelas  varchar(50),
 tingkat     int
 );
--table santri
create table santri (
 id_santri   serial primary key,
 nis         varchar(20) unique,
 nama_santri varchar(100),
 jk          char(1),
 kelas_id    int references kelas(id_kelas) ON UPDATE CASCADE ON DELETE RESTRICT
 );
--table jadwal
create table jadwal (
 id_jadwal   serial primary key,
 id_kelas    int references kelas(id_kelas) ON UPDATE CASCADE ON DELETE RESTRICT,
 id_ustadz   int references ustadz(id_ustadz) ON UPDATE CASCADE ON DELETE RESTRICT,
 mapel       varchar(50),
 hari        varchar(50),
 jam_mulai   time,
 jam_selesai time,
 lokasi      varchar(150)
 );
--table kehadiran
create table kehadiran (
 tanggal     date ,
 id_jadwal   int references jadwal(id_jadwal) on update cascade on delete restrict,
 id_santri   int references santri(id_santri) on update cascade on delete restrict,
 status      varchar(50) check (status in ('hadir', 'terlambat', 'sakit', 'izin', 'alpha')),
 waktu_masuk time,
 menit_telat int check (menit_telat >= 0),
 catatan     text
 );
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756345552610/ce0bdfde-520a-4ce6-a833-0f9a4d79d536.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756345564033/ff0d12e0-c72a-4caa-ad5d-f5105a7f95fe.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756345568849/f2203e8d-ec42-4d76-9dd0-091169be1c87.png align="center")

Kemudian kita akan menambahkan index pada beberapa column

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756352715437/be5d8812-9e55-4bb2-8609-eaa298862195.png align="center")

## 2.2 Menambahkan Data

**kelas**

* (nama=`Tahfidz 1A`, tingkat=1)
    

**ustadz**

* (nama=`Ust. Alwi`)
    

**santri**

* (`24101`, `Ahmad Fauzi`, `L`, kelas=`Tahfidz 1A`)
    
* (`24102`, `Bima Putra`, `L`, kelas=`Tahfidz 1A`)
    
* (`24103`, `Cahya Lestari`,`P`, kelas=`Tahfidz 1A`)
    

**jadwal**

* (kelas=`Tahfidz 1A`, ustadz=`Ust. Alwi`, mapel=`Tahfidz`, hari=`Senin`, jam=`07:00-08:30`, lokasi=`Kelas A`)
    
* (kelas=`Tahfidz 1A`, ustadz=`Ust. Alwi`, mapel=`Tahfidz`, hari=`Selasa`, jam=`07:0008:30`, lokasi=`Kelas A`)
    

**kehadiran** (contoh dua hari):

* (tgl `2025-08-25`, jadwal=Senin, S1=`HADIR` 06:58, 0, `Datang awal`)
    
* (tgl `2025-08-25`, jadwal=Senin, S2=`TERLAMBAT` 07:12, 12, `Macet`)
    
* (tgl `2025-08-25`, jadwal=Senin, S3=`HADIR` 07:05, 5, `-`)
    
* (tgl `2025-08-26`, jadwal=Selasa, S1=`HADIR` 06:59, 0, `-`)
    
* (tgl `2025-08-26`, jadwal=Selasa, S2=`IZIN`, `NULL`, `NULL`, `Urusan keluarga`)
    
* (tgl `2025-08-26`, jadwal=Selasa, S3=`ALPHA`, `NULL`, `NULL`, `-`)
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756352991150/8513c10c-cdc9-48f7-bfc0-ffa7f6a17695.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756352996159/db568eab-3888-4a3a-9ac6-0a7ed9c49ab7.png align="center")

\`

## 2.3 CRUD Data

1. **kelas**
    
    * Create kelas baru.
        
    * List kelas (urut tingkat, nama) dengan pagination (LIMIT/OFFSET).
        
    * Update nama & tingkat sebuah kelas.
        
    * Delete kelas (uji kegagalan jika masih dirujuk FK).
        
2. **ustadz**
    
    * Create ustadz.
        
    * Cari ustadz by nama (ILIKE), paginate.
        
    * Update nama ustadz.
        
    * Delete ustadz (uji FK).
        
3. **santri**
    
    * Create santri (NIS unik).
        
    * List santri per kelas + opsi search nama/NIS (ILIKE), paginate.
        
    * Detail santri beserta nama kelas.
        
    * Update (ganti kelas/jk/nama/nis).
        
    * Delete santri (uji FK).
        
4. **jadwal**
    
    * Create jadwal (kelas, ustadz, mapel, hari, jam, lokasi).
        
    * List jadwal per kelas/hari.
        
    * Detail jadwal (tampilkan nama kelas & ustadz).
        
    * Update jadwal.
        
    * Delete jadwal (uji FK).
        
5. **kehadiran**
    
    * Create satu baris absensi (tanggal, jadwal, santri, status, waktu\_masuk, menit\_telat, catatan).
        
        > ***Uji UNIQUE(tanggal, jadwal, santri) dengan mencoba insert duplikat.***
        
    * List absensi untuk satu tanggal & jadwal (tampilkan NIS, Nama Santri, status, menit\_telat).
        
    * Update status/waktu\_masuk/menit\_telat/catatan.
        
    * Delete satu catatan absensi.
        

### 2.3.1 Kelas

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756354886482/142d0805-a374-4766-b6a8-e4c5eae2b8b1.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756354426969/1e34f6f2-c8f8-47af-b659-a2a589bc2000.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756354765954/112b5110-755f-4527-8426-ce5944553500.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756354855209/3a42e729-8f01-40eb-931d-a7801d2bfdb3.png align="center")

### 2.3.2 Ustadz

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756359929149/fda8cf0c-a140-4571-9e2e-4dae701b385f.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756359933444/a5cc104b-3650-4583-8bd9-0406804b3a29.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756360163393/1740d107-8f31-43bb-a665-c68624f6ec86.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756360543436/301678ed-c0e5-468e-880b-f61adac8fd58.png align="center")

### 2.3.3 Santri

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756360824873/9e97c461-6dcf-4094-ab61-cd3319526e6b.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756362709376/27edc35e-b038-4b35-8b87-baab168dca83.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756362917158/3426dfb4-0d27-418c-ac21-972b39ed6500.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756363017322/aa89e41f-e71c-47bd-bb81-4d05d8fd64b0.png align="center")

### 2.3.4 Jadwal

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756363363187/6ad3f3d8-6c11-4c5e-b0b7-de92ca751e69.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756363515959/ab3fb568-a5a3-41c1-9d50-0fb0ba279189.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756363832482/9778c070-b3c8-4161-b8dd-d83b5c4aea9c.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756363994362/739e22b1-786d-46c3-b87b-58cfcbf32205.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756364048495/01055ea7-414c-4670-870e-1ecdf02a3406.png align="center")

### 2.3.5 Kehadiran

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756535338634/644db0d8-9900-4dc2-ada2-98bf162f1374.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756535500127/c7b63d8f-029f-44ff-abc2-e055aa39c9fb.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756535773381/267b3688-5871-43d0-b0ef-685f8c98152d.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756536045709/4ebf6fe8-d4b0-4922-b03d-ff02274fad60.png align="center")

## 2.4 Query Data

### 2.4.1 Query Total Kehadiran

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756859756583/e6a12e9b-6896-42a1-863f-ef7bb9eff8ef.png align="center")

### 2.4.2 Query Data Bulanan

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756860240094/e54d04c8-1f5d-4765-8689-0e717200abe3.png align="center")

### 2.4.3 Query Data Yang Sering terlambat

## 2.5 Uji Contraint

### 2.5.1 Memasukan Data Yang Mirip Pada Constraint UNIQUE

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756860721491/e69b6dc3-b563-4a0a-8e9e-53565e8fc8d6.png align="center")

Pada gambar diatas menunjukan bahwa data yang dikenai UNIQUE tidak dapat menyimpan yang sama, karena akan menghasilkan error , dimana nis ‘24101‘ sudah ada didalam table dan kita tidak dapat mengunakannya lagi

### 2.4.2 Menghapus Data Yang Terdapat Foreign Key

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1756861048993/63bfcb6c-e70a-4e1e-b537-e7a5433012a1.png align="center")

Pada gambar diatas menunjukan bahwa data yang tersambung dengan data yang menjadi fk (foreign key) tidak dapat dihapus karena itu dapat merusak susunan table , dan pasti akan muncul error

### 2.4.3

### 2.4.4 Mencoba Keunggulan Contsraint Check
