Quiz 2
Registry Synced

04 - SQL DDL: Creating Database Schemas

1824 words
9 min read

Reading compass

Now · 🎯 Learning Objectives

04 - SQL DDL: Creating Database Schemas

🎯 Learning Objectives

After reading this topic, you will be able to:
  • Write SQL DDL statements to create tables with appropriate data types
  • Define primary keys, foreign keys, and other constraints
  • Use ALTER TABLE to modify existing schemas
  • Explain the difference between CREATE TYPE and CREATE DOMAIN
  • Enforce referential integrity with ON DELETE/ON UPDATE actions

📋 Prerequisites

  • 03 - Relational Model — Keys (primary, foreign, candidate), domains, referential integrity
  • Basic SQL terminology — what a table is

📖 Core Content

4.1 Intuition: DDL is the Blueprint

If a database is a building, DDL (Data Definition Language) is the architectural blueprint. It defines:
  • What tables exist
  • What columns each table has
  • What data types those columns hold
  • What rules (constraints) the data must follow The actual data (rows) comes later via DML (INSERT, UPDATE, etc.). DDL is about structure — it's executed once and changes rarely.
Why This Matters: A well-designed schema is the foundation of a good database. Poor schema design leads to data anomalies, performance problems, and maintenance nightmares. Getting the DDL right is the most important step.

4.2 CREATE TABLE: The Basics

sql
CREATE TABLE instructor (
    ID        VARCHAR(5),
    name      VARCHAR(20) NOT NULL,
    dept_name VARCHAR(20),
    salary    NUMERIC(8,2),
    PRIMARY KEY (ID)
);
Syntax breakdown:
  • CREATE TABLE instructor (...) — Creates a table named instructor
  • ID VARCHAR(5) — Column named ID with variable-length string up to 5 chars
  • name VARCHAR(20) NOT NULL — Column cannot contain NULL values
  • salary NUMERIC(8,2) — Decimal number with 8 digits total, 2 after decimal point
  • PRIMARY KEY (ID) — Enforces uniqueness and NOT NULL on ID

4.3 SQL Data Types

CategoryData TypeDescriptionExample
StringCHAR(n)Fixed-length string (padded with spaces)CHAR(10) → 'hello '
StringVARCHAR(n)Variable-length string (up to n)VARCHAR(50) → 'hello'
NumericINT / INTEGERWhole numbers (typically 4 bytes)INT → 42
NumericSMALLINTSmall integer (2 bytes)SMALLINT → 100
NumericNUMERIC(p,d)Exact decimal (p total digits, d decimal)NUMERIC(8,2) → 12345.67
NumericREAL / FLOATApproximate floating pointREAL → 3.14
Date/TimeDATEDate (year-month-day)DATE → '2024-01-15'
Date/TimeTIMETime (hour:minute:second)TIME → '14:30:00'
Date/TimeTIMESTAMPDate + TimeTIMESTAMP → '2024-01-15 14:30:00'
Large ObjectBLOBBinary large object (images, files)BLOB
Large ObjectCLOBCharacter large object (text documents)CLOB
Choosing the right data type:
  • Use VARCHAR not CHAR for strings of varying length (saves space)
  • Use INT for whole numbers, NUMERIC for money (exact decimals)
  • Use DATE/TIMESTAMP for temporal data (not strings!)

4.4 Integrity Constraints

sql
CREATE TABLE student (
    ID        VARCHAR(5) PRIMARY KEY,    -- inline primary key
    name      VARCHAR(20) NOT NULL,       -- must have a value
    dept_name VARCHAR(20),
    tot_cred  NUMERIC(3,0) DEFAULT 0,     -- default value if not specified
    email     VARCHAR(50) UNIQUE,         -- no duplicates allowed
    age       NUMERIC(3,0) CHECK (age >= 0 AND age < 150), -- domain constraint
    CONSTRAINT valid_dept CHECK (dept_name IN ('CS', 'Math', 'Physics'))
);

NOT NULL

Ensures a column never has NULL:
sql
name VARCHAR(20) NOT NULL

UNIQUE

Ensures all values in a column (or combination) are distinct:
sql
email VARCHAR(50) UNIQUE

CHECK

Validates values against a condition:
sql
CHECK (salary >= 0)
CHECK (semester IN ('Fall', 'Spring', 'Summer'))
CHECK (end_date > start_date)

PRIMARY KEY

Shortcut for NOT NULL + UNIQUE. A table can have only one:
sql
PRIMARY KEY (ID)
-- or composite:
PRIMARY KEY (course_id, semester, year)

FOREIGN KEY

Links to another table's primary key:
sql
FOREIGN KEY (dept_name) REFERENCES department(dept_name)

4.5 Referential Integrity: ON DELETE and ON UPDATE

What happens when a referenced row is deleted or updated?
sql
CREATE TABLE course (
    course_id    VARCHAR(8) PRIMARY KEY,
    title        VARCHAR(50),
    dept_name    VARCHAR(20),
    credits      NUMERIC(2,0),
    FOREIGN KEY (dept_name) REFERENCES department(dept_name)
        ON DELETE CASCADE
        ON UPDATE CASCADE
);
ActionDELETE BehaviorUPDATE Behavior
CASCADEDelete referencing rowsUpdate referencing rows
SET NULLSet foreign key to NULLSet foreign key to NULL
SET DEFAULTSet to default valueSet to default value
RESTRICT (default)Reject deleteReject update
NO ACTIONSame as RESTRICT (check at end of transaction)Same as RESTRICT
Example: If department('CS') is deleted:
  • CASCADE: All courses with dept_name='CS' are also deleted
  • SET NULL: Courses' dept_name becomes NULL
  • RESTRICT: Delete is rejected until courses are reassigned
Best Practice: Use RESTRICT for critical data (don't accidentally delete a department and all its courses), CASCADE for dependent data (delete an order and its line items).

4.6 ALTER TABLE

Modify an existing table's schema:
sql
-- Add a column
ALTER TABLE instructor ADD COLUMN phone VARCHAR(15);
-- Drop a column
ALTER TABLE instructor DROP COLUMN phone;
-- Add a constraint
ALTER TABLE instructor ADD CONSTRAINT unique_email UNIQUE(email);
-- Add a foreign key
ALTER TABLE teaches ADD FOREIGN KEY (course_id) REFERENCES course(course_id);
-- Drop a constraint
ALTER TABLE instructor DROP CONSTRAINT unique_email;

4.7 DROP TABLE

Completely removes a table and its data:
sql
DROP TABLE instructor;  -- removes table permanently (irreversible!)
To delete all rows but keep the structure:
sql
DELETE FROM instructor;  -- removes all rows, table remains

4.8 CREATE TYPE vs. CREATE DOMAIN

Both create reusable data types, but with an important difference:
sql
-- CREATE TYPE: New type, no constraints
CREATE TYPE dollars AS NUMERIC(12,2) FINAL;
CREATE TABLE department (
    dept_name VARCHAR(20),
    building  VARCHAR(15),
    budget    dollars  -- uses the custom type
);
-- CREATE DOMAIN: New type WITH constraints
CREATE DOMAIN degree_level AS VARCHAR(10)
    CONSTRAINT degree_level_test
    CHECK (VALUE IN ('Bachelors', 'Masters', 'Doctorate'));
CREATE TABLE professor (
    name  VARCHAR(50),
    level degree_level  -- constrained to specific values
);
FeatureCREATE TYPECREATE DOMAIN
Constraints allowedNoYes
Overrideable operatorsYesNo
Column-level defaultsNoYes
Equivalent to typedefYesConstrained typedef

4.9 Schema Creation: Complete Example

Let's build a university database schema from scratch:
sql
-- Strong entities first (no foreign keys)
CREATE TABLE department (
    dept_name VARCHAR(20) PRIMARY KEY,
    building  VARCHAR(15),
    budget    NUMERIC(12,2) CHECK (budget >= 0)
);
CREATE TABLE student (
    ID        VARCHAR(5) PRIMARY KEY,
    name      VARCHAR(20) NOT NULL,
    dept_name VARCHAR(20),
    tot_cred  NUMERIC(3,0) DEFAULT 0,
    FOREIGN KEY (dept_name) REFERENCES department(dept_name)
);
-- ... more tables with foreign keys
CREATE TABLE course (
    course_id  VARCHAR(8) PRIMARY KEY,
    title      VARCHAR(50),
    dept_name  VARCHAR(20),
    credits    NUMERIC(2,0) CHECK (credits > 0),
    FOREIGN KEY (dept_name) REFERENCES department(dept_name)
);
-- Tables referencing earlier tables
CREATE TABLE takes (
    ID         VARCHAR(5),
    course_id  VARCHAR(8),
    semester   VARCHAR(6),
    year       NUMERIC(4,0),
    grade      VARCHAR(2),
    PRIMARY KEY (ID, course_id, semester, year),
    FOREIGN KEY (ID) REFERENCES student(ID),
    FOREIGN KEY (course_id) REFERENCES course(course_id)
);

📐 Key Formulas / Concepts

ConstraintSyntaxEffect
PRIMARY KEYPRIMARY KEY (col)Unique + NOT NULL; one per table
FOREIGN KEYFOREIGN KEY (col) REFERENCES t(col)Links to another table
NOT NULLcol type NOT NULLColumn must have a value
UNIQUEcol type UNIQUENo duplicate values allowed
CHECKCHECK (condition)Validates data against condition
DEFAULTcol type DEFAULT valSets default value
ON DELETE CASCADEON DELETE CASCADEDeleting parent deletes children
ON DELETE SET NULLON DELETE SET NULLDeleting parent nullifies FK
ON DELETE RESTRICTDefaultRejects delete if children exist

⚠️ Common Pitfalls

Pitfall 1: Forgetting that PRIMARY KEY Implies NOT NULL

The Mistake: Declaring PRIMARY KEY and also NOT NULL on the same column. Why It's Wrong: PRIMARY KEY already includes NOT NULL. Redundant declaration is harmless but unnecessary. Correct: Just use PRIMARY KEY.

Pitfall 2: Using VARCHAR for Dates

The Mistake: "I'll just store dates as VARCHAR — '2024-01-15' works fine." Why It's Wrong: VARCHAR dates don't prevent invalid dates ('2024-13-01'), can't be sorted chronologically, and can't use date arithmetic (ADD_MONTHS, etc.). Correct: Use DATE or TIMESTAMP for all temporal data.

Pitfall 3: Confusing CASCADE Actions

The Mistake: "ON DELETE CASCADE deletes the foreign key column, not the rows." Why It's Wrong: CASCADE means: when the parent row is deleted, also delete the child rows that reference it. It doesn't delete columns — it deletes entire rows. Correct: ON DELETE CASCADE: Parent row deleted → all child rows referencing it are deleted too. Use cautiously!

📝 Practice Questions

Q1. Write a CREATE TABLE statement for a department table with: dept_name (primary key), building, budget (must be >= 0).

Answer
sql
CREATE TABLE department (
    dept_name VARCHAR(20) PRIMARY KEY,
    building  VARCHAR(15),
    budget    NUMERIC(12,2) CHECK (budget >= 0)
);

Q2. Write a CREATE TABLE for employee with: emp_id (PK), name (NOT NULL), email (UNIQUE), salary (must be positive), dept_id (FK referencing department).

Answer
sql
CREATE TABLE employee (
    emp_id   INTEGER PRIMARY KEY,
    name     VARCHAR(50) NOT NULL,
    email    VARCHAR(100) UNIQUE,
    salary   NUMERIC(10,2) CHECK (salary > 0),
    dept_id  INTEGER REFERENCES department(dept_id)
);

Q3. What is the difference between DROP TABLE and DELETE FROM?

Answer
  • DROP TABLE instructor — Removes the entire table (structure + data). Table no longer exists.
  • DELETE FROM instructor — Removes all rows. Table structure remains, can still insert new data.
DROP is DDL (changes schema); DELETE is DML (changes data only).

Q4. Explain what ON DELETE CASCADE does. Give an example.

Answer
ON DELETE CASCADE means: when a row in the parent table is deleted, all rows in the child table that reference it are automatically deleted too.
Example: If department('CS') is deleted, and courses table has FOREIGN KEY (dept_name) REFERENCES department(dept_name) ON DELETE CASCADE, then all CS courses are deleted as well.
Use when: child rows have no meaning without the parent (e.g., order items without the order).

Q5. Add a column phone to the instructor table.

Answer
sql
ALTER TABLE instructor ADD COLUMN phone VARCHAR(15);

Q6. What is the difference between CREATE TYPE and CREATE DOMAIN?

Answer
  • CREATE TYPE creates a new data type (like typedef in C). Cannot add constraints.
  • CREATE DOMAIN creates a new data type WITH constraints (CHECK conditions).
Example:
sql
CREATE DOMAIN positive_int AS INTEGER CHECK (VALUE > 0);
CREATE TYPE ssn AS VARCHAR(9);  -- no constraints

Q7. What are the five possible actions for foreign key ON DELETE? Briefly describe each.

Answer
  1. CASCADE — Delete referencing rows too
  2. SET NULL — Set foreign key to NULL
  3. SET DEFAULT — Set foreign key to its default value
  4. RESTRICT — Don't allow delete if there are referencing rows
  5. NO ACTION — Same as RESTRICT, but checked at end of transaction

Q8. Write the ALTER TABLE commands to: (a) make email NOT NULL, (b) add a CHECK that age >= 18.

Answer
sql
-- (a) Make email NOT NULL
ALTER TABLE student ALTER COLUMN email SET NOT NULL;

-- (b) Add age check constraint
ALTER TABLE student ADD CONSTRAINT age_check CHECK (age >= 18);

🔗 Cross-References

Document outline

Keep your place and jump directly to a heading.

Table of Contents
System Normal // Awaiting Context

Intelligence Hub

Navigate the knowledge graph to generate context. The Hub adapts dynamically to surface backlinks, related notes, and metadata insights.