Pelajaran modul (2/4)
Batasan berganda dan tingkat tabel
Memastikan bahwa data dalam database sudah benar pada lapisan paling dasar ("integritas data") adalah hal yang mendasar. Jika Anda hanya menulis keamanan ke dalam aplikasi Node.js, bug dapat menyebabkan data di DB tidak konsisten. Kendala di level DDL adalah garis pertahanan terakhir yang tidak bisa ditembus.
Kendala utama
Selain PRIMARY KEY (yang menjadikan kolom unik dan BUKAN NULL) dan NOT NULL klasik dan UNIQUE, ada dua kategori mendasar untuk konsistensi logis data:
1. KUNCI ASING (Integritas Referensial)
Batasan REFERENCES memastikan bahwa ID penautan benar-benar ada di tabel "induk" yang ditunjuknya.
Misalnya, pesanan harus ditautkan ke pelanggan yang ada.
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
customer_id INTEGER REFERENCES customers(id)
);Apa yang dilakukan Kunci Asing?
- Ini mencegah Anda memasukkan
customer_idyang tidak ada dicustomers. - Ini mencegah Anda dari
DELETE(menghapus) pelanggan daricustomersjika ada pesanan yang mengarah ke mereka (ini melindungi dari catatan "yatim piatu").
Kita juga dapat memutuskan apa yang akan terjadi bila "induk" dihapus:
customer_id INTEGER REFERENCES customers(id) ON DELETE CASCADEDengan ON DELETE CASCADE, jika kami menghapus pelanggan, Postgres akan secara otomatis menghapus semua orders yang tertaut! (Gunakan dengan sangat hati-hati; biasanya pengaturan default yang memblokir pengoperasian lebih disukai.)
2. PERIKSA Batasan
Batasan CHECK memvalidasi baris dengan menguji ekspresi boolean sebelum melanjutkan untuk menyimpan.
CREATE TABLE contratti (
id SERIAL PRIMARY KEY,
stipendio NUMERIC(10,2) CHECK (stipendio > 0),
data_inizio DATE,
data_fine DATE,
CHECK (data_fine > data_inizio)
);CHECK pertama adalah batasan kolom (hanya mengacu pada stipendio).
CHECK kedua di bawah adalah batasan tabel (dapat melintasi nilai dari beberapa kolom, dan harus dideklarasikan di bagian bawah).
Jika INSERT atau UPDATE mencoba menyimpan akhir sebelum awal, Postgres akan menolaknya dengan kesalahan!
Batasan Penamaan
Seringkali merupakan praktik yang baik untuk memberi batasan nama yang eksplisit (menggunakan kata kunci CONSTRAINT). Dengan cara ini, ketika Postgres memblokir catatan, kesalahan akan memberi tahu Anda misalnya "batasan 'stipendio_positivo' dilanggar", yang jauh lebih jelas untuk proses debug!
CREATE TABLE prodotti (
id SERIAL PRIMARY KEY,
nome VARCHAR(50),
CONSTRAINT nome_univoco UNIQUE(nome)
);Cobalah
Buat tabel 'prenotazioni' dengan id (SERIAL PRIMARY KEY) dan 'customer_id' (INTEGER). Gunakan CONSTRAINT fk_cliente FOREIGN KEY (customer_id) REFERENCES pelanggan(id) untuk memberikan nama eksplisit pada batasan Kunci Asing. Lakukan di bagian bawah, sebagai batasan tabel.
Tunjukkan petunjuk
Tulis CONSTRAINT fk_cliente FOREIGN KEY (local_column) REFERENSI external_table(external_col)
Solusi tersedia setelah 3 upaya
Batasan dengan logika khusus
Buat tabel 'eventi' dengan id (SERIAL PRIMARY KEY), posti_totali (INTEGER) dan biglietti_venduti (INTEGER). Tambahkan batasan tabel bernama 'check_capienza' di mana biglietti_venduti tidak boleh lebih besar dari posti_totali.
Tunjukkan petunjuk
Tambahkan batasan di bagian bawah menggunakan CONSTRAINT check_capienza CHECK (ekspresi)
Solusi tersedia setelah 3 upaya