SQL Practice Logo

SQLPractice Online

Data Types & Type Conversion: Mistakes

Module: SQL Fundamentals

Implicit Conversion Breaks Index

SELECT * FROM orders WHERE order_id = '12345'; -- STRING vs INTEGER column

SELECT * FROM orders WHERE order_id = 12345; -- match column type

Comparing a VARCHAR literal to an INTEGER column forces the database to convert EVERY row before filtering — the index is useless. 5M rows: 8,000ms vs 80ms. Always match your literal to the column type.

Critical

FLOAT for Financial Calculations

CREATE TABLE transactions (amount FLOAT); -- 0.1 + 0.2 = 0.30000000000000004

CREATE TABLE transactions (amount DECIMAL(19,4)); -- exact to 4 decimal places

FLOAT uses base-2 binary representation and cannot exactly store most base-10 decimals. $123.45 × 1.075 = $132.70875000000001 with FLOAT — audit failures and customer overcharging. Use DECIMAL for any value humans care about being exact.

Critical

TIMESTAMP Without Timezone in Global Apps

created_at TIMESTAMP DEFAULT NOW() -- no timezone: ambiguous for global users

created_at TIMESTAMPTZ DEFAULT NOW() -- UTC internally, converts on read

TIMESTAMP stores a local time with no context. When your app servers are in different regions or DST kicks in, "2024-03-10 02:30" becomes ambiguous. TIMESTAMPTZ stores UTC always and converts to any timezone on display.

High

CAST Without TRY_CAST in ETL Crashes Pipeline

INSERT INTO clean SELECT CAST(raw_amount AS DECIMAL(10,2)) FROM staging; -- crashes on 'N/A'

INSERT INTO clean SELECT TRY_CAST(raw_amount AS DECIMAL(10,2)) FROM staging; -- NULL on bad row

A single malformed value (empty string, "N/A", "null") causes CAST to throw an error and kill the entire INSERT. TRY_CAST returns NULL for bad rows, letting the pipeline continue. Quarantine NULLs separately for human review.

High

Converting the Column Instead of the Literal

WHERE CAST(employee_id AS VARCHAR) = '100' -- converts 5M column values, breaks index

WHERE employee_id = CAST('100' AS INTEGER) -- converts one literal, index intact

When you wrap the column in a function or CAST, the database cannot use the index on that column. Wrap the literal (constant) value instead — it is computed once, not per row.

High

INT When BIGINT Is Already Needed

user_id INTEGER -- max 2,147,483,647; Twitter exceeded this in 2010

user_id BIGINT -- max 9,223,372,036,854,775,807

INTEGER overflows at 2.1B. Once a sequence hits the max, INSERTs fail with "integer out of range". Migrating a primary key column to BIGINT after the fact on a busy table requires downtime and reindex. Choose BIGINT for any ID that could scale past ~1B.

Medium