Topik ini membahas CREATE TABLE sebagai pernyataan perancangan paling mendasar, yaitu anatomi definisinya, nilai default, kolom pengenal otomatis, dan kolom terhitung. Modul definisi data menggunakan schema perpustakaan sebagai bahan, sehingga setiap keputusan desain pada topik-topik sebelumnya kini ditulis sebagai pernyataan DDL yang dapat dijalankan.
Anatomi CREATE TABLE#
CREATE TABLE menyebutkan nama tabel, lalu setiap kolom dengan tipe datanya beserta keterangan tambahan. Blok berikut membangun ulang dua tabel pertama dataset utama tanpa opsi senyap, sehingga status setiap pernyataan terlihat.
# bangun ulang kategori dan anggota beserta statusnya
PGOPTIONS='-c client_min_messages=warning' psql -U postgres -d perpustakaan <<'SQL'
DROP TABLE IF EXISTS peminjaman, buku, anggota, kategori CASCADE;
CREATE TABLE kategori (
id SERIAL PRIMARY KEY,
nama TEXT NOT NULL UNIQUE
);
CREATE TABLE anggota (
id SERIAL PRIMARY KEY,
nama TEXT NOT NULL,
email TEXT UNIQUE,
bergabung DATE NOT NULL,
aktif BOOLEAN NOT NULL DEFAULT TRUE
);
SQLDROP TABLE
CREATE TABLE
CREATE TABLESetiap baris definisi memuat tiga keputusan, yaitu nama kolom, tipe data yang dibahas pada modul jenis data, dan keterangan yang menegakkan aturan. NOT NULL menolak baris tanpa nilai, DEFAULT mengisi nilai ketika INSERT tidak menyebutkan kolomnya, dan PRIMARY KEY menggabungkan keunikan dengan keharusan terisi. Struktur hasilnya dapat diperiksa kembali dengan \d anggota sebagaimana topik esensial psql.
Nilai default#
DEFAULT menerima konstanta maupun fungsi, dan nilainya dipakai setiap kali INSERT tidak menyebutkan kolom tersebut. Dataset utama memakai pola ini dua kali, yaitu aktif BOOLEAN NOT NULL DEFAULT TRUE yang menandai anggota baru sebagai aktif, dan kolom pencatatan waktu yang mengisi dirinya dengan now(). Default yang bijak menghilangkan seluruh kelas kelalaian INSERT, karena kolom yang wajib ada menjadi mustahil terlupakan.
Nilai default juga menangani kolom baru pada tabel yang sudah berisi data. Menambahkan kolom dengan DEFAULT tidak menulis ulang tabel pada PostgreSQL modern, sehingga perubahan pada tabel besar tetap cepat, perilaku yang dijabarkan pada topik ALTER TABLE.
Kolom pengenal otomatis#
Dua cara tersedia untuk membuat pengenal bertambah sendiri. SERIAL adalah kependekan warisan yang membuat sequence dan mengikatnya sebagai default, sedangkan GENERATED ALWAYS AS IDENTITY adalah bentuk standar SQL yang lebih baru dan lebih eksplisit. Keduanya menghasilkan bilangan yang bertambah tanpa koordinasi dari aplikasi.
# pengenal otomatis dengan identity dan serial
psql -U postgres -d perpustakaan <<'SQL'
CREATE TABLE salinan (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
kode TEXT
);
INSERT INTO salinan (kode) VALUES ('SL-001'), ('SL-002');
SELECT * FROM salinan;
DROP TABLE salinan;
SQLCREATE TABLE
INSERT 0 2
id | kode
----+--------
1 | SL-001
2 | SL-002
(2 rows)
DROP TABLEDokumentasi resmi menyarankan identity untuk tabel baru karena maknanya tercantum pada definisi kolom, sedangkan SERIAL tetap dijumpai di mana-mana dan perlu dikenali. Bentuk GENERATED BY DEFAULT AS IDENTITY mengizinkan nilai eksplisit sesekali, misalnya saat migrasi data.
Kolom terhitung#
Kolom terhitung, yaitu generated column, menyimpan hasil ekspresi dari kolom lain pada baris yang sama. Nilainya selalu mutakhir karena dihitung ulang setiap kali barisnya berubah, dan tidak boleh ditulis langsung oleh INSERT.
# kolom terhitung untuk total nilai
psql -U postgres -d perpustakaan <<'SQL'
CREATE TABLE barang (
id SERIAL PRIMARY KEY,
nama TEXT NOT NULL,
harga NUMERIC(10,2) NOT NULL,
jumlah INTEGER NOT NULL DEFAULT 0,
total NUMERIC(12,2) GENERATED ALWAYS AS (harga * jumlah) STORED
);
INSERT INTO barang (nama, harga, jumlah) VALUES ('Label Buku', 2500, 40);
SELECT nama, harga, jumlah, total FROM barang;
DROP TABLE barang;
SQLCREATE TABLE
INSERT 0 1
nama | harga | jumlah | total
------------+---------+--------+-----------
Label Buku | 2500.00 | 40 | 100000.00
(1 row)
DROP TABLEKolom total tidak pernah disebut saat INSERT, dan SELECT tetap menampilkan nilainya. Alternatifnya adalah view yang menghitung saat dibaca, pilihan yang dibahas pada modul view, fungsi, trigger, sedangkan kolom terhitung menang ketika nilainya sering dibaca dan harus ikut diindeks.
Kesalahan umum#
Kesalahan pertama adalah mendefinisikan tabel tanpa kunci utama sama sekali, yang menyulitkan rujukan dan pembaruan baris di kemudian hari. Kesalahan kedua adalah menimbang semua kolom dengan batas panjang defensif, kebiasaan yang sudah dibedah pada topik jenis teks, sehingga definisi menjadi panjang tanpa perlindungan tambahan. Kesalahan ketiga adalah menamai kolom dengan kata yang bertabrakan dengan kata kunci SQL, misalnya order atau year, yang memaksa pembacaan berantai tanda kutip, sedangkan nama seperti tanggal_pesanan bebas dari masalah itu.
Kesalahan keempat adalah menaruh logika lintas tabel di CREATE TABLE, misalnya ingin total penjualan global sebagai kolom. Kolom terhitung hanya melihat barisnya sendiri, dan agregasi lintas baris adalah wilayah view atau query, bukan definisi tabel.
Ringkasan#
- CREATE TABLE menetapkan nama, tipe, dan keterangan per kolom, dengan NOT NULL, DEFAULT, dan PRIMARY KEY sebagai penegak aturan pertama.
- DEFAULT mengisi kolom yang tidak disebutkan pada INSERT, termasuk nilai dari fungsi seperti now().
- GENERATED ALWAYS AS IDENTITY menjadi cara baku membuat pengenal otomatis, sedangkan SERIAL adalah bentuk warisannya.
- Kolom terhitung menyimpan hasil ekspresi antarkolom pada baris yang sama dan tidak boleh ditulis langsung.
Referensi#
- Create Table — PostgreSQL Documentation — Referensi lengkap pernyataan CREATE TABLE.
- Basics — PostgreSQL Documentation — Bagian resmi tentang membuat, mengubah, dan menghapus tabel.
- Serial Types — PostgreSQL Documentation — Penjelasan SERIAL dan perbandingannya dengan identity.