Below is a list containing the SQL Server data types, in order of precedence.
- user-defined data types (highest)
sql_variant
xml
datetimeoffset
datetime2
datetime
smalldatetime
date
time
float
real
decimal
money
smallmoney
bigint
int
smallint
tinyint
bit
ntext
text
image
timestamp
uniqueidentifier
nvarchar
(includingnvarchar(max)
)nchar
varchar
(includingvarchar(max)
)char
varbinary
(includingvarbinary(max)
)binary
(lowest)
Source: Microsoft
When you use an operator to combine operands of different data types, the data type with the lower precedence is first converted to the data type with the higher precedence.
If the conversion isn’t a supported implicit conversion, an error is returned.
If both operands are of the same type, then no conversion is done (or needed) and the result of the operation uses the data type of the operands.
Example
Here’s an example of an implicit conversion that succeeds:
SELECT 1 * 1.00;
Result:
1.00
Here, the left operand was converted to the data type of the right operand.
Here’s a more explicit way of doing it:
DECLARE
@n1 INT,
@n2 DECIMAL(5, 2);
SET @n1 = 1;
SET @n2 = 1;
SELECT @n1 * @n2;
Result:
1.00
In this case I explicitly declared the left operand as an INT
and the right operand as DECIMAL(5, 2)
.
We can further examine the results with the sys.dm_exec_describe_first_result_set
system dynamic management function.
This function enables us to check the data type of each column returned in a query:
SELECT
system_type_name,
max_length,
[precision],
scale
FROM sys.dm_exec_describe_first_result_set(
'DECLARE @n1 INT, @n2 DECIMAL(5, 2);
SET @n1 = 1;
SET @n2 = 1;
SELECT @n1, @n2, @n1 * @n2;',
null,
0);
Result:
+--------------------+--------------+-------------+---------+ | system_type_name | max_length | precision | scale | |--------------------+--------------+-------------+---------| | int | 4 | 10 | 0 | | decimal(5,2) | 5 | 5 | 2 | | decimal(16,2) | 9 | 16 | 2 | +--------------------+--------------+-------------+---------+
Here, we can see that each row represents each column returned by the query. Therefore, the first column was an INT
, the second column was DECIMAL(5,2)
, and the third column a DECIMAL(16,2)
.
So SQL Server actually returned a DECIMAL(16,2)
, even though the original decimal value was a DECIMAL(5,2)
.
Example of a Conversion Error
As mentioned, if the conversion isn’t a supported implicit conversion, an error is returned:
SELECT 'Age: ' + 10;
Result:
Msg 245, Level 16, State 1, Line 1 Conversion failed when converting the varchar value 'Age: ' to data type int.
In this case, I was trying to concatenate a string (VARCHAR
) and a number (INT
). Seeing as INT
has a higher precedence than VARCHAR
, SQL Server tried to implicitly convert the string to an INT
.
This failed, because this string cannot be converted to an integer.
To overcome this, we can first convert the INT
to VARCHAR
:
SELECT 'Age: ' + CAST(10 AS VARCHAR(2));
Result:
Age: 10
Now both operands have the same data type, and so SQL Server performs the operation successfully without the need to perform any implicit conversions.
Another way of doing this particular operation is with the CONCAT()
function:
SELECT CONCAT('Age: ', 10);
Result:
Age: 10
The CONCAT()
function is a string function and therefore implicitly converts all arguments to string types before concatenation. Therefore, there was no need for us to perform an explicit conversion.
However, if the string operand can be implicitly converted to a number, then it won’t cause an error when using the +
operator:
SELECT '10' + 10;
Result:
20
But in this case, the +
operator turns into an addition mathematical operator, rather than a string concatenation operator.