CAST converts an expression to a specified type; CONVERT provides database-specific conversion features whose syntax and meaning vary.
Imported values often arrive as text even when they represent numbers or dates. Conversion makes the intended type explicit, but it cannot guarantee that malformed input is valid. Treat validation and type conversion as related but separate tasks.
This reference adds detail to the main course. You can read it independently: the small database below supplies every table and row used in the examples. Start with the question each query answers, then compare the returned values with the data rather than memorising a line of syntax.
Set up the practice database
Run this setup once in a new practice database, before the examples. It uses four customers and six sales. Ana has two sales, Ben has one, Cara has two, and Dev has none.
Sale 106 has no customer link; sale 104 has an unknown amount. These deliberate test cases expose missing information and unmatched relationships.
CREATE TABLE customers (
id INTEGER PRIMARY KEY,
name VARCHAR(40) NOT NULL,
city VARCHAR(40),
manager_id INTEGER
);
CREATE TABLE sales (
id INTEGER PRIMARY KEY,
customer_id INTEGER,
amount DECIMAL(10,2),
status VARCHAR(20) NOT NULL,
created_on DATE NOT NULL
);
INSERT INTO customers (id,name,city,manager_id) VALUES
(1,'Ana','Leeds',NULL),(2,'Ben','Leeds',1),
(3,'Cara','Porto',1),(4,'Dev',NULL,2);
INSERT INTO sales (id,customer_id,amount,status,created_on) VALUES
(101,1,10,'paid','2026-01-01'),
(102,1,30,'pending','2026-01-02'),
(103,2,20,'paid','2026-01-02'),
(104,3,NULL,'pending','2026-02-01'),
(105,3,20,'paid','2026-02-02'),
(106,NULL,5,'paid','2026-02-03');An amount of zero would be a known value. The NULL amount here means the value is unknown. A customer with no matching sale differs from a sale whose customer_id is NULL.
The primary keys identify individual records even when amounts or cities repeat. Dates use year-month-day format. The examples specify sorting whenever order matters; insertion order alone does not guarantee display order.
How CAST() and CONVERT() works
CAST(expression AS target_type) is the shared standard-style form. Casting amount to DECIMAL(12,2) states a precision and scale requirement in server databases. Casting to a character type creates text for display or export rather than a numeric measure. The type controls later operations: sorting text '100' and '20' is different from sorting numeric one hundred and twenty. Convert to the intended type before applying the arithmetic or ordering rule that relies on it.
Precision is the total permitted number of decimal digits, while scale describes digits after the decimal point for common DECIMAL definitions. A narrower target can round, truncate or reject a value according to engine rules and context. Converting a large identifier to a small integer type can overflow. Choose a target that reflects the application range rather than merely fitting the handful of values in a sample table.
Implicit conversions and their risks
Implicit conversion occurs when the engine reconciles mixed types automatically. It can make a query appear convenient but conceal errors or prevent efficient index access if the column is converted for every comparison. Match parameter types to their target columns and use explicit conversion where the intended result is otherwise unclear. Conversion of empty text, malformed numeric text or regional dates is not portable; one engine can fail while another returns a coerced value.
SQL Server CONVERT(type,expression,style) includes date and other formatting styles. MySQL CONVERT(expression,type) has a different argument order and also supports a character-set form. PostgreSQL does not offer the same general CONVERT signature, and SQLite relies on CAST with affinity-based behaviour. SQL Server TRY_CAST and TRY_CONVERT return NULL for many failed permitted conversions, but they are not universal functions. A missing converted value may mean invalid input, original NULL, or an intentional fallback, so retain the raw field and an error flag during import validation.
MySQL, PostgreSQL, SQL Server and SQLite
CAST is available in all four systems, but supported type names and failed-conversion rules differ. SQLite CAST uses its conversion and affinity rules and does not enforce fixed decimal precision in DECIMAL(12,2). SQL Server CONVERT has style codes; MySQL CONVERT has distinct type or charset forms. Do not present CONVERT as one portable function.
Check the engine-specific syntax and version requirements in SQL Server CAST and CONVERT.
Practice task and worked solution
Calculate a fractional amount divided by four using an explicit decimal cast. Return only sale 106.
Try the task before reading its worked solution. The supplied rows make the expected answer checkable by hand.
SELECT id,CAST(amount AS DECIMAL(12,2))/4.0 AS quarter
FROM sales WHERE id=106;id | quarter
106 | 1.25The amount five is converted to the declared numeric target, and the decimal denominator preserves the fractional intent. The resulting value is 1.25. This example separates conversion from final display; it does not update the table or guarantee a particular number of printed trailing zeros.
On a disposable expression, compare conversion of '12' with conversion of 'not-a-number' in the engine you use. Record whether the second fails or coerces, rather than copying another dialect’s result. Test a fractional value against both an integer and a decimal target to see information loss. Keep SQL Server TRY_CONVERT experiments explicitly labelled as T-SQL.
SQL CAST and CONVERT: Types, Precision and Safe Conversion Syntax
CAST() and CONVERT()
SELECT id,CAST(amount AS DECIMAL(12,2)) AS numeric_amount
FROM sales WHERE amount IS NOT NULL ORDER BY id;SQL CAST and CONVERT: Types, Precision and Safe Conversion Summary
CAST(expression AS type)is the standard way to convert a value;CONVERTis a dialect-specific alternative.- The target type controls later behaviour: casting to text changes sorting and arithmetic.
- Failed conversions differ: PostgreSQL raises an error for
'abc'as an integer, while SQLite returns 0. - Implicit conversion can hide bad data and stop an index being used; match types deliberately.
- Stage raw imported text, validate it and convert only approved rows into typed columns.
SQL CAST and CONVERT: Types, Precision and Safe Conversion Examples
Each example shows the code, the output it produces and what each part does.
Converting amounts to a decimal type
The conversion expresses the numeric target without changing stored records. A client may show 10 rather than 10.00 depending on display formatting. The selected values are compatible with the target range; the example does not demonstrate how malformed text would be handled.
SELECT id,CAST(amount AS DECIMAL(12,2)) AS numeric_amount
FROM sales WHERE amount IS NOT NULL ORDER BY id;id | numeric_amount
101 | 10.00
102 | 30.00
103 | 20.00
105 | 20.00
106 | 5.00Common SQL CAST and CONVERT: Types, Precision and Safe Conversion Mistakes
Assuming a failed cast always raises an error
Assuming CAST('not-a-number' AS INTEGER) always raises an error is unsafe: SQLite can produce zero while PostgreSQL rejects that input. Validate raw imported values using the chosen engine’s documented rules. A zero produced by coercion must not be mistaken for a legitimate saved zero.
SQL CAST and CONVERT: Types, Precision and Safe Conversion in Real Projects
Staging and validating a CSV import
A CSV import can stage raw text, validate fields, and convert only approved rows into typed production columns. Preserve the source string and rejection reason for review. This gives an operator evidence to correct the input instead of silently turning malformed amounts into plausible numbers.
Maintain a raw-text staging area when source validity is uncertain. A converted zero, an original zero and a rejected string are different states that an import must not collapse accidentally. Match parameter types to indexed columns so a convenience conversion does not force a costly per-row transformation or obscure the intended comparison.
SQL CAST and CONVERT: Types, Precision and Safe Conversion FAQ
Is CAST validation?
No. It performs a conversion, and its failure behaviour differs: some databases raise errors, others return 0 or NULL. Use an explicit validation step, such as a pattern check or TRY_CAST where available, when invalid input must be detected and reported.
Is CONVERT portable?
No. Its syntax and capabilities differ: SQL Server's CONVERT(type, value, style) adds date and number style codes, while MySQL's CONVERT(value, type) and CONVERT(value USING charset) work differently, and PostgreSQL uses CONVERT only for character sets. Use CAST for portable queries.
Does SQLite DECIMAL enforce two fractional digits?
No. Its type-affinity system does not provide server-style fixed decimal enforcement merely from a DECIMAL(12,2) declaration; values are stored as integers or floating-point numbers. Round explicitly, or store money as whole cents, when exact decimals matter in SQLite.
Is there a safe cast that returns NULL instead of an error?
SQL Server has TRY_CAST and TRY_CONVERT, which return NULL when a conversion fails. PostgreSQL and MySQL have no built-in equivalent; validate first with a pattern, such as PostgreSQL's value ~ '^-?[0-9]+$', and cast only the rows that pass.
What does the :: syntax mean in PostgreSQL?
value::integer is PostgreSQL's shorthand for CAST(value AS integer). It's convenient and common in PostgreSQL code, but other databases don't understand it, so use CAST in queries that must run elsewhere.
SQL CAST and CONVERT: Types, Precision and Safe Conversion Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
What value is returned by the explicit decimal quarter calculation for sale 106?
SQL CAST and CONVERT: Types, Precision and Safe Conversion Quiz
2 questions to check what you learned.
Which conversion syntax is standard-style?
- CAST(expression AS target_type)
- CONVERT(type,expression,style), which is identical in every dialect
- CAST(target_type,expression), with a comma-separated argument order
Why retain raw values during an import?
- To guarantee every malformed string becomes a valid zero
- To distinguish invalid source text from genuine converted values or missing input
- To make source text unnecessary even when conversion discards information