Creating and Managing Tables
1. Creating Table
CREATE TABLE customers (
id bigserial PRIMARY KEY,
email text UNIQUE NOT NULL,
full_name text NOT NULL,
created_at timestamptz NOT NULL DEFAULT now()
);
| Clause | Purpose |
|---|---|
| column type | One of PG data types |
| DEFAULT expr | Auto value when not provided |
| NOT NULL | Forbid NULL |
| PRIMARY KEY | Unique + NOT NULL |
| GENERATED ... AS IDENTITY | Modern auto-increment PREFERRED |
2. Creating Table with Constraints
CREATE TABLE orders (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
customer_id bigint NOT NULL REFERENCES customers(id) ON DELETE RESTRICT,
status text NOT NULL CHECK (status IN ('new','paid','shipped','cancelled')),
total_cents integer NOT NULL CHECK (total_cents >= 0),
placed_at timestamptz NOT NULL DEFAULT now(),
CONSTRAINT orders_unique_ref UNIQUE (customer_id, placed_at)
);
3. Creating Temporary Table
CREATE TEMP TABLE staging_orders AS
SELECT * FROM orders WHERE status = 'new';
CREATE TEMP TABLE t (id int) ON COMMIT DROP;
| ON COMMIT | Behavior |
|---|---|
| PRESERVE ROWS | Keep data (default) |
| DELETE ROWS | Truncate at commit |
| DROP | Drop at commit (TX-scoped table) |
4. Creating Unlogged Table
CREATE UNLOGGED TABLE cache_entries (
key text PRIMARY KEY,
value jsonb,
expires_at timestamptz
);
| Property | Effect |
|---|---|
| No WAL | Faster writes, lost on crash |
| Not replicated | Skipped by streaming/logical |
| Use case | Caches, intermediate staging |
5. Creating Table from Query
CREATE TABLE big_customers AS
SELECT * FROM customers WHERE lifetime_value > 10000;
CREATE TABLE empty_copy AS SELECT * FROM customers WITH NO DATA;
Note:
CREATE TABLE AS copies columns and data but NOT indexes, constraints, defaults.6. Creating Table Like Another
CREATE TABLE customers_archive (
LIKE customers INCLUDING ALL EXCLUDING INDEXES
);
| Option | What It Copies |
|---|---|
| DEFAULTS | Default expressions |
| CONSTRAINTS | CHECK constraints |
| INDEXES | Indexes (incl. PRIMARY KEY/UNIQUE) |
| STORAGE | Per-column storage |
| COMMENTS | Comments |
| IDENTITY | Identity definition |
| GENERATED | Generated column expressions |
| ALL | All of the above |
7. Listing Tables
\dt
\dt+ app.*
SELECT table_schema, table_name
FROM information_schema.tables
WHERE table_type='BASE TABLE' AND table_schema NOT IN ('pg_catalog','information_schema');
8. Describing Table Structure
| Command | Output |
|---|---|
| \d table | Columns, indexes, constraints |
| \d+ table | Adds storage, stats target |
| \dS table | Include system columns |
SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_schema='app' AND table_name='customers'
ORDER BY ordinal_position;
9. Renaming Table
ALTER TABLE customers RENAME TO customer;
ALTER TABLE app.customers RENAME COLUMN email_address TO email;
10. Setting Table Owner
ALTER TABLE customers OWNER TO app_owner;
| Requirement | Detail |
|---|---|
| Caller | Member of new owner role |
| Existing privileges | Preserved on objects |
11. Copying Table Structure and Data
CREATE TABLE backup AS TABLE customers; -- shorthand
CREATE TABLE clone (LIKE customers INCLUDING ALL);
INSERT INTO clone SELECT * FROM customers;
12. Truncating Table
TRUNCATE TABLE staging;
TRUNCATE TABLE orders, order_items RESTART IDENTITY CASCADE;
| Option | Effect |
|---|---|
| RESTART IDENTITY | Reset identity/sequences |
| CONTINUE IDENTITY | Default; keep current |
| CASCADE | Truncate FK-referencing tables |
| RESTRICT | Default; error if FKs reference |
13. Dropping Table
DROP TABLE old_orders;
DROP TABLE IF EXISTS old_orders CASCADE;
Warning: CASCADE drops dependent views, FKs, and rules. Audit with
pg_depend first.