Beginner: asking questions · Databases and the relational model · topic 4 of 62 · 35 min
CREATE TABLE and constraints
Explanation
Why let the database check the rules?
Your app should check input, but apps have bugs, and many programs (a website, a mobile app, a night-time import script) may write to the same table. A constraint is a rule stored in the table itself. The database checks it on every insert and update, from every program, every time. Bad data never gets in.
The shape of CREATE TABLE
CREATE TABLE accounts (
id INTEGER PRIMARY KEY,
holder TEXT NOT NULL,
email TEXT UNIQUE,
branch TEXT NOT NULL DEFAULT 'Pune',
balance INTEGER NOT NULL DEFAULT 0 CHECK (balance >= 0)
);| Constraint | Rule | Error when broken (SQLite) |
|---|---|---|
| NOT NULL | The column must have a value | NOT NULL constraint failed: accounts.holder |
| UNIQUE | No two rows may have the same value (NULLs are allowed) | UNIQUE constraint failed: accounts.email |
| CHECK (condition) | The condition must not be false | CHECK constraint failed: balance >= 0 |
| DEFAULT value | Used when an insert leaves the column out | Never fails; it fills a gap |
| PRIMARY KEY | Unique and identifies the row | UNIQUE constraint failed: ... |
| REFERENCES t(col) | A foreign key (needs PRAGMA foreign_keys = ON in SQLite) | FOREIGN KEY constraint failed |
Using DEFAULT
INSERT INTO accounts (id, holder, email, branch, balance)
VALUES (1, 'Asha Verma', 'asha@example.com', 'Mumbai', 15000);
INSERT INTO accounts (id, holder, email) VALUES (2, 'Ravi Kumar', 'ravi@example.com');
SELECT * FROM accounts;
-- 1 | Asha Verma | asha@example.com | Mumbai | 15000
-- 2 | Ravi Kumar | ravi@example.com | Pune | 0Notice the column list after the table name: (id, holder, email). Naming the columns in an INSERT is a good habit. The statement keeps working even if someone adds a column to the table later.
Table-level constraints
A constraint that involves several columns is written after the last column, as its own line. That is how order_items gets its composite primary key and its foreign keys.
CREATE TABLE order_items (
order_id INTEGER NOT NULL,
product_id INTEGER NOT NULL,
qty INTEGER NOT NULL CHECK (qty > 0),
price INTEGER NOT NULL,
PRIMARY KEY (order_id, product_id),
FOREIGN KEY (order_id) REFERENCES orders(id),
FOREIGN KEY (product_id) REFERENCES products(id)
);INTEGER PRIMARY KEY and AUTOINCREMENT in SQLite
In SQLite, a column declared exactly INTEGER PRIMARY KEY fills itself in: leave it out of the INSERT and SQLite uses the largest id so far plus one. If you delete the row with the largest id, that number can be used again.
Adding the word AUTOINCREMENT (INTEGER PRIMARY KEY AUTOINCREMENT) promises that an id is never reused, even after deletes. It costs a little extra work, and the SQLite docs advise using it only when you truly need that promise, for example when old ids are printed on receipts.
-- Insert 'p' and 'q' (ids 1 and 2), delete id 2, insert 'r':
-- INTEGER PRIMARY KEY -> r gets id 2 (reused)
-- INTEGER PRIMARY KEY AUTOINCREMENT -> r gets id 3 (never reused)Changing and removing tables
ALTER TABLE customers ADD COLUMN loyalty_points INTEGER NOT NULL DEFAULT 0;
DROP TABLE IF EXISTS old_imports;SQLite's ALTER TABLE can add, rename and drop columns and rename a table, with limits: an added column cannot be UNIQUE or a PRIMARY KEY, and a NOT NULL column needs a DEFAULT, or you get "Cannot add a NOT NULL column with default value NULL".
Common mistakes
- A comma after the last column, or a missing comma between columns. Both are syntax errors; read the error's "near ..." part to find the spot.
- Expecting CHECK to reject NULL. CHECK (marks > 0) passes when marks is NULL, because the result is unknown, not false. Add NOT NULL as well if the value is required.
- Leaving out the column list in INSERT, then breaking when a column is added. Name the columns.
- Running CREATE TABLE twice and getting "table already exists". Use CREATE TABLE IF NOT EXISTS in setup scripts.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
CREATE TABLE and constraints · 1/7
Apps have bugs, and many programs write to one table. So we let the database itself check the rules. These rules are called constraints.
Prefer a video by a teacher? Find free videos on “sql create table constraints not null unique check default foreign key” on YouTube ↗
In real life: A wallet balance that can never go negative
A payments app keeps a wallet balance for each user. The app checks the balance before a payment, but if two payments arrive in the same instant, both checks might pass. A CHECK (balance >= 0) rule on the table is the last line of defence: the database itself refuses any update that would make a balance negative, whichever server or script sent it.
CREATE TABLE wallets (
user_id INTEGER PRIMARY KEY,
balance INTEGER NOT NULL DEFAULT 0 CHECK (balance >= 0) -- in paise
);Practice (0/3 done)
The database is empty. 1) Create a table accounts with columns id (INTEGER PRIMARY KEY), holder (TEXT NOT NULL), branch (TEXT NOT NULL DEFAULT 'Pune') and balance (INTEGER NOT NULL DEFAULT 0 CHECK (balance >= 0)). 2) Insert (1, 'Asha Verma', 'Mumbai', 15000) naming all four columns. 3) Insert account 2 for 'Ravi Kumar' giving ONLY id and holder, so the defaults are used. 4) SELECT id, holder, branch, balance FROM accounts.
Create a table results with columns roll (INTEGER PRIMARY KEY), name (TEXT NOT NULL) and marks (INTEGER CHECK (marks BETWEEN 0 AND 100)). You are given four rows: (1, 'Asha', 76), (2, 'Ravi', 67), (3, 'Karan', 105), (4, 'Imran', 0). One of them breaks the CHECK rule; try it and read the error. Then insert ONLY the valid rows and finish with SELECT roll, name, marks FROM results.
The SHOP owner starts a loyalty scheme. Add a column loyalty_points (INTEGER NOT NULL DEFAULT 0) to customers with ALTER TABLE, then return id, name and loyalty_points of every customer.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- The SQL language and your toolsDatabases and the relational model · same module
- INSERTChanging data, transactions and ACID
- INSERT, UPDATE and DELETEBackend Development · Databases and SQL basics
- What is a database?Backend Development · Databases and SQL basics
- UPDATE and DELETE safelyChanging data, transactions and ACID
- How indexes workIndexes, query plans and views
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
A column is declared marks INTEGER CHECK (marks >= 0). Which insert is accepted?
Answer: marks = NULL
CHECK fails only when the condition is false. With NULL it is unknown, so the row is accepted. Add NOT NULL to block it.
What does DEFAULT 0 do?
Answer: Puts 0 in the column when an INSERT leaves it out
DEFAULT supplies a value only when the insert does not give one.
In SQLite, what is the difference between INTEGER PRIMARY KEY and INTEGER PRIMARY KEY AUTOINCREMENT?
Answer: AUTOINCREMENT never reuses an id, even after deletes
Both fill in ids. Without AUTOINCREMENT, the id of a deleted last row can be used again.
Which statement deletes a table and all its rows, with no undo?
Answer: DROP TABLE
DROP TABLE removes the table itself. Always have a backup before using it on real data.
Why add constraints in the database when the app already checks the input?
Answer: Every program that writes to the table is checked, including buggy ones
Many programs may write to one table. Constraints protect the data from all of them.
A column is left out of an INSERT and has no DEFAULT and no NOT NULL. What value does it get?Related
In SQLite, foreign keys are declared but you can still insert an order for customer 99, who does not exist. Why?Related
Answer: Foreign key checks are off until PRAGMA foreign_keys = ON
SQLite enforces foreign keys only after the PRAGMA, once per connection.
Which statement adds a new row?Related
Answer: INSERT INTO
INSERT INTO table (columns) VALUES (...) adds rows.
What is special about a primary key?Related
Answer: Its value is unique for every row
A primary key identifies exactly one row, like a roll number or a PNR.
From What is a database?
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 1 more topic in “Databases and the relational model” before its exam: The SQL language and your tools.
- Module 1 exam: Databases and the relational model · 15 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, SELECT: filtering and sorting. 62 topics left in the course before the final exam.