LambdaLabTM
Databases & SQL · Class 12 · Getting Started with MySQL
MySQLconstraints⏱️ 11 min read

Constraints

A data type says what kind of value a column holds. A constraint goes further and says which values are acceptable: this one may not be left empty, that one may not repeat. Write the rule once, when you build the table, and the database enforces it on every row anyone ever adds.

1A rule you only have to write once

You could try to be careful instead — always check for a duplicate Aadhaar before adding a teacher, always remember the name is compulsory. People forget, and programs have bugs. A constraint cannot forget. It is checked by the server on every single insert, by every user, for ever.

A constraint is a restriction placed on a column that the database enforces.

2The five you need

Constraints
ConstraintWhat it forbidsDuplicates?NULLs?
primary keyTwo rows that cannot be told apartNot allowedNot allowed
not nullLeaving the column emptyAllowedNot allowed
uniqueThe same value appearing twiceNot allowedAllowed
defaultNothing — it supplies a value insteadAllowedAllowed
checkAny value failing a condition you writeAllowedAllowed
Which of the five your paper asks for
The Computer Science (083) syllabus names not null, unique and primary key. default and check come from the class notes; check in particular is not in the Informatics Practices (065) syllabus, and its section below is marked accordingly.
unique vs primary key
They look similar and the difference is exactly one thing: unique allows NULL, a primary key does not. And a table may have many unique columns but only one primary key. Combining unique not null gives you something that behaves like a primary key — which is precisely what an alternate key is.

3Writing them into a table

A constraint is written after the data type, on the same line as the column. Here is the teachers table, which uses all four:

MySQL command line client
mysql> create table teachers (
-> id int primary key,
-> name varchar(30) not null,
-> designation varchar(15),
-> sal float,
-> doj date,
-> pan varchar(15) unique,
-> aadhar bigint unique not null,
-> city varchar(30) default 'Singtam');
Query OK, 0 rows affected (0.22 sec)

Read it as a set of decisions about the school:

id … primary key

Every teacher has an id, and no two share one. This is how a row is identified.

name … not null

A teacher without a name is not a record worth keeping. It may repeat, though — two people can share a name.

pan … unique

No two teachers can have the same PAN. But a new joiner may not have submitted it yet, so NULL is allowed.

aadhar … unique not null

Both rules together: compulsory, and never repeated. An alternate key.

city … default 'Singtam'

Most teachers live locally, so that is filled in when nobody says otherwise.

designation, sal, doj

No constraints. They may be left empty and may repeat freely.

4Where they show up in desc

MySQL command line client
mysql> desc teachers;
+-------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| id | int | NO | PRI | NULL | |
| name | varchar(30) | NO | | NULL | |
| designation | varchar(15) | YES | | NULL | |
| sal | float | YES | | NULL | |
| doj | date | YES | | NULL | |
| pan | varchar(15) | YES | UNI | NULL | |
| aadhar | bigint | NO | UNI | NULL | |
| city | varchar(30) | YES | | Singtam | |
+-------------+-------------+------+-----+---------+-------+
8 rows in set (0.00 sec)

Every constraint you wrote is visible here, in one of three columns:

Null: NO

not null is in force. id, name and aadhar all say NO.

Key: PRI / UNI

PRI is the primary key; UNI marks a unique column — pan and aadhar.

Default: Singtam

The default value, sitting where every other column says NULL.

5Watch them refuse

This is the part that makes constraints believable. Each of these is a real attempt to break one of the rules above.

A duplicate primary key. Student 1099 already exists:

MySQL command line client
mysql> insert into students values (1099,'Duplicate',10,80,'2010-01-01','Singtam');
ERROR 1062 (23000): Duplicate entry '1099' for key 'students.PRIMARY'

A NULL primary key. Every row must be identifiable:

MySQL command line client
mysql> insert into students values (NULL,'NoId',10,80,'2010-01-01','Singtam');
ERROR 1048 (23000): Column 'id' cannot be null

A duplicate unique value. That Aadhaar belongs to somebody already:

MySQL command line client
mysql> insert into teachers (id,name,aadhar,pan) values (13,'Clash',411122223333,'ZZZPZ1111Z');
ERROR 1062 (23000): Duplicate entry '411122223333' for key 'teachers.aadhar'

A missing compulsory value. The teacher's name was left out, and name is not null:

MySQL command line client
mysql> insert into teachers (id,designation,aadhar) values (14,'PGT',412345678901);
ERROR 1364 (HY000): Field 'name' doesn't have a default value
Read that last message carefully
It says doesn't have a default value rather than “cannot be null”. MySQL is explaining its reasoning: you gave no name, so it looked for a default to fall back on, and there was none. Had the column been declared name varchar(30) not null default 'Unknown', the row would have been accepted.

6check — a rule of your ownOptional for Informatics Practices

Who this section is for
The Computer Science (083) syllabus lists not null, unique and primary key; check comes from the class notes and is worth knowing alongside them. It is not in the Informatics Practices (065) syllabus, so IP students can skip this section.

The four constraints so far are fixed rules — no duplicates, no empties. check lets you write your own condition, and the database refuses any row that fails it.

A school admits children between 3 and 20. Nothing about int says that, so say it yourself:

MySQL command line client
mysql> create table admissions (
-> adm_no int primary key,
-> name varchar(30) not null,
-> age int check (age >= 3 and age <= 20),
-> grade int,
-> city varchar(30) default 'Singtam');
Query OK, 0 rows affected (0.25 sec)

The condition in the brackets is an ordinary one — the same and and comparisons a where clause uses. A sensible age is accepted without comment:

MySQL command line client
mysql> insert into admissions values (101, "Tenzing", 14, 9, "Gangtok");
Query OK, 1 row affected (0.01 sec)

An age of 25 is not:

MySQL command line client
mysql> insert into admissions values (102, "Too Old", 25, 12, "Namchi");
ERROR 3819 (HY000): Check constraint 'admissions_chk_1' is violated.

And neither is an age of 2, at the other end:

MySQL command line client
mysql> insert into admissions values (103, "Too Young", 2, 1, "Namchi");
ERROR 3819 (HY000): Check constraint 'admissions_chk_1' is violated.
>= and <= mean the boundaries are allowed
Ages of exactly 3 and exactly 20 are both accepted — run them and MySQL says Query OK. That is what >= and <= buy you. Written as > and <, a three-year-old could not be admitted.

The rule guards update as well, which is easy to forget — a constraint is a promise about the data, not about one command:

MySQL command line client
mysql> update admissions set age = 30 where adm_no = 101;
ERROR 3819 (HY000): Check constraint 'admissions_chk_1' is violated.

admissions_chk_1 is the name MySQL gave the rule, since we did not name it. You can see it, and the exact condition, with show create table:

the middle of the CREATE TABLE that MySQL stored
mysql> show create table admissions;
`adm_no` int NOT NULL,
`name` varchar(30) NOT NULL,
`age` int DEFAULT NULL,
`grade` int DEFAULT NULL,
`city` varchar(30) DEFAULT 'Singtam',
PRIMARY KEY (`adm_no`),
CONSTRAINT `admissions_chk_1` CHECK (((`age` >= 3) and (`age` <= 20)))
Older MySQL accepted it and ignored it
Before version 8.0.16, MySQL would let you write a check and then never enforce it — which is worse than not having one. Everything above was run on MySQL 8.0.46, where it is properly enforced. If a check seems to do nothing on an old lab machine, that is why.

7A primary key of two columns

The Keys lesson introduced the composite key: when no single column is unique, a group of columns acts as the primary key together. Here is how that is actually written — primary key moves to its own line at the end, with the columns in brackets:

MySQL command line client
mysql> create table attendance (
-> adm_no int,
-> adate date,
-> present char(1),
-> primary key (adm_no, adate));
Query OK, 0 rows affected (0.24 sec)
 
mysql> desc attendance;
+---------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+---------+------+-----+---------+-------+
| adm_no | int | NO | PRI | NULL | |
| adate | date | NO | PRI | NULL | |
| present | char(1) | YES | | NULL | |
+---------+---------+------+-----+---------+-------+
3 rows in set (0.01 sec)

Two rows of the description say PRI. One student may appear on many dates, and one date covers many students — but the pair occurs once, which is exactly the rule an attendance register needs:

MySQL command line client
mysql> insert into attendance values (101,"2026-09-11","Y");
ERROR 1062 (23000): Duplicate entry '101-2026-09-11' for key 'attendance.PRIMARY'

Notice the duplicate value MySQL reports: '101-2026-09-11' — the two columns joined together. That is the clearest possible evidence that the key is the combination, not either column on its own.

8default, doing its job

The other three constraints refuse things. default is the one that helps: leave the column out and it fills itself in.

MySQL command line client
mysql> insert into teachers (id, name, aadhar) values (99, "Default City", 400000000001);
Query OK, 1 row affected (0.03 sec)
 
mysql> select id, name, city from teachers;
+----+--------------+---------+
| id | name | city |
+----+--------------+---------+
| 99 | Default City | Singtam |
+----+--------------+---------+
1 row in set (0.01 sec)

No city was supplied, and Singtam appeared anyway. Without the default the cell would have been NULL. A default is a sensible guess, not a rule — you can still write any other city, and it will be accepted.

9Recap

primary key

No duplicates, no NULLs, one per table. Shows as PRI.

not null

A value is compulsory. Shows as Null: NO.

unique

No duplicates, but NULL is allowed. Shows as UNI. Many per table.

default v

Fills in v when you supply nothing. Shows in the Default column.

Quick Check

What is the difference between unique and primary key?

Quick Check

A column is declared city varchar(30) default 'Singtam'. A row is inserted without a city. What is stored?

Quick Check

Which error appears when you insert a row whose primary key value is already present?

Quick Check

Which constraint would you use for a column that must always be filled in but may repeat?