PostgreSQL Create Table
Overview
Tables are the basic structure for storing data in PostgreSQL. This chapter explains how to create tables using the CREATE TABLE statement.
CREATE TABLE Statement
Basic Syntax
sql
CREATE TABLE table_name (
column1 datatype [constraints],
column2 datatype [constraints],
...
[table_constraints]
);Simple Examples
sql
-- Create a simple users table
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Create products table
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2),
description TEXT
);Data Types
Common Data Types
| Type | Description | Example |
|---|---|---|
| INTEGER | Integer | 42 |
| SERIAL | Auto-incrementing integer | 1, 2, 3... |
| VARCHAR(n) | Variable-length string | 'hello' |
| TEXT | Unlimited text | 'long text...' |
| BOOLEAN | Boolean value | TRUE, FALSE |
| DATE | Date | '2024-01-15' |
| TIMESTAMP | Timestamp | '2024-01-15 10:30:00' |
| DECIMAL(p,s) | Exact numeric | 99.99 |
| JSON/JSONB | JSON data | '{"key": "value"}' |
Column Constraints
Common Constraints
sql
CREATE TABLE employees (
-- Primary key constraint
id SERIAL PRIMARY KEY,
-- Not null constraint
name VARCHAR(100) NOT NULL,
-- Unique constraint
email VARCHAR(100) UNIQUE,
-- Default value
status VARCHAR(20) DEFAULT 'active',
-- Check constraint
age INTEGER CHECK (age >= 18),
-- Foreign key constraint
department_id INTEGER REFERENCES departments(id)
);Constraint Descriptions
| Constraint | Description |
|---|---|
| PRIMARY KEY | Primary key, uniquely identifies each row |
| NOT NULL | Does not allow null values |
| UNIQUE | Values must be unique |
| DEFAULT | Default value |
| CHECK | Check condition |
| REFERENCES | Foreign key reference |
Table-Level Constraints
Composite Primary Key
sql
CREATE TABLE order_items (
order_id INTEGER,
product_id INTEGER,
quantity INTEGER NOT NULL,
PRIMARY KEY (order_id, product_id)
);Composite Unique Constraint
sql
CREATE TABLE user_roles (
user_id INTEGER,
role_id INTEGER,
UNIQUE (user_id, role_id)
);Named Constraints
sql
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2),
CONSTRAINT positive_price CHECK (price > 0),
CONSTRAINT unique_name UNIQUE (name)
);Creating Tables with Foreign Keys
sql
-- Create parent table first
CREATE TABLE departments (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL
);
-- Then create child table
CREATE TABLE employees (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
department_id INTEGER,
CONSTRAINT fk_department
FOREIGN KEY (department_id)
REFERENCES departments(id)
ON DELETE SET NULL
ON UPDATE CASCADE
);Foreign Key Options
| Option | Description |
|---|---|
| ON DELETE CASCADE | Cascade delete when parent is deleted |
| ON DELETE SET NULL | Set to NULL when parent is deleted |
| ON DELETE RESTRICT | Prevent deletion of referenced parent |
| ON UPDATE CASCADE | Cascade update when parent key changes |
Conditional Creation
sql
-- Create only if table doesn't exist
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL
);Create Table from Query
sql
-- Create new table from existing table
CREATE TABLE active_users AS
SELECT * FROM users WHERE status = 'active';
-- Copy structure only without data
CREATE TABLE users_backup (LIKE users INCLUDING ALL);Temporary Tables
sql
-- Create temporary table (auto-deleted at session end)
CREATE TEMPORARY TABLE temp_results (
id INTEGER,
value TEXT
);
-- Or use TEMP keyword
CREATE TEMP TABLE temp_data (
id INTEGER,
data JSONB
);Practical Example
E-commerce Database Schema
sql
-- Users table
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Products table
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name VARCHAR(200) NOT NULL,
description TEXT,
price DECIMAL(10, 2) NOT NULL CHECK (price >= 0),
stock INTEGER DEFAULT 0 CHECK (stock >= 0),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Orders table
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id),
total_amount DECIMAL(10, 2) NOT NULL,
status VARCHAR(20) DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Order items table
CREATE TABLE order_items (
id SERIAL PRIMARY KEY,
order_id INTEGER NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
product_id INTEGER NOT NULL REFERENCES products(id),
quantity INTEGER NOT NULL CHECK (quantity > 0),
unit_price DECIMAL(10, 2) NOT NULL
);View Table Structure
sql
-- Using psql command
\d table_name
\d+ table_name -- Detailed info
-- Using SQL query
SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_name = 'users';