Module F-2·22 min read

Data types, CREATE TABLE, INSERT, SELECT, UPDATE, DELETE — every fundamental operation from first principles.

F-2 — Tables, Rows, and the Relational Mental Model

Who this module is for: You completed F-1, have PostgreSQL installed, and can connect with psql. Now you need to understand what a table actually is, what data types exist and which to use, and how to perform every fundamental SQL operation — creating tables, inserting data, reading it, modifying it, and deleting it. No assumed knowledge of SQL.


The Relational Mental Model

A relational database stores data in tables. A table is the simplest structure to grasp: it is a spreadsheet.

text
  • A column (also called a field or attribute) defines a piece of data every row will have — its name and type
  • A row (also called a record or tuple) is one complete entity — one user, one order, one product
  • A cell is the intersection of a row and column — one specific value

The critical difference from a spreadsheet: in PostgreSQL, every value in a column must match that column's declared type. You cannot store the number 42 in a column declared as TEXT, and you cannot store the string "hello" in a column declared as INTEGER. The database enforces this for you.


Data Types — The Foundation of Every Column

Choosing the right data type for each column is one of the most important decisions you make. The wrong type causes subtle bugs, wastes storage, and breaks operations you will want to do later.

Numbers

sql

When to use which:

  • INTEGER — counts, ages, quantities, foreign key references (if table will stay under 2 billion rows)
  • BIGINT — auto-incrementing IDs in high-traffic systems, timestamps as milliseconds
  • NUMERIC(10, 2) — prices ($999,999.99), percentages, anything where exact decimal matters
  • Never use FLOAT or DOUBLE PRECISION for financial data — 0.1 + 0.2 is not exactly 0.3 in floating point

Text

sql

The rule: use TEXT for everything unless you have a specific reason to enforce a maximum length. VARCHAR(255) is a habit from older databases — in PostgreSQL, TEXT is just as efficient and more flexible.

True/False

sql

PostgreSQL accepts TRUE, FALSE, 't', 'f', 'yes', 'no', '1', '0' when inserting.

Dates and Times

sql

The most important rule in this module: always use TIMESTAMPTZ, never bare TIMESTAMP. A bare TIMESTAMP stores a date and time with no timezone context — if your server's timezone changes, or if you have users in multiple timezones, the stored values become ambiguous. TIMESTAMPTZ stores UTC internally and converts to/from the session timezone transparently.

Unique Identifiers

sql

For primary keys: use BIGSERIAL for most tables. Use UUID when you need IDs generated client-side or across distributed systems.


CREATE TABLE

sql

A complete example:

sql

Breaking this down:

  • id BIGSERIAL PRIMARY KEY — auto-incrementing integer, unique identifier for each row
  • name TEXT NOT NULL — required text field (cannot be left empty)
  • description TEXT — optional (can be NULL — the absence of a value)
  • price NUMERIC(10,2) NOT NULL — exact decimal, required
  • in_stock BOOLEAN NOT NULL DEFAULT true — required, defaults to true if not provided
  • created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() — automatically set to the current time

Naming conventions: use snake_case (lowercase with underscores). Do not use spaces, capital letters, or reserved words (order, user, table need to be quoted if used as names — avoid them).

Verify the table was created

sql

INSERT — Adding Rows

sql

RETURNING — get the generated ID back:

sql

This is essential in application code — you insert a row and immediately get back the auto-generated ID to use in subsequent operations.


SELECT — Reading Data

sql

Why avoid SELECT * in production code:

  • If you add a column later, SELECT * returns it automatically — potentially including sensitive data
  • The query plan cannot be optimised as well without knowing which columns are needed
  • Your application code breaks when column order changes

LIMIT — get a subset of rows:

sql

UPDATE — Modifying Existing Rows

sql

⚠️ The most dangerous mistake with UPDATE: forgetting the WHERE clause.

sql

Always write the WHERE clause before running an UPDATE. Always. In psql, you can add LIMIT 1 to test your condition first:

sql

RETURNING works with UPDATE too:

sql

DELETE — Removing Rows

sql

⚠️ Same danger as UPDATE: DELETE FROM products without a WHERE clause deletes every row.

sql

TRUNCATE — faster than DELETE for removing all rows:

sql

Use TRUNCATE when you want to empty a table completely. Use DELETE when you need to remove specific rows or want to use RETURNING.


DROP TABLE — Removing the Table Itself

sql

DROP TABLE is permanent. Unlike DELETE (which removes rows but keeps the table structure), DROP TABLE removes everything — the structure, the data, the indexes, the constraints. There is no undo.


Practical Exercise: A Complete Products Workflow

Work through this from top to bottom in psql:

sql

NULL: The Absence of a Value

NULL means "no value" — it is not zero, it is not an empty string, it is the absence of any value. This trips up almost every beginner.

sql

Summary

OperationSQLRisk if you forget WHERE
Create tableCREATE TABLE name (cols...)N/A
Add rowsINSERT INTO name (cols) VALUES (...)N/A
Read rowsSELECT cols FROM nameNo risk
Modify rowsUPDATE name SET col = val WHERE ...Modifies every row
Remove rowsDELETE FROM name WHERE ...Deletes every row
Remove tableDROP TABLE nameN/A (always total)

The data types you will use 90% of the time:

  • BIGSERIAL for primary keys
  • TEXT for strings
  • INTEGER or BIGINT for whole numbers
  • NUMERIC(p,s) for exact decimals (especially money)
  • BOOLEAN for true/false
  • TIMESTAMPTZ for dates and times (always, never bare TIMESTAMP)

Module F-3 covers filtering and finding data — the WHERE clause in depth, sorting with ORDER BY, limiting results with LIMIT, and the string and date functions you will use constantly.

Next: F-3 — Filtering, Sorting, and Finding What You Need →


Knowledge Check

A Senior Principal Software Engineer is designing a global e-commerce platform where order creation times must be stored and consistently interpreted across various user timezones. Which PostgreSQL data type is the most appropriate choice for the 'created_at' column, and why?


An operations team needs to regularly clear a large, temporary staging table containing millions of rows before importing new data. The table has no foreign key constraints and no row-level triggers. Which SQL command is the most efficient and appropriate for this task, and what are its key advantages over alternatives?


A microservice in a production environment retrieves user profile data using SELECT * FROM users WHERE id = :userId;. From a Senior Principal Software Engineer's perspective, why is using SELECT * in this context considered a poor practice, particularly for long-term maintainability and performance?

Test your knowledge with more question sets

Sign in to access a wider variety of questions and get notified when new practice sets are added to this module.

Sign in & Register

Discussion

0

Join the discussion

Loading comments...

© 2026 Jatin Jain Saraf (JJS). All rights reserved.