Relasi Dalam Database Mengunakan PostgreSQL: one to one, one to many, dan many to many
By Ahmad Afan Shobari

Assalamualikum, pada kesempatan kali ini kita akan membuat relasi dalam database:
data terbagi menjadi 3:
one to one
one to many
many to many
1. One to One
1.1Masalah

Banyak
NULLuntuk role yang tidak butuh biodata → boros, berisik, rawan salah.Keamanan & tanggung jawab bercampur: data login (sensitif) digabung dengan biodata (publik).
Sulit berkembang: tambah kolom profil baru akan “mengganggu” semua baris (termasuk admin).
1.2 Solusi
Intinya: bedakan akun dari profil.
users→ khusus autentikasi & otorisasi (username, password_hash, role).profile→ khusus biodata (name, address, no_hp, jenis_kelamin), opsional tergantung role.
Dengan begitu:
Admin cukup punya akun (tanpa profil).
Member/staff bisa punya profil lengkap.
Data bersih, hemat
NULL, dan mudah diatur izinnya.
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
username VARCHAR(64) NOT NULL UNIQUE,
password_hash TEXT NOT NULL,
role VARCHAR(16) NOT NULL CHECK (role IN ('admin','member','staff')),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE profile (
user_id BIGINT PRIMARY KEY
REFERENCES users(id) ON DELETE CASCADE,
name VARCHAR(120),
address VARCHAR(255),
no_hp VARCHAR(32),
jenis_kelamin CHAR(1) CHECK (jenis_kelamin IN ('L','P')),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
Kuncinya pada table profiles dimana pada bagian user_id mereferensikan id users

Kemudian membuat data pada users

Kemudian membuat data untuk profiles
error: banyak typo di berbagai tempat

Kemudian membaca hasil keduanya bersamaan dengan mengunakan join (hanya menampilkan tanpa benar benar mengabungkanya jika di lihat satu persatu seperti ini
error: typo dalam penulisan kata profile


2. One to Many
2.1 Masalah

Batas kolom: Hanya bisa menyimpan 4 setoran. Saat user menyetor ke-5, harus tambah kolom baru.
Banyak
NULL: Tidak semua user menyetor 4 kali → kolom kosong.Sulit analitik: Agregasi (SUM, AVG), filter per tanggal/metode setoran jadi ribet karena data melebar ke banyak kolom.
Tidak ada detail waktu/metode per setoran.
2.2 Solusi
Pisahkan entitas
usersdan kejadiansetoran.Satu
userpunya banyak barissetoran.
2.3 Praktik
- Ini adalah table yang akan kita buat
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(64) NOT NULL UNIQUE,
name VARCHAR(120) NOT NULL
);
CREATE TABLE transaksi (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
nominal NUMERIC(12,2) NOT NULL CHECK (nominal > 0),
tgl DATE NOT NULL,
jenis_transaksi VARCHAR(32)
);
Inilah adalah contoh pemaktrikanya


Setelah data dibuat maka kita akan memasukan datanya

2.4 Error

Saya salah dalam memberi nama table ke 2 maka saya harus membuat table kembali
Data pada table users, saya hapus entah kenapa saya berpikir untuk mengulangnya maka id 1 dan 2 juga tidak dapat di akses
3. Many to Many
3.1 Masalah

Integritas buruk: tidak ada FK ke kamus
tag. Ejaan bisa beda (“VIP”, “Vip”, “vip”).Sulit query: mencari user yang punya semua tag tertentu jadi rumit (harus parsing string/ARRAY).
Duplikasi tak terlihat: tag yang sama bisa ditulis berulang dengan variasi penulisan.
3.2 Solusi
Pisahkan menjadi 3 tabel: users, tags, dan tabel penghubung user_has_tag.

3.3 Praktik
- ini adalah table yang akan kita buat
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
username VARCHAR(64) NOT NULL UNIQUE,
name VARCHAR(120) NOT NULL
);
CREATE TABLE tags (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(64) NOT NULL UNIQUE
);
CREATE TABLE user_has_tag (
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
tag_id BIGINT NOT NULL REFERENCES tags(id) ON DELETE CASCADE,
PRIMARY KEY (user_id, tag_id)
);

setelah membuat table kita akan menambahkan isinya
error: typo pada tabel users_name_tags dimana saya menulis tags_is padahal harusnya tags_id

error:
typo penulisan user_id harusnay users_id
lupa kalau tags hanya ada 3 ngak sampai 4




