Primary Key dan Foreign Key: Fondasi Relasi Antar Tabel
Blog/Tutorial SQL/Primary Key dan Foreign Key: Fondasi Relasi Antar Tabel

Primary Key dan Foreign Key: Fondasi Relasi Antar Tabel

BimaBima
·11 Maret 2026·9 menit baca

Penulis

Bima

Bima

Founder & Data Professional

Bagikan

TL;DR

Primary key adalah kolom yang nandain tiap baris di satu tabel secara unik — nilainya gak boleh kembar dan gak boleh kosong. Foreign key adalah kolom di tabel lain yang nunjuk ke primary key itu, dan inilah yang bikin dua tabel nyambung. Contohnya id_pelanggan jadi primary key di tabel pelanggan, lalu muncul lagi sebagai foreign key di tabel transaksi supaya database tau transaksi ini punya siapa.

Primary key adalah kolom yang nandain tiap baris di satu tabel secara unik. Nilainya gak boleh kembar, gak boleh kosong.

Foreign key adalah kolom di tabel lain yang nunjuk ke primary key itu. Inilah yang bikin dua tabel nyambung.

Tanpa dua hal ini, database kamu cuma kumpulan spreadsheet yang kebetulan disimpan di server. JOIN gak jalan, data ganda numpuk, dan transaksi bisa nyantol ke pelanggan yang gak pernah ada.

Apa itu primary key?

Primary key adalah kolom (atau gabungan kolom) yang nilainya unik di seluruh tabel dan gak pernah kosong. Database pakai kolom ini buat nunjuk satu baris tertentu dengan pasti — tanpa perlu nebak baris mana yang dimaksud.

Satu tabel cuma boleh punya satu primary key. Ini aturan mati.

CREATE TABLE pelanggan (
    id_pelanggan  INT PRIMARY KEY,
    nama          VARCHAR(100) NOT NULL,
    kota          VARCHAR(50),
    email         VARCHAR(100) UNIQUE
);

Begitu id_pelanggan jadi primary key, database otomatis nolak dua hal: baris dengan id yang sama, dan baris dengan id kosong.

Coba masukin data kembar:

INSERT INTO pelanggan VALUES (1, 'Rina', 'Surabaya', 'rina@example.com');
INSERT INTO pelanggan VALUES (1, 'Budi', 'Medan', 'budi@example.com');
-- ERROR: duplicate key value violates unique constraint

Ditolak. Bagus — itu memang tugasnya.

Kolom apa yang cocok jadi primary key?

Kolom yang nilainya gak bakal berubah seumur hidup barisnya. Ini kriteria utamanya.

Kandidat yang bagus: id numerik yang naik otomatis, atau UUID.

Kandidat yang jelek: nomor HP (bisa ganti), email (bisa ganti), nama (bisa kembar). Aku pernah lihat sistem yang pakai email sebagai primary key. Begitu satu pelanggan ganti email, semua transaksi lamanya jadi nyantol ke orang yang salah.

Composite primary key

Kadang gak ada satu kolom pun yang unik sendirian. Contohnya tabel detail transaksi:

CREATE TABLE detail_transaksi (
    id_transaksi  INT,
    id_produk     INT,
    qty           INT NOT NULL,
    PRIMARY KEY (id_transaksi, id_produk)
);

id_transaksi muncul berkali-kali (satu transaksi bisa beli 5 produk). id_produk juga muncul berkali-kali. Tapi kombinasi keduanya unik — satu produk cuma boleh muncul sekali di satu transaksi.

Apa itu foreign key?

Foreign key adalah kolom di satu tabel yang nilainya wajib ada di primary key tabel lain. Fungsinya nyambungin baris di tabel anak ke baris induknya, dan database yang jagain supaya sambungan itu gak pernah putus.

CREATE TABLE transaksi (
    id_transaksi  INT PRIMARY KEY,
    id_pelanggan  INT NOT NULL,
    tanggal       DATE NOT NULL,
    total         DECIMAL(12,2),
    CONSTRAINT fk_transaksi_pelanggan
        FOREIGN KEY (id_pelanggan)
        REFERENCES pelanggan(id_pelanggan)
);

Sekarang coba masukin transaksi buat pelanggan nomor 99, padahal tabel pelanggan cuma punya id 1, 2, dan 3:

INSERT INTO transaksi VALUES (105, 99, '2026-01-10', 50000);
-- ERROR: violates foreign key constraint

Ditolak juga. Ini yang disebut referential integrity — database mastiin tiap transaksi punya pemilik yang beneran ada.

Kenapa ini penting?

Tanpa foreign key, kamu bisa punya data yatim: transaksi yang nyantol ke pelanggan nomor 99 yang gak pernah ada di sistem.

Kelihatannya sepele. Sampai kamu jalanin laporan penjualan per pelanggan, dan Rp 3,4 juta hilang begitu aja karena baris-barisnya gak ketemu induknya waktu di-JOIN.

Kalau kamu curiga ada data yatim di database yang FK-nya belum dipasang, cek pakai ini:

SELECT t.id_transaksi, t.id_pelanggan
FROM transaksi t
LEFT JOIN pelanggan p ON t.id_pelanggan = p.id_pelanggan
WHERE p.id_pelanggan IS NULL;

Baris yang keluar itu transaksi tanpa pemilik. Logika LEFT JOIN-nya dijelasin lengkap di halaman glosarium LEFT JOIN.

Gimana primary key dan foreign key bekerja bareng?

Begitu relasinya kepasang, JOIN jadi gampang. Ini contoh dari dataset toko_berkah:

SELECT p.nama,
       p.kota,
       COUNT(t.id_transaksi) AS jumlah_transaksi,
       SUM(t.total)          AS total_belanja
FROM pelanggan p
JOIN transaksi t ON p.id_pelanggan = t.id_pelanggan
GROUP BY p.nama, p.kota
ORDER BY total_belanja DESC;

Bagian ON p.id_pelanggan = t.id_pelanggan itu persis relasi yang tadi kamu bikin. Primary key di kiri, foreign key di kanan.

Detail sintaks JOIN-nya ada di halaman glosarium INNER JOIN.

Contoh kasus: data yatim di toko_berkah

Waktu aku pertama kali nge-cek dataset toko_berkah — 3.180 transaksi dari 6 bulan — tabel transaksinya belum punya foreign key sama sekali. Data dimasukin lewat impor CSV dari kasir.

Query cek data yatim di atas nemuin 47 transaksi dengan id_pelanggan yang gak ada di tabel pelanggan. Totalnya Rp 6,2 juta.

Penyebabnya: 47 transaksi itu dari pembeli yang batal daftar akun. Kasir tetap masukin id sementara, tapi barisnya gak pernah nyampe tabel pelanggan.

Dampaknya di laporan bulanan: total omzet dari query SUM(total) di tabel transaksi adalah Rp 214 juta. Tapi laporan penjualan per pelanggan — yang pakai JOIN — cuma nunjukin Rp 207,8 juta.

Selisih 2,9%. Cukup kecil buat gak keliatan, cukup besar buat bikin salah keputusan.

Setelah foreign key dipasang, baris yatim baru gak bisa masuk lagi. 47 baris lama? Itu urusan lain — harus dibersihin manual dulu sebelum ALTER TABLE mau jalan.

Apa itu ON DELETE dan kenapa harus hati-hati?

Waktu bikin foreign key, kamu bisa atur apa yang terjadi kalau baris induknya dihapus.

AturanEfek waktu induk dihapusKapan dipakai
ON DELETE RESTRICTPenghapusan ditolak selama masih ada anakData transaksi dan keuangan
ON DELETE CASCADESemua baris anak ikut kehapusData turunan yang gak berharga sendiri
ON DELETE SET NULLForeign key anak jadi kosongRelasi opsional, misalnya kategori produk

CASCADE itu praktis dan bahaya. Hapus satu pelanggan, semua riwayat transaksinya lenyap — termasuk yang udah masuk laporan pajak.

Buat tabel transaksi, pakai RESTRICT. Database bakal nolak penghapusan, dan kamu dipaksa mikir dulu sebelum ngapus.

Kesalahan umum

1. Pakai kolom yang bisa berubah sebagai primary key

Email, nomor HP, NIK yang salah ketik. Semua bisa berubah. Begitu berubah, semua relasi ke tabel lain putus. Pakai id yang gak punya arti apa-apa selain jadi penanda.

2. Lupa kasih index ke kolom foreign key

Primary key otomatis dapat index. Foreign key nggak di sebagian besar database — MySQL bikin otomatis, PostgreSQL nggak.

Akibatnya JOIN jadi lambat banget di tabel besar. Bikin index manual:

CREATE INDEX idx_transaksi_pelanggan ON transaksi(id_pelanggan);

3. Tipe data primary key dan foreign key beda

INT di tabel induk, VARCHAR di tabel anak. Database bakal nolak bikin constraintnya, dan pesan errornya sering bikin bingung.

4. Pasang CASCADE tanpa mikir

Udah dibahas di atas. Sekali kehapus, gak ada undo.

5. Nganggep foreign key bikin database lambat

Iya, ada biaya pengecekan tiap kali insert. Tapi biayanya kecil banget dibanding biaya bersihin ribuan data yatim tiga bulan kemudian.

FAQ

Apa bedanya primary key dan foreign key?

Primary key nandain tiap baris di tabelnya sendiri secara unik — nilainya gak boleh kembar dan gak boleh kosong. Foreign key ada di tabel lain dan nunjuk ke primary key itu. Satu tabel cuma boleh punya satu primary key, tapi bisa punya banyak foreign key.

Apakah satu tabel wajib punya primary key?

Secara teknis gak wajib, database tetap mau bikin tabelnya. Tapi tanpa primary key kamu gak bisa nunjuk satu baris tertentu dengan pasti, dan tabel lain gak bisa nyambung ke situ. Baris duplikat juga bisa masuk tanpa ketauan. Kasih primary key ke setiap tabel, sekalipun cuma kolom id yang naik otomatis.

Bisakah foreign key bernilai NULL?

Bisa, kecuali kamu kasih NOT NULL. Foreign key kosong artinya baris itu belum punya induk — misalnya transaksi dari pembeli yang gak daftar akun. Kalau tiap transaksi wajib punya pelanggan, tambahin NOT NULL supaya database nolak baris tanpa induk.

Apa itu composite primary key?

Primary key yang terdiri dari dua kolom atau lebih. Dipakai kalau gak ada satu kolom pun yang unik sendirian. Contohnya tabel detail_transaksi: id_transaksi bisa muncul berkali-kali, id_produk juga, tapi kombinasi keduanya unik.

Apa efeknya ON DELETE CASCADE?

Kalau baris induk dihapus, semua baris anak yang nunjuk ke situ ikut kehapus otomatis. Ini praktis tapi bahaya buat data keuangan. Buat tabel transaksi, pakai ON DELETE RESTRICT. Aturan lengkapnya bisa kamu baca di dokumentasi constraint PostgreSQL.

Penutup

Tiga hal yang perlu kamu bawa:

  • Primary key = penanda unik di tabelnya sendiri. Pilih kolom yang gak bakal berubah.
  • Foreign key = penunjuk ke tabel lain. Ini yang bikin JOIN jalan dan data yatim gak bisa masuk.
  • ON DELETE RESTRICT buat tabel transaksi. CASCADE cuma buat data turunan yang gak berharga sendiri.

Coba jalanin query cek data yatim di database yang kamu pegang sekarang. Kalau ada yang keluar, kamu baru aja nemu bocor yang selama ini gak keliatan di laporan.

Lanjut ngulik relasi antar tabel? Baca panduan JOIN di SQL dari nol. Buat yang mau ngerti aturan lain yang jaga kualitas data, ada juga penjelasan constraint SQL lengkap.

Coba Langsung

Mau praktek langsung? Mulai latihan SQL gratis

Latihan interaktif, langsung di browser.

Buka NgulikSQL →
Bagikan:
Bima
Ditulis oleh

Bima

Founder & Data Professional

Founder Ngulik Data. Passionate about making data analysis accessible for everyone.

Artikel Terkait

7 SQL Client Gratis Terbaik buat Analis Data (2026)
Tutorial SQL
10 Juli 2026•9 menit baca

7 SQL Client Gratis Terbaik buat Analis Data (2026)

Nggak perlu bayar buat nulis query. Ini 7 SQL client gratis yang beneran dipakai analis, plus kelebihan dan kekurangannya masing-masing.

BimaBima
SQL Style Guide: Cara Nulis Query yang Enak Dibaca Tim
Tutorial SQL
7 Juli 2026•9 menit baca

SQL Style Guide: Cara Nulis Query yang Enak Dibaca Tim

Sepuluh aturan SQL style guide yang bikin query kamu kebaca sama tim — dan sama kamu sendiri 6 bulan lagi. Lengkap dengan contoh sebelum-sesudah.

BimaBima
Take-Home Test SQL Data Analyst: Contoh Soal + Cara Ngerjainnya
Tutorial SQL
4 Juli 2026•11 menit baca

Take-Home Test SQL Data Analyst: Contoh Soal + Cara Ngerjainnya

Contoh soal take-home test SQL yang beneran dipakai perusahaan, dikerjain step by step — dari baca soal, nulis query, sampai nyusun insight yang bikin recruiter nengok.

BimaBima
Kembali ke Blog
Ngulik Data logoNgulik Data

Platform edukasi data lengkap untuk professionals Indonesia. Belajar SQL, Data Analysis, dan lebih banyak lagi dengan praktek langsung dan feedback real-time.

Copyright © 2026 - All rights reserved

LINKS
SupportPricingDatasetBlogAffiliates
LEGAL
Terms of servicesPrivacy policy
Ngulik Data
DatasetLeaderboardBlogStore