Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Precedência de tipo de dados no SQL Server


Abaixo está uma lista contendo os tipos de dados do SQL Server, em ordem de precedência.
  1. tipos de dados definidos pelo usuário (mais altos)
  2. sql_variant
  3. xml
  4. datetimeoffset
  5. datetime2
  6. datetime
  7. smalldatetime
  8. date
  9. time
  10. float
  11. real
  12. decimal
  13. money
  14. smallmoney
  15. bigint
  16. int
  17. smallint
  18. tinyint
  19. bit
  20. ntext
  21. text
  22. image
  23. timestamp
  24. uniqueidentifier
  25. nvarchar (incluindo nvarchar(max) )
  26. nchar
  27. varchar (incluindo varchar(max) )
  28. char
  29. varbinary (incluindo varbinary(max) )
  30. 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.