CREATE: Databases, Schemas and Tables
CREATE defines the objects data lives in. Learn CREATE DATABASE, CREATE SCHEMA and CREATE TABLE, with column definitions and inline constraints.
- SQL Basics
- DDL
- DML
- SELECT
- WHERE
- Functions
- NULL and Logic
- Aggregate Functions
- GROUP BY
- JOIN
- Subqueries
- Set Operations
- CTEs
- Constraints
- Keys
- Relationships
- Database Design
- Normalisation
- Views
- Window Functions
- Advanced SQL
- Procedures and Functions
- Triggers
- Temporary Tables
- Transactions
- Isolation and Locking
- Indexes
- Query Performance
- SQL Security
- SQL Dialects
- Practical SQL
Concept
DDL (Data Definition Language) defines the shape of the database. CREATE is where every database begins: a database, then a schema, then tables with typed columns and the constraints that keep the data honest.
Syntax
CREATE DATABASE database_name;
CREATE SCHEMA schema_name;
CREATE TABLE [schema_name.]table_name (
column_name data_type [column_constraint] [, ...]
[, table_constraint]
);Example
CREATE DATABASE IF NOT EXISTS sql_path;
USE sql_path; -- MySQL and SQL Server
CREATE TABLE departments (
id INT NOT NULL,
name VARCHAR(60) NOT NULL,
location VARCHAR(60) NULL,
CONSTRAINT pk_departments PRIMARY KEY (id),
CONSTRAINT uq_departments_name UNIQUE (name)
);
CREATE TABLE employees (
id INT NOT NULL AUTO_INCREMENT,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
email VARCHAR(120) NULL,
dept_id INT NULL,
hire_date DATE NOT NULL,
salary DECIMAL(10,2) NOT NULL,
status VARCHAR(10) NOT NULL DEFAULT 'active',
PRIMARY KEY (id),
UNIQUE KEY uq_employees_email (email),
CONSTRAINT fk_employees_dept FOREIGN KEY (dept_id)
REFERENCES departments(id),
CONSTRAINT ck_employees_salary CHECK (salary >= 0)
);Explanation
Every part of that statement is doing a job:
NOT NULL- the column must always have a value.DEFAULT 'active'- the value used when theINSERTdoes not mention the column.PRIMARY KEY- identifies a row and, in practice, creates a unique index.FOREIGN KEY-dept_idmust match an existingdepartments.id.CHECK- a rule the database refuses to break, so no application bug can store a negative salary.- Named constraints (
fk_employees_dept) mean error messages tell you which rule failed, andALTER TABLE ... DROP CONSTRAINThas something to name.
Dialect notes
| Need | MySQL / MariaDB | PostgreSQL | SQL Server | Oracle |
|---|---|---|---|---|
| Auto numbering | AUTO_INCREMENT | GENERATED ALWAYS AS IDENTITY or SERIAL | IDENTITY(1,1) | GENERATED AS IDENTITY |
| Skip if it exists | IF NOT EXISTS | IF NOT EXISTS | Test OBJECT_ID() first | Catch ORA-00955 |
| Switch database | USE db | Reconnect; SET search_path for schemas | USE db | Schemas belong to users |
Important rules
- A table name must be unique within its schema.
CREATE TABLEfails if a referenced parent table does not exist yet, so create parents first.- In MySQL, MariaDB and Oracle, DDL is auto committing: it silently ends the open transaction and cannot be rolled back. In PostgreSQL and SQL Server, DDL is transactional.
CHECKconstraints are enforced from MySQL 8.0.16 and MariaDB 10.2 onward. Older versions parse and ignore them.
Common mistakes
- Creating a child table before its parent and hitting a foreign key error.
- Relying on
CHECKin a legacy MySQL version where it was silently ignored. - Leaving constraints unnamed, then being unable to read or drop them later.
- Adding
IF NOT EXISTSeverywhere in a migration, which hides the fact that a step already ran with a different definition.
Best practices
- Name every constraint with a readable prefix:
pk_,uq_,fk_,ck_. - Declare
NOT NULLunless unknown is genuinely meaningful for that column. - Put
CREATE TABLEstatements in version controlled migration files, never type them straight into production. - Add the constraints at creation time. Adding them later means cleaning up bad rows first.
Practice
- Write
CREATE TABLE projectswith an id, a name, a nullabledept_idthat referencesdepartments, a budget that cannot be negative and a start date that defaults to today. - Which of your columns should be
NOT NULL, and why isend_datenot one of them? - Explain what would happen if you ran your statement twice without
IF NOT EXISTS.