CREATE TABLE

Mendefinisikan tabel beserta tipe kolom dan nilai default secara terencana.

Daftar isi

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.

bash
# 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
);
SQL
text Keluaran
DROP TABLE
CREATE TABLE
CREATE TABLE

Setiap 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.

bash
# 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;
SQL
text Keluaran
CREATE TABLE
INSERT 0 2
 id |  kode
----+--------
  1 | SL-001
  2 | SL-002
(2 rows)

DROP TABLE

Dokumentasi 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.

bash
# 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;
SQL
text Keluaran
CREATE TABLE
INSERT 0 1
    nama    |  harga  | jumlah |   total
------------+---------+--------+-----------
 Label Buku | 2500.00 |     40 | 100000.00
(1 row)

DROP TABLE

Kolom 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#