What Is a Column in a Database? Columns Explained Simply
A column in a database is a vertical set of values that share the same data type and represent a single attribute of an entity. In a customers table, "email" is a column. Every row in that table has an email value (or NULL), and all those values together form the email column.
Columns in Context
Think of a database table like a spreadsheet:
- Rows (records) go horizontally and represent individual entities (one customer, one order, one product)
- Columns (fields) go vertically and represent attributes (name, email, created_at, status)
| id | name | plan | created_at | |
|---|---|---|---|---|
| 1 | Acme Corp | acme@example.com | enterprise | 2025-01-15 |
| 2 | Beta Inc | beta@example.com | starter | 2025-03-22 |
| 3 | Gamma LLC | gamma@example.com | pro | 2025-06-01 |
This table has 5 columns and 3 rows. Each column stores one type of information about each company.
Column Properties
Every column has several properties defined when the table is created:
Data Type
The kind of data the column stores:
| Data Type | Stores | Example |
|---|---|---|
| INTEGER / INT | Whole numbers | id, quantity, age |
| DECIMAL / NUMERIC | Precise numbers | price, tax_rate |
| VARCHAR(n) | Variable-length text up to n characters | name, email |
| TEXT | Unlimited text | description, notes |
| BOOLEAN | True/false | is_active, has_paid |
| DATE | Calendar date | birth_date, hire_date |
| TIMESTAMP | Date and time | created_at, updated_at |
| UUID | Universally unique identifier | id (in modern systems) |
| JSON / JSONB | Structured data | metadata, preferences |
Choosing the right data type matters for:
- Storage efficiency: INTEGER uses 4 bytes; VARCHAR(255) can use up to 255
- Query performance: Numeric comparisons are faster than string comparisons
- Data integrity: A DATE column rejects "hello" as input
- Functionality: Date columns support date arithmetic; text columns support pattern matching
Constraints
Rules that limit what values a column can hold:
| Constraint | Meaning | Example |
|---|---|---|
| NOT NULL | Cannot be empty | email VARCHAR(255) NOT NULL |
| UNIQUE | No duplicate values | email VARCHAR(255) UNIQUE |
| PRIMARY KEY | Unique identifier for each row (NOT NULL + UNIQUE) | id SERIAL PRIMARY KEY |
| FOREIGN KEY | Must reference a value in another table | customer_id REFERENCES customers(id) |
| DEFAULT | Value used when none is provided | status VARCHAR(20) DEFAULT 'active' |
| CHECK | Custom validation rule | age INT CHECK (age >= 0) |
Default Values
What the column contains when no explicit value is provided during INSERT:
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
status VARCHAR(20) DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
is_archived BOOLEAN DEFAULT FALSE
);
Column vs. Field vs. Attribute
These terms are often used interchangeably, but technically:
| Term | Context | Meaning |
|---|---|---|
| Column | Database/SQL | The physical storage structure |
| Field | Application/forms | A place where data is entered or displayed |
| Attribute | Data modeling/ER diagrams | A property of an entity |
| Property | Object-oriented programming | A characteristic of an object |
In practice, saying "the email column," "the email field," or "the email attribute" all refer to the same thing in different contexts.
Creating and Modifying Columns
Creating a table with columns
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name VARCHAR(200) NOT NULL,
description TEXT,
price DECIMAL(10, 2) NOT NULL CHECK (price >= 0),
category VARCHAR(50),
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Adding a column to an existing table
ALTER TABLE products ADD COLUMN sku VARCHAR(50) UNIQUE;
Modifying a column
-- Change data type
ALTER TABLE products ALTER COLUMN price TYPE DECIMAL(12, 2);
-- Add NOT NULL constraint (requires existing NULLs to be filled first)
UPDATE products SET category = 'uncategorized' WHERE category IS NULL;
ALTER TABLE products ALTER COLUMN category SET NOT NULL;
-- Rename a column
ALTER TABLE products RENAME COLUMN name TO product_name;
Removing a column
ALTER TABLE products DROP COLUMN is_active;
Column Naming Best Practices
Good column names make databases self-documenting:
| Practice | Good | Bad |
|---|---|---|
| Descriptive | customer_email | ce |
| Snake_case (SQL convention) | first_name | firstName |
| Singular (the column holds one value per row) | emails | |
| No reserved words | user_status | status (reserved in some DBs) |
| Include units where ambiguous | duration_seconds | duration |
| Consistent prefixes for related columns | billing_address, billing_city | address, city_for_billing |
Indexed Columns
An index is a data structure that speeds up queries on specific columns. Think of it like a book index: instead of reading every page (row) to find a topic, you look it up in the index.
-- Create an index on a frequently queried column
CREATE INDEX idx_orders_customer_id ON orders(customer_id);
-- Composite index for queries that filter on multiple columns
CREATE INDEX idx_orders_status_date ON orders(status, created_at);
Index columns you frequently:
- Filter with WHERE
- Join with JOIN ON
- Sort with ORDER BY
- Group with GROUP BY
Do not index columns that:
- Are rarely queried
- Have very few distinct values (boolean columns with 50/50 distribution)
- Change constantly (indexes slow down writes)
Computed and Generated Columns
Some columns derive their value from other columns rather than being stored directly:
-- Virtual generated column (computed on read)
ALTER TABLE orders ADD COLUMN total_with_tax DECIMAL(10,2)
GENERATED ALWAYS AS (subtotal * (1 + tax_rate)) STORED;
-- In a query (not stored)
SELECT
first_name || ' ' || last_name AS full_name,
price * quantity AS line_total
FROM order_items;
Columns in Analytics
When analyzing data, columns serve different roles:
| Role | Description | Examples |
|---|---|---|
| Dimension | Categorical attributes you group by | region, product_category, status |
| Measure | Numeric values you aggregate | revenue, quantity, duration |
| Time | Temporal attributes for trending | order_date, created_at |
| Identifier | Unique keys for joining | customer_id, order_id |
Platforms like Skopx automatically identify these roles when connecting to your database, letting you ask analytical questions without knowing the schema: "What is revenue by region?" automatically groups by the region dimension and sums the revenue measure.
Summary
A column is the fundamental building block of database structure. It defines what kind of data can be stored, enforces rules about valid values, and determines how efficiently that data can be queried. Well-designed columns with appropriate types, constraints, and indexes make databases fast, reliable, and easy to understand.
Saad Selim
The Skopx engineering and product team