Converting types: CAST, CONVERT and TRY_CAST
When SQL Server converts for you and when you must ask, the rules of data type precedence, date styles with CONVERT, safe conversion with TRY_CAST, and the traps in empty strings and imported text.
Data type precedence
+ between text and an int is addition, not joining:
SELECT '10' + 5 AS TextPlusInt, '10' + '5' AS TextPlusText, CONCAT('10', 5) AS Joined, 10 + 2.5 AS IntPlusDecimal;TextPlusInt TextPlusText Joined IntPlusDecimal
----------- ------------ ------ --------------
15 105 105 12.5| Higher precedence wins | Examples |
|---|---|
datetimeoffset > datetime2 > datetime > date | |
float > real | |
decimal > money > bigint > int > smallint > tinyint > bit | |
nvarchar > nchar > varchar > char |
'abc' + 5 fails: SQL Server tries to turn 'abc' into an int. And comparing a varchar column with an int value converts the column, row by row, which is both slow and a source of conversion errors.
CAST and CONVERT
CAST(x AS type) is standard SQL. CONVERT(type, x [, style]) is T-SQL’s version, with an optional style number that controls how dates and numbers are written as text or read from it:
SELECT CAST('42' AS int) AS CastText, CAST(18.5 AS varchar(10)) AS NumberAsText, CONVERT(varchar(10), CAST('2024-12-31' AS date), 103) AS Style103, CONVERT(varchar(8), CAST('2024-12-31' AS date), 112) AS Style112, CONVERT(date, '31/12/2024', 103) AS ReadBritish;CastText NumberAsText Style103 Style112 ReadBritish
-------- ------------ ---------- -------- -----------
42 18.5 31/12/2024 20241231 2024-12-31| Style | Format | Example |
|---|---|---|
TRY_CAST: convert or give NULL
TRY_CAST and TRY_CONVERT return NULL instead, which makes them ideal for checking imported data. Explore which texts convert to which types:
CREATE TABLE #Import (RowNo int, PriceText varchar(20), DateText varchar(20));INSERT INTO #Import (RowNo, PriceText, DateText) VALUES (1, '12.50', '2024-07-01'), (2, ' 7', '2024-07-02'), (3, 'n/a', '2024-07-03'), (4, '9.99', '2024-07-32'), (5, '', ''); SELECT RowNo, PriceText, DateText, TRY_CAST(PriceText AS decimal(10,2)) AS Price, TRY_CAST(DateText AS date) AS TheDateFROM #ImportWHERE TRY_CAST(PriceText AS decimal(10,2)) IS NULL OR TRY_CAST(DateText AS date) IS NULL;RowNo PriceText DateText Price TheDate
----- --------- ---------- ----- ----------
3 n/a 2024-07-03 NULL 2024-07-03
4 9.99 2024-07-32 9.99 NULL
5 NULL 1900-01-01The empty-string trap
SELECT CAST('' AS int) AS EmptyAsInt, CAST('' AS date) AS EmptyAsDate, TRY_CAST(NULLIF(TRIM(''), '') AS date) AS Safe;EmptyAsInt EmptyAsDate Safe
---------- ----------- ----
0 1900-01-01 NULLNULLIF(TRIM(x), '') turns blanks (and all-space values) into NULL first, so they stay unknown instead of becoming 0 or 1900-01-01.
FORMAT for display
FORMAT(value, pattern, culture) uses .NET format strings, with a culture for currency symbols and separators. Use it for display only:
SELECT Name, FORMAT(Price, 'C', 'en-GB') AS UkPrice, FORMAT(Price, 'C', 'de-DE') AS GermanPrice, FORMAT(Stock, 'N0') AS StockWithSeparatorsFROM dbo.ProductsWHERE ProductId IN (2, 6);Name UkPrice GermanPrice StockWithSeparators ---------------- ------- ----------- ------------------- Cordless drill £89.00 89,00 € 12 Timber 2x4 2.4 m £6.80 6,80 € 500
decimal(10,2): blanks and all-space values should become NULL, and so should anything that is not a number. Use the values '12.50', ' 7', 'n/a', '' and ' '.
Show a hint
Show the solution
SELECT PriceText, TRY_CAST(NULLIF(TRIM(PriceText), '') AS decimal(10,2)) AS PriceFROM (VALUES ('12.50'), (' 7'), ('n/a'), (''), (' ')) AS v(PriceText);PriceText Price
--------- -----
12.50 12.50
7 7.00
n/a NULL
NULL
NULLRemember
Mixed types are converted towards the higher precedence type: numbers beat text, so '10' + 5 = 15. CAST is standard; CONVERT adds style numbers for dates (103 British, 112 yyyymmdd, 23 ISO). TRY_CAST / TRY_CONVERT return NULL instead of failing: use them to find bad imported rows. Empty strings become 0 or 1900-01-01: wrap with NULLIF(TRIM(x), '') first. FORMAT is for display only, and slow; keep values in their real types for storage and maths.