Abaixo está uma lista contendo os tipos de dados do SQL Server, em ordem de precedência.
- tipos de dados definidos pelo usuário (mais altos)
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
(incluindonvarchar(max)
)nchar
varchar
(incluindovarchar(max)
)char
varbinary
(incluindovarbinary(max)
)binary
(mais baixo)
Quando você usa um operador para combinar operandos de diferentes tipos de dados, o tipo de dados com menor precedência é primeiro convertido no tipo de dados com maior precedência.
Se a conversão não for uma conversão implícita com suporte, um erro será retornado.
Se ambos os operandos forem do mesmo tipo, nenhuma conversão será feita (ou necessária) e o resultado da operação usará o tipo de dados dos operandos.
Exemplo
Aqui está um exemplo de uma conversão implícita bem-sucedida:
SELECT 1 * 1.00;
Resultado:
1.00
Aqui, o operando esquerdo foi convertido para o tipo de dados do operando direito.
Aqui está uma maneira mais explícita de fazer isso:
DECLARE
@n1 INT,
@n2 DECIMAL(5, 2);
SET @n1 = 1;
SET @n2 = 1;
SELECT @n1 * @n2;
Resultado:
1.00
Neste caso eu declarei explicitamente o operando esquerdo como um
INT
e o operando direito como DECIMAL(5, 2)
. Podemos examinar melhor os resultados com o
sys.dm_exec_describe_first_result_set
função de gerenciamento dinâmico do sistema. Esta função nos permite verificar o tipo de dados de cada coluna retornada em uma consulta:
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);
Resultado:
+--------------------+--------------+-------------+---------+ | system_type_name | max_length | precision | scale | |--------------------+--------------+-------------+---------| | int | 4 | 10 | 0 | | decimal(5,2) | 5 | 5 | 2 | | decimal(16,2) | 9 | 16 | 2 | +--------------------+--------------+-------------+---------+
Aqui, podemos ver que cada linha representa cada coluna retornada pela consulta. Portanto, a primeira coluna era um
INT
, a segunda coluna era DECIMAL(5,2)
, e a terceira coluna um DECIMAL(16,2)
. Então o SQL Server realmente retornou um
DECIMAL(16,2)
, mesmo que o valor decimal original fosse um DECIMAL(5,2)
. Exemplo de um erro de conversão
Conforme mencionado, se a conversão não for uma conversão implícita com suporte, um erro será retornado:
SELECT 'Age: ' + 10;
Resultado:
Msg 245, Level 16, State 1, Line 1 Conversion failed when converting the varchar value 'Age: ' to data type int.
Neste caso, eu estava tentando concatenar uma string (
VARCHAR
) e um número (INT
). Vendo como INT
tem uma precedência maior que VARCHAR
, o SQL Server tentou converter implicitamente a string em um INT
. Isso falhou porque essa string não pode ser convertida em um número inteiro.
Para superar isso, podemos primeiro converter o
INT
para VARCHAR
:SELECT 'Age: ' + CAST(10 AS VARCHAR(2));
Resultado:
Age: 10
Agora, ambos os operandos têm o mesmo tipo de dados e, portanto, o SQL Server executa a operação com êxito sem a necessidade de realizar conversões implícitas.
Outra maneira de fazer esta operação em particular é com o
CONCAT()
função:SELECT CONCAT('Age: ', 10);
Resultado:
Age: 10
O
CONCAT()
function é uma função de string e, portanto, converte implicitamente todos os argumentos em tipos de string antes da concatenação. Portanto, não havia necessidade de realizarmos uma conversão explícita. No entanto, se o operando string puder ser convertido implicitamente em um número, ele não causará um erro ao usar o
+
operador:SELECT '10' + 10;
Resultado:
20
Mas neste caso, o
+
O operador se transforma em um operador matemático de adição, em vez de um operador de concatenação de string.