Second Normal Form (2NF) — Database

Second Normal Form (2NF) Syarat 2NF: Sudah memenuhi 1NF Semua kolom non-key bergantung pada seluruh primary key, bukan hanya sebagian (no partial dependency)…

Second Normal Form (2NF) adalah aturan normalisasi yang kedua: di tabel yang primary key-nya gabungan dua kolom, setiap kolom lain harus bergantung pada kedua kolom itu, bukan cuma salah satunya. Bayangin buku catatan pesanan di Kedai Senja: tiap baris adalah satu menu di satu nota, misalnya "nota 1, Kopi Susu, 2 gelas". Jumlah gelasnya memang milik baris itu. Tapi nama "Kopi Susu" bukan milik nota, dia milik menunya. Kalau nama menu ditulis ulang di setiap nota, mengganti nama berarti membalik semua halaman, dan pasti ada yang kelewat.

🧪 Tebakan cepat: ada dua baris Kopi Susu di tabel pesanan. Kamu mengganti namanya jadi "Kopi Susu Senja" di baris pesanan 1 saja, lalu menampilkan semua baris produk Kopi Susu. Berapa nama berbeda yang keluar: satu atau dua? Tebak dulu, jawabannya ada di bagian "Ubah satu baris, datanya bertentangan".

Tabel yang kita pakai

Di pelajaran 1NF, isi pesanan Kedai Senja pindah ke order_items, satu baris per produk. Sekarang tiap baris juga mencatat product_id dan jumlahnya (qty):

order_id product_id product_name qty
1 1 Kopi Susu 2
1 4 Roti Bakar 1
2 2 Kopi Susu Aren 1
3 3 Teh Tarik 1
3 1 Kopi Susu 1

Pesanan 1 dan 2 milik Budi, pesanan 3 milik Siti. Primary key-nya (order_id, product_id). Primary key yang terdiri dari dua kolom atau lebih disebut composite primary key. Yang harus unik adalah pasangannya: order_id 1 boleh muncul dua kali, tapi pasangan (1, 1) cuma boleh ada sekali. Kolom yang bukan bagian primary key (product_name dan qty) disebut kolom non-key.

Bergantung pada apa?

Kolom B bergantung pada kolom A kalau begitu A diketahui, nilai B pasti cuma satu. Istilah resminya functional dependency. Cek dua kolom non-key tadi:

Kolom Cukup tahu... Jenis
product_name product_id saja: produk 1 pasti Kopi Susu, di pesanan mana pun partial dependency
qty order_id dan product_id: Kopi Susu dipesan 2 di pesanan 1, tapi 1 di pesanan 3 full dependency

Partial dependency artinya kolom non-key cuma bergantung pada sebagian primary key. Syarat 2NF ada dua: tabelnya sudah memenuhi 1NF, dan semua kolom non-key bergantung penuh pada seluruh primary key. Jadi order_items di atas melanggar 2NF karena product_name.

Ubah satu baris, datanya bertentangan

Pemilik kedai mengganti nama Kopi Susu dari halaman pesanan 1. Yang berubah cuma baris itu:

UPDATE order_items SET product_name = 'Kopi Susu Senja'
WHERE order_id = 1 AND product_id = 1;

SELECT order_id, product_id, product_name
FROM order_items
WHERE product_id = 1;
order_id product_id product_name
1 1 Kopi Susu Senja
3 1 Kopi Susu

Produk yang sama sekarang punya dua nama, dan database gak protes. Itu jawaban tebakannya: dua. Masalah ini disebut update anomaly. Ada dua saudaranya:

Pecah tabelnya

Kolom yang cuma bergantung pada product_id pindah ke tabel yang primary key-nya product_id itu sendiri:

CREATE TABLE products (
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL
);

CREATE TABLE order_items (
  order_id INTEGER NOT NULL,
  product_id INTEGER NOT NULL REFERENCES products(id),
  qty INTEGER NOT NULL,
  PRIMARY KEY (order_id, product_id)  -- composite primary key
);

INSERT INTO products VALUES (1, 'Kopi Susu'), (2, 'Kopi Susu Aren'), (3, 'Teh Tarik'), (4, 'Roti Bakar');
INSERT INTO order_items VALUES (1, 1, 2), (1, 4, 1), (2, 2, 1), (3, 3, 1), (3, 1, 1);

Sekarang ganti nama cukup satu baris, dan semua pesanan membacanya lewat JOIN:

UPDATE products SET name = 'Kopi Susu Senja' WHERE id = 1;

SELECT oi.order_id, p.name AS product_name, oi.qty
FROM order_items oi
JOIN products p ON p.id = oi.product_id
WHERE oi.product_id = 1;
order_id product_name qty
1 Kopi Susu Senja 2
3 Kopi Susu Senja 1

Gak mungkin bertentangan lagi, karena namanya cuma ada di satu tempat. Pesanan 2 dibatalkan pun, Kopi Susu Aren tetap ada di products.

Kapan 2NF perlu dicek

Partial dependency cuma mungkin terjadi kalau primary key-nya gabungan. Kalau primary key cuma satu kolom (misalnya id auto-increment), gak ada "sebagian" dari key itu, jadi tabel yang sudah 1NF otomatis memenuhi 2NF. Cara ceknya bisa dihitung:

Kolom di primary key Kolom key yang jadi sandaran Hasil
2 1 (product_name ke product_id) partial dependency
2 2 (qty ke keduanya) full dependency
1 1 (name ke products.id) tidak mungkin partial
3 2 partial dependency

⚠️ Jebakan yang sering ketemu

TL;DR: 2NF = sudah 1NF, dan setiap kolom non-key bergantung pada seluruh primary key. Pelanggarannya, partial dependency, cuma bisa muncul di composite primary key: product_name di order_items (order_id, product_id) cuma bergantung pada product_id. Akibatnya update anomaly (satu produk punya dua nama), delete anomaly dan insert anomaly. Solusinya: pindahkan kolom itu ke tabel sendiri (products) dan sambungkan dengan product_id. Primary key satu kolom = tidak mungkin partial.

Yang akan kamu pelajari