By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
You’re analyzing sales data in a PostgreSQL database. Your query joins orders (stored as VARCHAR) with customers (stored as INTEGER). The query fails with:
orders
VARCHAR
customers
INTEGER
ERROR: operator does not exist: character varying = integer
Or worse—it doesn’t fail, but silently returns wrong results because '123' (string) and 123 (integer) are treated as different values.
'123'
123
This is where casting comes in.
CAST
::
NULL
0
Why this matters in production:- Broken reports: If you don’t cast, aggregations (SUM, AVG) may fail or return nonsense.- Performance hits: Implicit casting (where the database guesses types) slows down queries.- Data integrity: NULL values can skew results if not handled explicitly.
Real-world scenario:You’re building a dashboard for a retail client. The revenue column is stored as TEXT (because legacy systems exported it that way). You need to: 1. Cast it to DECIMAL to calculate totals.2. Replace NULL with 0 to avoid gaps in charts.3. Use NULLIF to prevent errors when dividing by zero (e.g., revenue / units_sold).
revenue
TEXT
DECIMAL
NULLIF
revenue / units_sold
CAST(value AS type)
WHERE id = '123'
WHERE id = CAST('123' AS INTEGER)
value::type
'123'::INTEGER
COALESCE(value1, value2, ...)
COALESCE(revenue, 0)
NULLIF(value1, value2)
value1 = value2
value1
revenue / NULLIF(units_sold, 0)
'123' + 1
124
CAST('42' AS INTEGER)
CAST('3.14' AS DECIMAL)
DATE
'2023-01-01'::DATE
TIMESTAMP
'2023-01-01 12:00'::TIMESTAMP
BOOLEAN
't'::BOOLEAN
docker run -p 5432:5432 -e POSTGRES_PASSWORD=pass postgres
CREATE TABLE sales ( id SERIAL PRIMARY KEY, product_name VARCHAR(100), revenue TEXT, -- Stored as text (legacy system) units_sold TEXT, -- Stored as text sale_date TEXT -- Stored as 'YYYY-MM-DD' ); INSERT INTO sales (product_name, revenue, units_sold, sale_date) VALUES ('Widget A', '100.50', '5', '2023-01-15'), ('Widget B', '200.00', '0', '2023-01-16'), -- units_sold = 0 (division risk) ('Widget C', NULL, '3', '2023-01-17'), -- NULL revenue ('Widget D', '50.25', NULL, '2023-01-18'); -- NULL units_sold
Cast revenue to DECIMAL and units_sold to INTEGER: sql SELECT product_name, CAST(revenue AS DECIMAL) AS revenue_decimal, units_sold::INTEGER AS units_sold_int FROM sales; Output: product_name | revenue_decimal | units_sold_int -------------+-----------------+--------------- Widget A | 100.50 | 5 Widget B | 200.00 | 0 Widget C | NULL | 3 Widget D | 50.25 | NULL
units_sold
sql SELECT product_name, CAST(revenue AS DECIMAL) AS revenue_decimal, units_sold::INTEGER AS units_sold_int FROM sales;
product_name | revenue_decimal | units_sold_int -------------+-----------------+--------------- Widget A | 100.50 | 5 Widget B | 200.00 | 0 Widget C | NULL | 3 Widget D | 50.25 | NULL
Replace NULL revenue with 0 using COALESCE: sql SELECT product_name, COALESCE(CAST(revenue AS DECIMAL), 0) AS revenue_clean FROM sales; Output: product_name | revenue_clean -------------+-------------- Widget A | 100.50 Widget B | 200.00 Widget C | 0.00 Widget D | 50.25
COALESCE
sql SELECT product_name, COALESCE(CAST(revenue AS DECIMAL), 0) AS revenue_clean FROM sales;
product_name | revenue_clean -------------+-------------- Widget A | 100.50 Widget B | 200.00 Widget C | 0.00 Widget D | 50.25
Calculate revenue per unit, avoiding division by zero with NULLIF: sql SELECT product_name, CAST(revenue AS DECIMAL) / NULLIF(units_sold::INTEGER, 0) AS revenue_per_unit FROM sales; Output: product_name | revenue_per_unit -------------+------------------ Widget A | 20.10 Widget B | NULL -- Division by zero avoided Widget C | NULL -- NULL revenue Widget D | NULL -- NULL units_sold
sql SELECT product_name, CAST(revenue AS DECIMAL) / NULLIF(units_sold::INTEGER, 0) AS revenue_per_unit FROM sales;
product_name | revenue_per_unit -------------+------------------ Widget A | 20.10 Widget B | NULL -- Division by zero avoided Widget C | NULL -- NULL revenue Widget D | NULL -- NULL units_sold
Combine all fixes in one query: sql SELECT product_name, COALESCE(CAST(revenue AS DECIMAL), 0) AS revenue_clean, COALESCE(units_sold::INTEGER, 0) AS units_sold_clean, COALESCE(CAST(revenue AS DECIMAL), 0) / NULLIF(COALESCE(units_sold::INTEGER, 0), 0) AS revenue_per_unit FROM sales; Output: product_name | revenue_clean | units_sold_clean | revenue_per_unit -------------+---------------+------------------+------------------ Widget A | 100.50 | 5 | 20.10 Widget B | 200.00 | 0 | NULL -- Still NULL (0/0) Widget C | 0.00 | 3 | 0.00 Widget D | 50.25 | 0 | NULL -- 50.25/0
sql SELECT product_name, COALESCE(CAST(revenue AS DECIMAL), 0) AS revenue_clean, COALESCE(units_sold::INTEGER, 0) AS units_sold_clean, COALESCE(CAST(revenue AS DECIMAL), 0) / NULLIF(COALESCE(units_sold::INTEGER, 0), 0) AS revenue_per_unit FROM sales;
product_name | revenue_clean | units_sold_clean | revenue_per_unit -------------+---------------+------------------+------------------ Widget A | 100.50 | 5 | 20.10 Widget B | 200.00 | 0 | NULL -- Still NULL (0/0) Widget C | 0.00 | 3 | 0.00 Widget D | 50.25 | 0 | NULL -- 50.25/0
WHERE id = CAST(user_input AS INTEGER)
TRY_CAST
CASE WHEN ... THEN ... ELSE NULL END
-- Good: Cast before filtering (if possible) SELECT * FROM sales WHERE revenue::DECIMAL > 100; `` - Avoid casting inJOIN` conditions: Pre-cast columns in a CTE or subquery.
`` - Avoid casting in
SUM(COALESCE(revenue, 0))
-- revenue::DECIMAL(10,2) for currency calculations
ERROR: invalid input syntax for type integer
'abc'
SUM(revenue)
DECIMAL(5,2)
1234.567
DECIMAL(10,3)
NULLIF('1', 1)
COALESCE(col1, col2, col3, 0)
"Which of these casts `'2023-01-01' to a DATE?
CAST('2023-01-01' AS DATE)
TO_DATE('2023-01-01')
COALESCE vs. NULLIF:
"You need to replace NULL with 0 in a column. Which function do you use?"
ISNULL
CASE WHEN
Division by zero:
units_sold = 0
revenue / (units_sold + 1)
revenue / COALESCE(units_sold, 1)
CASE WHEN units_sold = 0 THEN NULL ELSE revenue / units_sold END
COALESCE(NULL, 1, 2)
1
NULLIF(5, 5)
NULLIF(5, 6)
5
'3.99'::INTEGER
3
4
Challenge:You have a table employees with a salary column stored as TEXT. Some values are 'N/A' (not a number). Write a query to: 1. Cast salary to DECIMAL.2. Replace 'N/A' with NULL.3. Calculate the average salary, ignoring NULL values.
employees
salary
'N/A'
Solution:
SELECT AVG( CASE WHEN salary = 'N/A' THEN NULL ELSE CAST(salary AS DECIMAL) END ) AS avg_salary FROM employees;
Why it works:- CASE converts 'N/A' to NULL before casting.- AVG ignores NULL values by default.
CASE
AVG
CAST(col AS INTEGER)
col::INTEGER
3.9
CAST(col AS DECIMAL(10,2))
(10,2)
YYYY-MM-DD
COALESCE(col, 0)
col1 / NULLIF(col2, 0)
col2 = 0
NULLIF(col, 'N/A')
TRY_CAST(col AS INTEGER)
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.