Constraints and Data Integrity
# CHAPTER 19
Constraints and Data Integrity
1. Introduction
A database is the final line of defense against corrupted data. You cannot trust the frontend application. You cannot trust the backend PHP or Node.js code. Bugs happen. If a bug accidentally attempts to set an employee's salary to -5000, and the database accepts it, the company's financial reports are instantly ruined. In this chapter, we will learn how to build "Constraints"—strict mathematical rules applied directly to the columns to guarantee absolute Data Integrity.2. Learning Objectives
By the end of this chapter, you will be able to:-
Prevent missing data using
NOT NULL.
-
Apply fallback values using
DEFAULT.
-
Review the
UNIQUEconstraint.
-
Build complex validation logic using
CHECKconstraints.
- Alter existing tables to add defensive constraints.
3. The NOT NULL Constraint
By default, PostgreSQL allows you to insert an entirely blank row (a row full of NULL values). For critical fields like an email address or a password hash, this is unacceptable.
*(If a query executes INSERT INTO users (phonenumber) VALUES ('555-5555'), PostgreSQL will instantly crash and reject the query because email and passwordhash were not provided).*
4. The DEFAULT Constraint
Sometimes, a user doesn't provide data, but instead of rejecting the query, you want PostgreSQL to silently fill in a sensible default value.
*(Now, if you run INSERT INTO users (username) VALUES ('john');, the database automatically generates the ID, sets him to active, and stamps the exact UTC time).*
5. The UNIQUE Constraint (A Quick Review)
As discussed in Chapter 12, UNIQUE ensures that no two rows can share the exact same value. It is critical for emails, usernames, and serial numbers.
email VARCHAR(150) UNIQUE NOT NULL is the ultimate defensive definition for an account identifier.
6. The Powerful CHECK Constraint
This is where database architecture gets truly defensive. A CHECK constraint allows you to write actual mathematical boolean logic directly into the table definition. PostgreSQL will evaluate this logic on every single INSERT or UPDATE.
*(If a buggy backend script executes UPDATE products SET price = -50, PostgreSQL evaluates the CHECK (price > 0) constraint, sees it is false, and aggressively blocks the update).*
7. Adding Constraints to Existing Tables
You don't have to delete your tables to add constraints! You can use theALTER TABLE command to upgrade security on live production databases.
8. Mini Project: The Bulletproof Employee Table
Let's combine everything into a perfectly defensive, enterprise-grade table architecture.9. Common Mistakes
- Confusing Application Validation with Database Constraints: You should *always* validate emails and numbers in the frontend (React) and the backend (Node.js/PHP). However, you must *never* rely on them exclusively. Forms get bypassed. APIs get hit directly. The Database Constraint is the final, unbreakable wall.
-
Applying
NOT NULLto everything: Beginners often applyNOT NULLto every single column. This causes massive headaches later when forms are updated or optional fields are introduced. Only useNOT NULLon data that is mathematically critical to the application's survival.
10. Best Practices
-
Name your CHECK constraints: By default, if you just write
CHECK (age > 18), PostgreSQL generates a random, ugly name for the constraint (likeemployeesagecheck). If the constraint fails, the error log just prints the ugly name. It is better to explicitly name them:CONSTRAINT mustbeadult CHECK (age > 18).
11. Exercises
-
1.
Write the DDL to create a
rolecolumn that defaults to the string 'Subscriber' if no data is provided.
-
2.
Write an
ALTER TABLEcommand to add aUNIQUEconstraint to an existingphone_numbercolumn.
12. SQL Challenges
Write the DDL syntax for atask table. It must have a status column. Use a CHECK constraint to ensure the status can *only* be exactly 'Pending', 'In Progress', or 'Completed'.
13. MCQ Quiz with Answers
What is the primary purpose of a CHECK constraint in PostgreSQL?
If a column is defined as isadmin BOOLEAN DEFAULT FALSE, what happens when a developer executes an INSERT statement but completely forgets to include the isadmin column in their query?
14. Interview Questions
- Q: In a modern web stack, data is often validated in the frontend (e.g., React) and in the backend controller (e.g., Laravel/Django). Why is it still an absolute architectural requirement to duplicate validation logic using Database Constraints?
-
Q: Explain the difference between
UNIQUEandPRIMARY KEY. Can a table have multipleUNIQUEcolumns?
15. FAQs
Q: Can aCHECK constraint compare two different columns?
A: Yes! You can write CHECK (enddate > startdate). This guarantees a user cannot book a hotel checkout date that occurs *before* their check-in date!
16. Summary
Your database is now heavily armored. By utilizingNOT NULL, DEFAULT, and advanced CHECK constraints, you guarantee that corrupted data, negative prices, and impossible date ranges can never enter your system, regardless of how many bugs exist in the application code.