Constraints reject bad writes before they land. UNIQUE prevents duplicate values on a field; NOT NULL requires the field to be present; FOREIGN KEY links to another entity and governs what happens when the referenced row is deleted (CASCADE, RESTRICT, or SET NULL).
unique constraint violation. Composite keys (multiple fields) are allowed.null, are rejected.on_delete action:
listConstraints(entity) to inspect them.
flowchart TD
W["db.create or update"] --> Q{Check all
constraints}
Q -- UNIQUE collision --> X1[reject: unique]
Q -- NOT NULL missing --> X2[reject: not_null]
Q -- FK parent absent --> X3[reject: foreign_key]
Q -- all pass --> OK[write lands]
D["db.delete parent"] --> DQ{FK on_delete?}
DQ -- CASCADE --> D1[delete children too]
DQ -- RESTRICT --> D2[reject if children]
DQ -- SET NULL --> D3[null out FK on children]
style X1 fill:#ffcdd2,stroke:#c62828
style X2 fill:#ffcdd2,stroke:#c62828
style X3 fill:#ffcdd2,stroke:#c62828
style D2 fill:#ffcdd2,stroke:#c62828
style OK fill:#c8e6c9,stroke:#2e7d32
style D1 fill:#c8e6c9,stroke:#2e7d32
style D3 fill:#c8e6c9,stroke:#2e7d32
users.email. Click Add — the constraint appears in the list to the right.Seed data to create two users with the same email. The second insert is rejected (log shows ✗ unique constraint violation).Foreign key. Source is pre-filled: posts.author_id → users.id, on delete CASCADE. Click Add, then Setup FK demo → Delete parent. The child posts vanish with the user.RESTRICT, reset the demo, and try to delete the parent again. The delete is rejected while children exist.Run all tests at the bottom to see all six scenarios exercised automatically.Pick one or more fields to require unique values across the entity.
No constraints yet. Use the form on the left.
Pre-built scenarios that show each constraint in action. Each runs in isolation — start with Reset demo data between runs if you want a clean slate.
Adds a UNIQUE constraint on users.email, inserts Alice, then tries Bob with Alice's email.
Adds FK posts.user_id → users.id (RESTRICT), creates a user, then tries to add posts referencing real and fake user ids.
Adds FK comments.post_id → posts.id (CASCADE), creates a post with two comments, then deletes the post — comments vanish.
Adds FK comments.post_id → posts.id (RESTRICT), creates a post with one comment, then tries to delete the post — rejected.
| ID | Data |
|---|
Run all tests performs six scenarios in a fresh namespace (prefix test_) and reports each as pass or fail:
test_users.email rejects duplicate insertstest_users.name rejects rows without name