Module 1 › Data Types

Data Types: choosing the right type for every column

Module 1, Session 4. Why TEXT-for-everything is dangerous, core PostgreSQL data types, the type decision tree, and converting TEXT columns with ALTER TABLE ... TYPE ... USING.

Jo class mein bola, yahan nukte mein likha hai.
What I said in class, written here as key points.

← All NukteSELECT * FROM TheShiraverse

PostgreSQL Data Types

Why TEXT-for-everything is a production time bomb, mastering the 8 core types, the 10-second decision tree, and in-place schema conversions with ALTER TABLE ... TYPE ... USING.

25
Interactive Scenes
1
Practice Arena
5
Hands-on Drills
4
Interview Scenarios

Today’s Agenda — Data Types

Four architectural pillars to choose the right data type for every column and eliminate silent data corruption

Pillar 01
🛡️ Integrity & Cost
01 The ₹34 Lakh Bug (Fintech Incident)
02 Why Types Guard Data Integrity
03 Hardware Storage & Byte Footprint
Pillar 02
🔢 Numbers & Text
04 Whole Numbers: SMALLINT to BIGINT
05 Decimals: NUMERIC vs Float Drift
06 Text: CHAR, VARCHAR & The Phone Trap
Pillar 03
⏰ Time & Evolution
07 Horology: DATE, TIMESTAMPTZ & BOOLEAN
08 The 10-Second Type Decision Tree
09 ALTER TABLE & In-Place USING
Pillar 04
🏆 Production & Drills
10 RetailMart Live Schema Type Audit
11 Practice Arena: 5 Type Drills
12 Interview Studio & 4 Golden Rules
🛡️
The Production Reality: Storing numbers or dates as TEXT is a time bomb. PostgreSQL data types are hardware-level gatekeepers that reject corrupted writes, save massive SSD memory, and guarantee exact financial arithmetic.

Where We Left Off

✓ COMPLETED IN SESSION 3 3 FOUNDATIONS MASTERED

What We Built in Session 3

In the previous session, we moved from theory into writing real SQL in PostgreSQL:

✓
DDL Foundations: CREATE SCHEMA and CREATE TABLE to structure your database world.
✓
DML Operations: Populated rows with INSERT INTO and verified them with SELECT *.
✓
The "TEXT Shortcut": To get started fast without friction, we typed almost every column as TEXT.
⚠️ THE TODAY SHIFT SESSION 4 MISSION

Why We Must Graduate Today

Using TEXT for everything was training wheels. In production, it creates severe bugs:

⚠
Zero Protection: A TEXT price column happily accepts 'free', '-500', or 'N/A'.
⚠
Broken Queries: SUM(amount) or AVG(rating) fails immediately on TEXT columns.
⚠
Today’s Goal: Master the 4 core type families, learn the 10-second decision tree, and convert TEXT columns using ALTER TABLE.
💡
The Lesson from Session 3: While TEXT made table prototyping fast, in production every column requires an explicit type. Types are hardware-level constraints that prevent corrupted writes and enable aggregate calculations.
💸
The Rs. 34 Lakh Bug WHY TEXT-FOR-EVERYTHING IS DANGEROUS
FINTECH STARTUP • BENGALURU 🕘 8 MONTHS LATER • QUARTER-END REPORT
STEP 01 • THE INCIDENT
fintech-startup Early architecture decision
“We will convert to numbers when we need to calculate.”
A Bengaluru fintech stored all transaction amounts as TEXT — same shortcut as our Session 3 tables. 8 months pass without a problem. Then quarter-end arrives.
STEP 02 • THE BOTTLENECK
📝 TEXT column
Accepted All
A frontend bug silently sent 'Rs.15,000' and 'fifteen thousand' as payment amounts. TEXT accepted every single one — no error, no warning.
🛡 NUMERIC(12,2)
Defense
The right type rejects bad input at the gate, before it ever touches disk. Rs. 34 lakh in bad entries = 0 rows if the column is NUMERIC.
STEP 03 • THE ONE-LINE FIX
8 months late
🐘 payments_fix — Day-Zero DDL Defense
-- Frontend bug: TEXT accepted all of these
INSERT INTO payments (user_id, amount)
  VALUES ('1003', 'Rs.15,000');   -- ✓ stored
INSERT INTO payments (user_id, amount)
  VALUES ('1004', 'fifteen thousand'); -- ✓ stored

-- Quarter-end SUM blows up:
SELECT SUM(amount::NUMERIC) FROM payments;
-- ERROR: invalid input syntax for type
--        numeric: 'Rs.15,000'

-- The fix — one ALTER, should have been day 0:
ALTER TABLE payments
  ALTER COLUMN amount TYPE NUMERIC(12,2)
  USING amount::numeric;
⚡ ALTER executed • column type changed ⚠ Rs. 34 lakh already corrupt
STEP 04 • CORE PRINCIPLE
The Moral: The right type is not paperwork — it is your first line of defense. TEXT accepts anything; NUMERIC rejects garbage at the gate. Choose the right type on day zero, not after 8 months of silent corruption.

Translating the ₹34 Lakh Bug to PostgreSQL

The Physical to Relational Protection Shield
DEFENSE SHIELD • 5 CORE DATA TYPES

Every vulnerability in the fintech incident directly maps to an essential PostgreSQL data type that rejects corrupted data at the hardware gate:

Fintech Bug Vector Protective Data Type Production Defense Guarantee
💵 Payment Amounts ('Rs.15,000') NUMERIC(12, 2) Exact base-10 arithmetic, rejects corrupt text at write time, zero float drift.
📱 Phone Numbers ('09876543210') VARCHAR(15) Preserves leading zeros and '+' formatting, prevents erroneous math.
⚡ UPI Transaction IDs BIGINT 64-bit scale (19-digit numbers) — never overflows even at 10,000 txns/sec.
📅 Payment Timestamps TIMESTAMPTZ Microsecond precision stored in UTC — immune to daylight saving shifts.
🔘 Settlement Status Flags BOOLEAN Strict 1-byte binary state (TRUE / FALSE) — zero ambiguity.
💡
The Crucial Insight: Data types are not bureaucratic paperwork — they are your hardware-level first line of defense. Pick the right type on Day Zero to reject garbage before it ever touches disk.

Whole Numbers: Physical Containers & Capacity Limits

In database hardware, data types are physical byte-sized containers on SSD & RAM. Pick the container that comfortably holds your data without wasting storage — but never let it overflow.

VISUAL MEMORY & CAPACITY SCALE • INTEGER DATA TYPES 2 Bytes • 4 Bytes • 8 Bytes • Sequence Engine
SMALLINT 2 BYTES (16-BIT)
32,767
Ratings, Age, Months • Saves 50% RAM
INTEGER (INT) 4 BYTES (32-BIT)
±214 CRORE
Course Default • 90% Production Choice
BIGINT 8 BYTES (64-BIT)
±9.22 × 10¹⁸
Global Telemetry • Never Overflows
SERIAL AUTO-INCREMENT
1, 2, 3, 4, 5...
Automatic Counter • Sequence Engine
SMALLINT
🎫 The Paper Ticket / Pocket Pass
2 BYTES • 16-BIT
PASS 16-BIT SEAT NUMBER # 042 LIMIT 32,767
RANGE: -32,768 to +32,767
Holds lightweight counts comfortably:
  • Customer age (0 to 120)
  • Star ratings (1 to 5 stars)
  • Month days (1 to 31) • Cinema seats
💥 RIPS IN HALF IF OVERLOADED:
Storing a salary of ₹50,000 breaks the 32,767 ceiling:
ERROR: smallint out of range
INTEGER / INT
🏢 The Heavy Bank Vault
4 BYTES • 32-BIT
MIN −214 Cr CAPACITY ±214 CRORE
RANGE: ±214 CRORE (2147483647)
Holds entire populations & inventories:
  • 140 Crore citizens in India + all of USA
  • Swiggy customer IDs • College roll numbers
  • Product catalog SKUs • Warehouse inventory
⭐ THE 90% DEFAULT CHOICE:
If a whole number represents typical human or enterprise counts, default to INT without second thought.
BIGINT
🪐 The Infinite Galactic Vault
8 BYTES • 64-BIT
SCALE ±9.22 × 10¹⁸ CAPACITY 19 DIGITS
RANGE: ±9223372036854775807
High-frequency telemetry & logs:
  • Razorpay / PhonePe UPI transaction IDs
  • YouTube global view counts
  • Nanosecond server timestamp logs
🛡️ NEVER OVERFLOWS IN HUMAN HISTORY:
Even if your app logs 10,000 transactions every second, BIGINT will not fill up for 2.9 crore years.
⚠ REAL-WORLD CRASH • GOOGLE YOUTUBE December 2014 • The 214 Crore Integer Ceiling
Why Psy’s “Gangnam Style” Made YouTube Switch to BIGINT:
YouTube stored view counts as a signed 32-bit INTEGER (max 2147483647, about 214 crore views). “Gangnam Style” was the first video to get close, so YouTube moved the counter to 64-bit BIGINT months before it reached the ceiling. One more view on a full INT would have wrapped to a negative number. (The spinning counter people saw was a joke animation.)
⚙ MECHANICAL GENERATOR SERIAL IS NOT A STORAGE TYPE
The Automatic Token Dispenser Machine:
SERIAL is simply a 4-byte INT column pre-wired to a mechanical numbering counter:
[0001] → [0002] → [0003] stamps nextval() automatically

Whole Numbers and Auto-IDs

PostgreSQL gives you four integer sizes plus auto-incrementing serials. Pick the smallest type that will NEVER overflow.

SMALLINT 2 Bytes (16-bit)
LIMIT: -32,768 to +32,767
Small counts & flags. Saves 50% RAM over INT in high-volume tables.
rating = 5 • age = 28 • seat = 42
💡 Overflows if value > 32,767
INTEGER / INT 4 Bytes (32-bit)
LIMIT: ±214 CRORE
The 90% production workhorse. Default choice for counts, IDs & quantities.
order_id = 104291 • cust_id = 4821
⭐ Course & Industry Default
BIGINT 8 Bytes (64-bit)
LIMIT: ±9.22 × 10¹⁸ (19 DIGITS)
Global transaction telemetry & event logs. Never overflows in human history.
upi_txn = 920194829104 • views = 520 crore
🛡️ Prevents the 214 Crore Overflow
SERIAL Auto-Sequence
ENGINE: INT + nextval('seq')
Shorthand helper: creates INT + dedicated generator sequence + NOT NULL.
id SERIAL PRIMARY KEY → 1, 2, 3...
⚙️ Mechanical ID Dispenser
PostgreSQL Integer Architecture & Overflow Guard
▶ Run Query
PostgreSQL
-- 1. Create a table with properly sized integer columns:
CREATE TABLE warehouse_inventory (
  item_id      SERIAL PRIMARY KEY,      -- Auto-increments: 1, 2, 3...
  shelf_tier   SMALLINT NOT NULL,       -- Tier 1 to 5 (Saves 50% memory)
  stock_count  INT NOT NULL,            -- Up to 214 Crore units
  global_rfid  BIGINT NOT NULL          -- 64-bit global tracking barcode
);

-- 2. Verify the SERIAL sequence engine underneath:
-- PostgreSQL creates a sequence: warehouse_inventory_item_id_seq
-- Sets default to: nextval('warehouse_inventory_item_id_seq')

-- 3. Overflow demonstration (Safe failure):
INSERT INTO warehouse_inventory (shelf_tier, stock_count, global_rfid)
  VALUES (99999, 100, 982104829104);
-- ERROR: smallint out of range (-32768 to 32767)

-- 4. Each type's exact ceiling (this is what ▶ Run shows):
SELECT 32767::SMALLINT AS smallint_max,
       2147483647::INT AS int_max,
       9223372036854775807::BIGINT AS bigint_max;

Decimals & Money: The Jeweler’s Scale vs The Floating Drift

Binary computers cannot represent base-10 fractions like 0.1 accurately. Storing money as FLOAT causes silent, accumulating loss across bank ledgers.

NUMERIC(p, s) / DECIMAL
⚖️ The Jeweler’s Scale • Exact Base-10
✓ ZERO DRIFT
0.10 0.20 0.1 + 0.2 = 0.30 ✓
Exact Digit-by-Digit Storage: Stores the number as exact base-10 digits on disk. Exactly matches the rupee and paise mathematics taught in school. Zero rounding drift down to the absolute last digit.
⭐ MANDATORY IN PRODUCTION FOR:
Prices, Checkout Gross/Net Totals, GST / Taxes, Account Balances & Razorpay Invoices.
REAL / FLOAT4 / FLOAT8
💥 The Floating Radar • IEEE 754 Drift
✗ BINARY APPROXIMATION
0.1 0.2 0.1 + 0.2 ≠ 0.3 ⚠️
Binary Floating-Point Approximation: Binary transistors cannot store fractions like 1/10 as exact finite binaries (identical to how 1/3 = 0.3333... has infinite decimals in base-10). It creates tiny phantom discrepancies on every single write.
⚠ FINANCIAL DISASTER IN ACCOUNTING:
Across lakhs of transactions the tiny errors add up: the books stop matching to the paisa and every bank audit fails.
ANATOMY OF NUMERIC(p, s) NUMERIC(10, 2)
12345678.95
• Precision (p = 10): Total digits allowed (8 before + 2 after decimal)
• Scale (s = 2): Exactly 2 digits reserved after decimal (paise / cents)

Decimals and Money

Storing currency as binary floating-point (REAL/FLOAT) introduces silent rounding drift. Always use NUMERIC for money.

NUMERIC / DECIMAL Arbitrary Precision
UP TO 1,31,072 DIGITS, EXACT
Exact base-10 digits. Mandatory for prices, money, and financial ledgers.
price = 1499.50 • gst = 269.91
⭐ Mandatory for Money & Ledger
REAL (FLOAT4) 4 Bytes (32-bit)
DRIFT: 6 DIGITS ACCURACY (APPROX)
Approximate binary float (6 decimal digits). For graphics and GPS coordinates.
latitude = 18.5204 • temp = 36.6
⚠️ Approximate: never for money
DOUBLE PRECISION 8 Bytes (64-bit)
DRIFT: 15 DIGITS ACCURACY (APPROX)
Approximate binary float (15 decimal digits). Scientific simulations & ML.
orbital_radius = 1.496e+8
🔭 Scientific & AI Vectors Only
The Float Drift Demonstration & Exact Money Schema
▶ Run Query
PostgreSQL
-- 1. Proof of Float Drift vs Exact Numeric in PostgreSQL:
SELECT 0.1::FLOAT8 + 0.2::FLOAT8   AS float_drift,
       0.1::NUMERIC + 0.2::NUMERIC AS exact_money;
-- float_drift: 0.30000000000000004  (❌ binary approximation, not 0.3)
-- exact_money: 0.3                  (✓ EXACT: matches rupee & paise arithmetic)

-- 2. Production Table Schema with Financial Constraints:
CREATE TABLE customer_orders (
  order_id     SERIAL PRIMARY KEY,
  subtotal     NUMERIC(10, 2) NOT NULL, -- Up to ₹9,99,99,999.99 with exact paise
  gst_tax      NUMERIC(10, 2) NOT NULL, -- 18% GST calculation
  total_billed NUMERIC(10, 2) GENERATED ALWAYS AS (subtotal + gst_tax) STORED
);

The Three Text Types: Storage Boxes & The Phone Trap

How text is physically packed on disk, why CHAR wastes blocks, and why formatted numeric identifiers are NOT numbers.

CHAR(10)
📦 Rigid Fixed Carton (Wasteful)
SPACE PADDED
P u n e [6 SPACES PADDED]
STORAGE: 10 FULL BYTES ALWAYS
Rigid Fixed Slots: Always pads out to exactly 10 characters with empty blank space characters. Storing the 4-letter city 'Pune' consumes 10 full bytes of SSD storage.
⚠ VERDICT: Almost NEVER use CHAR(n) in modern PostgreSQL schemas.
VARCHAR(n)
🛍️ Elastic Ziplock Bag (Tight)
NO PADDING
len=4 P u n e ZERO WASTE
STORAGE: EXACTLY 4 BYTES USED
Dynamically Fitted: Stores only the actual characters plus a 1-to-4 byte length prefix. 'Pune' consumes only 4 bytes of actual character data.
⭐ PRODUCTION WORKHORSE:
Names, Emails, Cities, Phone Numbers, Addresses & Status Flags.
TEXT
🏭 Open Infinite Warehouse
UP TO 1 GB
∞ NO CEILING (UP TO 1 GB) Same internal engine & speed as VARCHAR
STORAGE: IDENTICAL SPEED TO VARCHAR
Zero Performance Penalty: In PostgreSQL, TEXT and VARCHAR share identical performance. The (n) in VARCHAR is strictly a validation guard.
📝 BEST FOR:
Customer Reviews, Descriptions, Markdown Articles, Audit Logs & Bios.
⚠ ARCHITECTURE PITFALL The Phone Number • PIN Code • Aadhaar Trap
INPUT: "09876543210"
• Stored as a number (BIGINT): Strips leading zero → 9876543210 (CORRUPTED!)
• Stored as VARCHAR(15): Preserves formatting → "+91 09876 543210" (✓ SAFE)
The Golden Test: Do you ever SUM(), AVG(), or multiply it? If NO — it is TEXT (VARCHAR), NOT a number!

The Three Text Types

PostgreSQL stores all three with identical performance under the hood. Choose by data constraint, not speed myth.

CHAR(n) Fixed Length
STORAGE: FIXED n BYTES (PADDED)
Pads with blank spaces up to length n. Wasteful on SSD storage.
country_code = 'IN' (CHAR(2))
❌ Wasteful: Avoid in Modern Postgres
VARCHAR(n) Variable with Limit
STORAGE: ACTUAL BYTES + HEADER
Stores actual characters up to limit n. Standard for constrained inputs.
email = '[email protected]' (VARCHAR(255))
⭐ Standard for Constrained Inputs
TEXT Unlimited Variable
STORAGE: UP TO 1 GB (ZERO CEILING)
No arbitrary ceiling (up to 1 GB). Same speed as VARCHAR in PostgreSQL.
notes, reviews, bios, descriptions
⭐ Best for Unconstrained Text
Text Storage Inspection & Phone Number Proof
▶ Run Query
PostgreSQL
-- 1. Inspecting Actual Storage Footprint with octet_length():
SELECT
  octet_length('Pune'::CHAR(10))    AS char_bytes,    -- 10 bytes (Padded with 6 spaces!)
  octet_length('Pune'::VARCHAR(10)) AS varchar_bytes, -- 4 bytes (Zero wasted bytes!)
  octet_length('Pune'::TEXT)        AS text_bytes;    -- 4 bytes (Same speed & storage!)

-- 2. The Phone Number Trap Proof:
CREATE TEMP TABLE contacts (phone_int BIGINT, phone_txt VARCHAR(15));
INSERT INTO contacts VALUES (09876543210, '09876543210');

SELECT phone_int, phone_txt FROM contacts;
-- phone_int: 9876543210    (❌ Leading 0 stripped! Corrupt phone number!)
-- phone_txt: 09876543210   (✓ Preserved intact!)

Dates, Times & Flags: The Horology Studio

Calendar dates, instant timestamps with timezone shifts, durations, and binary decision flags.

DATE 4 BYTES
2026-10-11
Calendar Day Stamp
Year, Month & Day only: No hours, minutes, seconds or timezones. Stores birthdays and daily business reporting dates.
• birthday • order_date • hiring_date
TIMESTAMPTZ 8 BYTES
14:30 UTC
World Timezone Clock
Exact Microsecond Moment: Normalized and stored in UTC. Shifts automatically to the viewer's local timezone offset.
★ RECOMMENDED FOR: created_at, logs & payments
INTERVAL TIME SPAN
+ 30 DAYS
Sand Timer Duration
Duration Math: Represents an elapsed amount of time. Allows expressions like: now() - INTERVAL '7 days'.
• subscription_expires_at • trial_end
BOOLEAN 1 BYTE
TRUE
Physical Rocker Switch
3 Binary States: TRUE, FALSE, or NULL (unknown). Used for flags and status checks.
• is_active • is_delivered • verified
⭐ THE 95% PRODUCTION BASELINE Master these 8 types and you can build 95% of real-world database schemas:
SMALLINT INTEGER BIGINT NUMERIC(p,s) VARCHAR(n) TEXT TIMESTAMPTZ BOOLEAN

Dates, Times, and Flags

Store moments in time accurately across timezones, and binary states with boolean flags.

DATE 4 Bytes
STORAGE: YYYY-MM-DD ONLY
Calendar date only (2026-10-11). Birthdays, order dates.
date_of_birth = '1998-05-16'
📅 Daily Business & Birthdays
TIME 8 Bytes
STORAGE: HH:MM:SS ONLY
Time of day without date (14:30:00). Store operating hours.
opening_time = '09:30:00'
⏰ Operating Hours & Schedules
TIMESTAMPTZ 8 Bytes
STORAGE: UTC INSTANT ON DISK
Date + time. Always prefer TIMESTAMPTZ (normalizes to UTC).
created_at = '2026-10-11 14:30:00+05:30'
⭐ Mandatory for Logs & Audits
BOOLEAN 1 Byte
STORAGE: 3 BINARY STATES
TRUE, FALSE, or NULL. Flags like is_active, is_delivered.
is_active = TRUE • verified = FALSE
🔘 Binary Decision Flags
Timezone Normalization & Date Interval Math
▶ Run Query
PostgreSQL
-- 1. TIMESTAMPTZ Automatic Timezone Normalization:
SET timezone = 'Asia/Kolkata';
SELECT now() AS kolkata_time; -- e.g. 2026-10-11 14:30:00+05:30

SET timezone = 'America/New_York';
SELECT now() AS new_york_time; -- e.g. 2026-10-11 05:00:00-04:00 (Same instant in history!)

-- 2. Practical Date & Interval Math:
SELECT
  CURRENT_DATE + INTERVAL '30 days'  AS subscription_expiry,
  now() - INTERVAL '7 days'          AS active_user_window,
  AGE(CURRENT_DATE, '1998-05-16')    AS exact_customer_age;

The 10-Second Type Decision Tree

Follow this 4-step checklist for every column you create. Never guess.

1. Whole Numbers? INT or BIGINT
QUESTION: Can you count it?
Default to INT. Use BIGINT for transaction IDs & view counts.
INT: customer_id • BIGINT: txn_id
Rule: Never SERIAL for secondary FKs
2. Money or Decimals? NUMERIC(p,s)
QUESTION: Does it involve currency?
ALWAYS NUMERIC. NEVER use FLOAT or REAL for monetary values.
price = 1499.50 • tax = 18.00
Rule: Zero paisa rounding loss
3. Text or Strings? VARCHAR(n) or TEXT
QUESTION: Is it words or codes?
VARCHAR(n) when domain limit exists. TEXT for unconstrained notes.
phone = '+91-98765-43210' • review = TEXT
Rule: No arithmetic = TEXT
4. Dates & Times? TIMESTAMPTZ
QUESTION: When did it happen?
Always store timestamps with timezone awareness. DATE for birthdays.
created_at = now() • dob = '1998-05-16'
Rule: UTC normalization saves lives
⚡
The 10-Second Rule: If you perform math on it → INT, BIGINT, or NUMERIC. If it has leading zeros or symbols → VARCHAR. If it tracks a moment in history → TIMESTAMPTZ. If it is binary state → BOOLEAN.

ALTER TABLE — Turning Legacy TEXT Columns Into Proper Types

Convert columns to proper types WITHOUT dropping tables — using ALTER TABLE ... ALTER COLUMN ... TYPE ... USING. The USING clause tells PostgreSQL how to cast existing text values.

SYNTAX ANATOMY • THE 4 IN-PLACE MIGRATION CLAUSES SAFE IN-PLACE CONVERSION • ZERO TABLE DROPS
1. ALTER TABLE
college.students
Target database table
2. ALTER COLUMN
student_id
Target column to alter
3. TYPE target_type
TYPE INT
New protective data type
4. USING expression
USING student_id::int
Explicit casting formula
TEXT → INT AUTO-IDs & QUANTITIES
-- Cast text string to integer:
ALTER TABLE college.students
  ALTER COLUMN student_id TYPE INT USING student_id::int;
-- ▶ Run tries the cast alone:
SELECT '104291'::int AS student_id;
🛡️ Safety Net: Aborts safely if non-digits (like 'N/A') exist. Zero table corruption.
TEXT → DATE CALENDARS & BIRTHDAYS
-- Cast text string to DATE:
ALTER TABLE college.students
  ALTER COLUMN date_of_birth
  TYPE DATE USING date_of_birth::date;
-- ▶ Run tries the cast alone:
SELECT '1998-05-16'::date AS date_of_birth;
⚡ Superpower: Unlocks instant calendar math: AGE(CURRENT_DATE, date_of_birth).
TEXT → NUMERIC EXACT CURRENCY • ZERO DRIFT
-- Cast text fee to NUMERIC(10,2):
ALTER TABLE college.fee_payments
  ALTER COLUMN amount TYPE NUMERIC(10,2) USING amount::numeric;
-- ▶ Run tries the cast alone:
SELECT '1499.50'::numeric(10,2) AS amount;
💰 Why NUMERIC(10,2)? 10 total digits, 2 paise digits. Exact decimals, zero float drift.
TEXT → BOOLEAN 1 BYTE • 3 STATES
-- Cast text string to BOOLEAN:
ALTER TABLE college.students
  ALTER COLUMN is_active TYPE BOOLEAN USING is_active::boolean;
-- ▶ Run tries the cast alone:
SELECT 'true'::boolean AS is_active,
       '1'::boolean AS flag_one;
🔍 Intelligent Parser: Parses 'true', 'false', 't', 'f', '1', '0' automatically.
PRODUCTION TOOLKIT • OTHER ALTERS YOU WILL USE EVERY DAY ADD • RENAME • DROP
ADD COLUMN
ALTER TABLE t ADD COLUMN created_at TIMESTAMPTZ DEFAULT now();
RENAME COLUMN
ALTER TABLE t RENAME COLUMN old_name TO new_name;
DROP COLUMN
ALTER TABLE t DROP COLUMN unused;

Real World: The sales.orders Type Audit

All 9 columns of the real RetailMart orders table (1,50,000 orders) — each with its proper type. None of them left as generic TEXT.

TABLE: sales.orders Production Schema Type Audit
1,50,000 ROWS 9 COLUMNS 0 GENERIC TEXT 4 TYPE FAMILIES
1. INT — KEYS & IDS 4 BYTES • FAST INDEXES
order_id Primary key, one per order
INT (4B) = 5
cust_id Points to customers.customers
INT (4B) = 33879
store_id Points to stores.stores
INT (4B) = 178
payment_mode_id Code for how they paid
INT (4B) = 1
2. NUMERIC(12,2) — MONEY ZERO FLOAT DRIFT
gross_total Before discount. Never FLOAT!
NUMERIC(12,2) = ₹43,836.23
discount_amount CHECK (discount_amount >= 0)
NUMERIC(12,2) = ₹209.50
net_total What the customer paid
NUMERIC(12,2) = ₹43,626.73
3. DATE — CALENDAR DAY 4 BYTES • ISO YYYY-MM-DD
order_date Calendar day order placed
DATE (4B) = '2024-12-08'
4. VARCHAR(20) — STATUS CODE DOMAIN BOUNDED STRING
order_status 7 states, DEFAULT 'Processing'
VARCHAR(20) = 'Delivered'
5. ELSEWHERE IN RETAILMART — THE OTHER CORE TYPES REAL COLUMNS
reviews.rating INT + CHECK
customers.reviews: CHECK (1 to 5)
= 5 (★ ★ ★ ★ ★)
reviews.review_text TEXT
customers.reviews: free text
any length, no ceiling
addresses.is_default BOOLEAN (1B)
customers.addresses: main address?
= TRUE
65%
Practice Milestone 01

Query Mode: Unlocked — Data Types

Choosing the RIGHT type is the core skill — every wrong type is a future bug in production.

🧠Practice Time
🎯 SESSION 04 • FAANG DRILLS

Common Data Type Interview Pitfalls

Click any question below to inspect the verified technical model answer, the core underlying engineering concept, and the exact trap interviewers listen for.

DATA INTEGRITY & PRODUCTION TYPES

“Why should you NEVER store money as FLOAT or REAL in SQL?”

✓ VERIFIED MODEL ANSWER:
FLOAT and REAL are binary floating-point approximations — 0.1 + 0.2 becomes 0.30000000000000004. Over lakhs of transactions, accumulated float drift causes serious financial discrepancies. Always use NUMERIC(precision, scale) for monetary amounts because it stores exact base-10 decimals with zero rounding loss.
🧠 WHY INTERVIEWERS ASK THIS:

Tests whether you understand binary floating-point representation vs exact fixed-point decimals in relational databases.

⚠️ COMMON TRAP TO AVOID:

Never use FLOAT or DOUBLE PRECISION for financial, tax, or ledger columns.

Data Types Self-Check

Close your notes. Answer from memory. Click any card to reveal the verified answer.

1. Which type for money, and which must you never use?
2. Why is phone number VARCHAR, not INT? Give 2 reasons.
3. Write the ALTER statement converting a TEXT column to DATE.
4. What does the USING clause do in ALTER ... TYPE?
5. Do VARCHAR(100) and VARCHAR(50) use different disk storage for a 30-char name?
6. What happens if you run ALTER ... TYPE INT USING col::int on a column with 'N/A'?

The 4 Golden Rules Bento

The core principles governing PostgreSQL data integrity and storage types.

RULE 01 • DATA DEFENSE

The Right Type is Your First Line of Defense

NUMERIC for money (never FLOAT), VARCHAR for formatted codes, DATE for calendar days, and TIMESTAMPTZ for moments. Types reject invalid data at write time, before it can corrupt downstream queries.

⚡ Invalid writes fail at the gate — zero corrupt rows.
RULE 02 • MIGRATIONS

ALTER with USING Casts In Place

ALTER TABLE ... ALTER COLUMN ... TYPE ... USING converts existing data without dropping tables. If a cast fails, bad data is hiding in your table — clean it first.

🔄 Atomic in-place migration — zero table drops.
RULE 03 • THE MATH TEST

No Arithmetic Means It Is Text

Phone numbers, PIN codes, Aadhaar, and tracking IDs contain numbers but are not quantitative. If you don't SUM() or AVG() it, store it as VARCHAR.

🔢 The Math Test: Preserves leading zeros & formatting.
RULE 04 • PRODUCTION BASELINE

Master the Core 8 Types

SMALLINT, INT, BIGINT, NUMERIC(p,s), VARCHAR(n), TEXT, TIMESTAMPTZ, and BOOLEAN cover 95% of real-world database design needs.

🏆 The 95% Baseline — all you need for enterprise schemas.

Data Types Quick Reference Studio

A practical reference for core PostgreSQL data types and everyday ALTER migrations.

PostgreSQL Data Types Cheat Sheet
SQL REFERENCE
-- CORE DATA TYPES SUMMARY
SERIAL        -- Auto-incrementing ID (1,2,3...)
INT / BIGINT  -- Whole numbers for math (INT: ±214 crore)
NUMERIC(p,s)  -- Money and exact decimals (ALWAYS)
VARCHAR(n)    -- Short strings (names, emails, codes)
TEXT          -- Unlimited length strings (descriptions)
DATE          -- Calendar day (YYYY-MM-DD)
TIMESTAMPTZ   -- Exact moment with timezone
BOOLEAN       -- true / false
-- ALTER TABLE TYPE MIGRATIONS
ALTER TABLE t ALTER COLUMN c
  TYPE INT USING c::int;

ALTER TABLE t ALTER COLUMN c
  TYPE DATE USING c::date;

ALTER TABLE t ALTER COLUMN c
  TYPE NUMERIC(10,2) USING c::numeric;

ALTER TABLE t ALTER COLUMN c
  TYPE BOOLEAN USING c::boolean;

Take-Home Challenge: The Data Type Migration Sprint

Complete these hands-on migration drills in your local database before moving forward to Constraints.

🎯 THE 4-STEP MIGRATION SPRINT:
Step 1 — Audit Existing Types

Run a query on information_schema.columns to inspect your tables from Session 3 and list all columns currently defined as text.

Step 2 — Convert Identifier & Integer Columns

Use ALTER TABLE ... TYPE INT USING col::int on your primary IDs and whole numbers.

Step 3 — Convert Date & Timestamp Columns

Migrate calendar date columns to DATE using USING date_col::date.

Step 4 — Convert Financial Amounts to NUMERIC

Convert fee and price columns to NUMERIC(10,2). Prove that SUM(fee) now works directly without casting!

Master Curriculum Journey Roadmap

TheShiraverse Curriculum Flow
🟢 ACTIVE WAYPOINT: MODULE 1 • TOPIC 04 (Data Types & In-Place Migrations)
Track: 60 Topics • 6 Modules • Free & Live
01
TOPIC 01 Session 1 • Done
What is SQL & DBs?
Relational Model Port 5432 & Server 5 SQL Sublanguages Declarative Syntax
✓ COMPLETED VERIFIED
02
TOPIC 02 Session 2 • Done
How SQL is Organised
Database Hierarchy Schemas as Folders Tables as Files Catalog Introspection
✓ COMPLETED VERIFIED
03
TOPIC 03 Session 3 • Done
Writing First Queries
SELECT Evaluation CREATE • ALTER • DROP INSERT • UPDATE • DELETE The Safe WHERE Rule
✓ COMPLETED VERIFIED
04
TOPIC 04 Today • Live
Data Types & Migrations
Ending All-TEXT NUMERIC vs FLOAT INT • DATE • TIMESTAMPTZ ALTER ... TYPE ... USING
📍 YOU ARE HERE ACTIVE
05
TOPIC 05 Up Next
Constraints & Keys
NOT NULL • DEFAULT CHECK • UNIQUE PRIMARY KEY FOREIGN KEY
🔒 NOT STARTED UP NEXT
✦ THE FOCUSED ASCENT: ZERO CONCEPTS ➔ SCHEMAS & ARCHITECTURE ➔ FIRST QUERIES & MUTATIONS ➔ STRICT DATA TYPES ➔ CONSTRAINTS & KEYS ✦

Next Session: Protecting Data with Constraints & Keys

NEXT MISSION • CONSTRAINTS & KEYS
Constraints & Keys: Guardrails & Relational Identity
Moving from choosing data types to enforcing declarative business rules and relational bridges — physically preventing invalid data, duplicate entries, and orphan rows at the database engine kernel.
• THE SHIRAVERSE
🛡
1. NOT NULL
Forbid missing values on critical fields and prevent unexpected application crashes at write time.
⚡
2. DEFAULT Values
Auto-populate fallback values and audit timestamps cleanly with DEFAULT now() and static literals.
⚙️
3. CHECK Constraints
Enforce mathematical domain logic: CHECK (price > 0), CHECK (discount BETWEEN 0 AND 100).
🔒
4. UNIQUE Constraints
Guarantee zero duplicate records on natural business keys like user emails, phone numbers, and handles.
🔑
5. PRIMARY KEY
Anchor unique entity identity (surrogate vs natural) and govern physical index lookup speed on disk.
🔗
6. FOREIGN KEY & Actions
Build referential bridges between tables and control cascading deletes with RESTRICT vs CASCADE.
→ next   ← back   F fullscreen   H hide bars   N notes
1 / 23