We have secured our tables using structural constraints (PRIMARY KEY, NOT NULL). Now we must implement pure Business Logic at the lowest level of the database using the final two constraints: CHECK and DEFAULT.
CHECKConstraint: A custom mathematical True/False formula evaluated against incoming data. If the data evaluates to "False" against your formula, the database physically rejects the insertion.DEFAULTConstraint: A safety-net fallback value. If a backend Python or Java application completely forgets to send a value for a column, the Database injects theDEFAULTvalue instead of throwing an error or insertingNULL.
If you declare a column Price INT, MySQL will happily let you insert -500 into it because mathematically, -500 is indeed a valid integer.
We use these constraints because Data Types only check the shape of the data, but CHECK constraints verify the actual sanity of the data based on CEO business rules.
CHECK: Protects the company from impossible states (Negative bank account balances, or users whose Age is listed as 999).DEFAULT: Saves network bandwidth! When an API creates a million users on a Friday, it doesn't need to manually sendis_active = TRUEa million times across the internet. It can just send names and passwords, and the Database Engine will seamlessly inject theTRUEdefaults natively to save time.
- Use
CHECKfor numeric boundaries (Prices, Ratings 1-to-5, Ages) or specific String patterns. - Use
DEFAULTfor common initial states (Account Creation Datestamps, Initial Balances, Status Flags).
If you are ever interviewing for a Senior Database Engineer role, you must know this historical trap:
Prior to MySQL Version 8.0.16 (released in 2019), MySQL famously ignored the CHECK constraint! If you wrote CREATE TABLE... CHECK (Age >= 18), the MySQL engine would read your code, successfully compile it, and then completely ignore the math. It would happily let you insert a 5-year-old.
Why? The original storage engine architecture wasn't designed for complex inline math. If you are forced to work on a legacy MySQL 5.7 Server today, you cannot trust CHECK constraints. You must build complex backend SQL programs called "Triggers" to manually simulate the math. (Don't worry, modern MySQL 8.0 fully enforces CHECK beautifully).
You declare these exactly on the same row as the Column Definition.
CREATE TABLE Products (
Product_Name VARCHAR(100),
-- Using DEFAULT
Inventory_Count INT DEFAULT 0,
-- Using CHECK
Price DECIMAL(10,2) CHECK (Price >= 0.99)
);The YouTube Video Upload Logic:
- You upload a video. The
Viewscolumn doesn't need to be sent by the frontend API. It natively triggers aDEFAULT 0. - The
Like_Ratiocolumn natively triggers aDEFAULT 'Unrated'. - The
Video_Lengthcolumn fires aCHECK (Length_Seconds > 0)ensuring corrupted 0-second video files are immediately rejected by the database.
Let's formally define a robust table using explicit constraints:
CREATE TABLE Bank_Accounts (
Account_ID INT PRIMARY KEY AUTO_INCREMENT,
Owner_Name VARCHAR(100) NOT NULL,
-- The fallback. Everyone starts with zero dollars.
Balance DECIMAL(15,2) DEFAULT 0.00,
-- Advanced CHECK constraint. You cannot be negative!
CONSTRAINT chk_positive_balance CHECK (Balance >= 0.00),
-- Advanced CHECK constraint. A user rating must literally be 1, 2, 3, 4, or 5.
Customer_Rating INT,
CONSTRAINT chk_valid_rating CHECK (Customer_Rating BETWEEN 1 AND 5)
);
-- ❌ FATAL ERROR: This fails because the Rating is 9 (violating the CHECK!)
INSERT INTO Bank_Accounts (Owner_Name, Customer_Rating) VALUES ('Alice', 9);
-- ✅ SUCCESS: We completely forgot to send the Balance, so it inserts 0.00!
INSERT INTO Bank_Accounts (Owner_Name, Customer_Rating) VALUES ('Bob', 5);- Confusing DEFAULT with NOT NULL: A column can be
NOT NULLbut have no Default. A column can have a Default but legally allowNULL. If a Python script literally sends the commandINSERT ... VALUES (NULL), the Database will insert theNULL!DEFAULTonly triggers if the column is physically missing from the SQLINSERTcommand entirely. - Not Naming the Check Rules: As shown in Section 8 (
CONSTRAINT chk_positive_balance), you must explicitly name yourCHECKrules. If you don't, and the math fails, the server error log will just spit out: "Constraint 14xqz violated". That is useless for an engineer trying to figure out which column crashed.
Stacking CHECKs with AND:
You can build deeply complex mathematical validators within a single check statement using basic SQL operators (AND, OR, IN).
CREATE TABLE Flights (
-- The flight must take off BEFORE it lands natively!
Takeoff_Time DATETIME,
Landing_Time DATETIME,
-- Table-Level CHECK Constraint comparing two columns against each other!
CONSTRAINT chk_time_logic CHECK (Takeoff_Time < Landing_Time)
);- Task 1: Write the column definition for a
Subscribe_To_Newslettercolumn. It should be a Boolean (remember Phase 3 fakes this withTINYINT), and if the frontend API completely forgets to send a value, it should physically fall back toFALSE. - Task 2: Why must you be deeply cautious deploying a
CHECKconstraint on an ancient server running MySQL version 5.6? (Hint: See Section 5).