Primary key (PK) là danh tính của mỗi dòng — NOT NULL, UNIQUE, không đổi; thường dùng surrogate key (serial/UUID). Bảng nối có thể dùng PK ghép: PRIMARY KEY (order_id, product_id).
Foreign key (FK) giữ tính toàn vẹn liên kết: không thể chèn orders.user_id = 999 nếu chưa có user 999, và không xóa được user khi còn order trỏ tới (trừ khi đặt CASCADE).
Ứng xử khi xóa/sửa cha (ON DELETE):
- RESTRICT (mặc định): chặn nếu còn con — an toàn nhất.
- CASCADE: xóa/sửa lan xuống con.
- SET NULL: đặt FK con về NULL (cột phải nullable).
Lưu ý hiệu năng: PK tự có index, nhưng cột FK nên tự thêm index — thiếu thì mỗi lần xóa/sửa cha sẽ quét toàn bộ bảng con. Lưu ý đáng nói: FK đảm bảo nhất quán nhưng tốn chi phí mỗi ghi; một số hệ throughput cực cao tắt FK và tự kiểm soát ở tầng app — đánh đổi nhất quán lấy tốc độ.
A primary key (PK) is each row's identity — NOT NULL, UNIQUE, immutable; usually a surrogate key (serial/UUID). Junction tables may use a composite PK: PRIMARY KEY (order_id, product_id).
A foreign key (FK) preserves referential integrity: you can't insert orders.user_id = 999 if user 999 doesn't exist, and you can't delete a user while orders still reference them (unless CASCADE is set).
Behavior when the parent is deleted/updated (ON DELETE):
- RESTRICT (default): blocks if children exist — safest.
- CASCADE: deletes/updates cascade down to children.
- SET NULL: sets the child FK to NULL (column must be nullable).
Performance note: a PK is indexed automatically, but you should index FK columns yourself — without it, every parent delete/update scans the whole child table. Notable pitfall: FKs guarantee consistency but cost something on every write; some very-high-throughput systems disable FKs and enforce integrity in the app layer — trading consistency for speed.