Diferença entre numérico, flutuante e decimal no SQL Server

322

Quais são as diferenças entre numeric, floate decimaltipos de dados e que devem ser utilizados em que situações?

Para qualquer tipo de transação financeira (por exemplo, campo salarial), qual é a preferida e por quê?

priyanka.sarkar
fonte
1
O link decimal e numérico acima precisa ser atualizado para docs.microsoft.com/en-us/sql/t-sql/data-types/… . O link acima não existe mais.
Nigel Ainscoe
1
Geralmente, ao lidar com assuntos financeiros, é interessante trabalhar com tipos Inteiros , além dos de ponto flutuante , e armazenar os valores em centavos , em vez de dólares , por exemplo.
Pedro

Respostas:

494

use os tipos de dados flutuantes ou reais apenas se a precisão fornecida por decimal (até 38 dígitos) for insuficiente

  • Os tipos de dados numéricos aproximados não armazenam os valores exatos especificados para muitos números; eles armazenam uma aproximação extremamente próxima do valor. ( Technet )

  • Evite usar colunas flutuantes ou reais nas condições de pesquisa da cláusula WHERE, especialmente os operadores = e <> ( Technet )

geralmente porque a precisão fornecida pelo decimal é de [10E38 ~ 38 dígitos] se o seu número puder caber nele, e um espaço de armazenamento menor (e talvez a velocidade) do Float não é importante e lidar com comportamentos anormais e problemas de tipos numéricos aproximados não são importantes. aceitável, use decimal geralmente .

informação mais útil

  • numérico = decimal (5 a 17 bytes) ( tipo de dados numérico exato )
    • será mapeado para Decimal no .NET
    • ambos têm (18, 0) parâmetros padrão (precisão, escala) no SQL server
    • scale = número máximo de dígitos decimais que podem ser armazenados à direita do ponto decimal.
    • observe que money (8 bytes) e smallmoney (4 bytes) também são exatos e são mapeados para o Decimal In .NET e têm 4 pontos decimais ( MSDN )
    • decimal e numérico (Transact-SQL) - MSDN
  • real (4 bytes) ( tipo de dados numérico aproximado )
  • float (8 bytes) ( tipo de dados numérico aproximado )
    • será mapeado para o dobro no .NET
  • Todos os tipos numéricos exatos sempre produzem o mesmo resultado, independentemente do tipo de arquitetura do processador que está sendo usado ou da magnitude dos números
  • O parâmetro fornecido para o tipo de dados flutuante define o número de bits que são usados ​​para armazenar a mantissa do número do ponto flutuante .
  • O tipo de dados numérico aproximado geralmente usa menos armazenamento e tem melhor velocidade (até 20x) e você também deve considerar quando eles foram convertidos no .NET

Tipos de dados numéricos exatos Tipos de dados numéricos aproximados

fonte principal : Kit de treinamento individual do MCTS (Exame 70-433): Desenvolvimento de banco de dados Microsoft® SQL Server® 2008 - Capítulo 3 - Tabelas, tipos de dados e integridade declarativa dos dados Lição 1 - Escolhendo tipos de dados (diretrizes) - Página 93

Iman
fonte
17
use the float or real data types only if the precision provided by decimal is insufficient- Eu pensei que real é MENOS exato e decimal, então como você escreve para usar real se decimal é insuficiente?
fácil
7
real é menos preciso, portanto, não é recomendado a menos armazenar grandes números maiores que decimais (> 10e38) é necessário ou espaço considerações .i acho que a precisão aqui nos meios cotação valores possíveis e magnitude não a precisão
Iman
12
@BornToCode A "precisão" aqui refere-se à amplitude dos valores que você deseja armazenar. se você precisar armazenar valores entre 1e10 e 1e-10, tudo decimalficará bem. É uma precisão de 20. Se você precisar armazenar valores entre, digamos, 1e20 e 1e-20, bem, decimal não pode fazer isso. São 40 dígitos de precisão. Você nunca pode armazenar 1e20 e 1e-20 no mesmo decimalcampo. Em vez disso, você pode usar float, que armazena internamente tudo como um log da base 2. Isso permite uma gama completa de precisão em um campo com a desvantagem de que apenas os primeiros ~ 8 dígitos serão precisos.
Bacon Bits
Terceiro, os comentários de BornToCode e Iman. Acabei de experimentar (usando o SQL Server 2012) e parece que a máquina epsilon para float (53), o tipo de ponto flutuante de maior precisão, é 2.22044604925031E-16. Então você obteria cerca de 15 números significativos. Por outro lado, posso obter 38 números significativos fora do decimal.
Stewart
"Use o float..." - disse quem? É uma citação ou sua opinião?
User443854 17/04/19
24

Diretrizes do MSDN: usando dados decimais, flutuantes e reais

A precisão máxima padrão dos tipos de dados numéricos e decimais é 38. No Transact-SQL, numérico é funcionalmente equivalente ao tipo de dados decimal. Use o tipo de dados decimal para armazenar números com decimais quando os valores dos dados devem ser armazenados exatamente como especificado.

O comportamento de float e real segue a especificação IEEE 754 em tipos de dados numéricos aproximados. Devido à natureza aproximada dos tipos de dados flutuantes e reais, não use esses tipos de dados quando for necessário um comportamento numérico exato, como em aplicativos financeiros, em operações envolvendo arredondamento ou em verificações de igualdade. Em vez disso, use os tipos de dados inteiro, decimal, dinheiro ou dinheiro pequeno. Evite usar colunas flutuantes ou reais nas condições de pesquisa da cláusula WHERE, especialmente os operadores = e <>. É melhor limitar as colunas flutuantes e reais a> ou <comparações.

kmote
fonte
O número (fixo) de casas decimais é especificado na Scalecoluna.
Cees Timmerman
1
Se você deseja 'exatamente como especificado', então, do ponto de vista dos padrões, há algumas vantagens, numericpois ele nunca será armazenado com mais precisão do que o solicitado: consulte stackoverflow.com/a/759606/626804
Ed Avis,
13

Não é uma resposta completa, mas um link útil:

"Eu frequentemente faço cálculos com valores decimais. Em alguns casos, converter valores decimais para flutuar o mais rápido possível, antes de qualquer cálculo, produz uma precisão melhor."

http://sqlblog.com/blogs/alexander_kuznetsov/archive/2008/12/20/for-better-precision-cast-decimals-before-calculations.aspx

AK
fonte
2
Isso não faz sentido. Todas as outras respostas, com fontes, dizem que os tipos de dados numéricos ou decimais são precisos, e os tipos float ou reais são uma aproximação muito próxima. Devido à menor precisão, entendo que a conversão para flutuação pode permitir cálculos mais rápidos, mas não maior precisão.
Cbaldan
3
Todos os tipos de dados numéricos podem sofrer estouro e estouro. O estouro é um erro explícito; no entanto, o estouro é silencioso. As características do underflow para decimale floatsão diferentes . O decimal preserva contra o subfluxo, tanto quanto possível, aumentando a precisão ou a escala. No entanto, uma vez que você atinge o limite de dígitos significativos em decimal, os fluxos insuficientes são silenciosos (e a precisão é perdida). O flutuador tem uma gama maior de escalas possível e são as limitações de escala que realmente são a causa do subfluxo. Assim, o flutuador pode ter uma escala melhor. No entanto, ainda é um tipo inexato .
ErikE
13

Eles diferem na precedência do tipo de dados

Decimal e Numérico são os mesmos funcionalmente, mas ainda há precedência de tipo de dados , o que pode ser crucial em alguns casos.

SELECT SQL_VARIANT_PROPERTY(CAST(1 AS NUMERIC) + CAST(1 AS DECIMAL),'basetype')

O tipo de dados resultante é numérico porque tem precedência no tipo de dados .

Lista exaustiva de tipos de dados por precedência:

Link de referência

Stephan
fonte
7

Decimal tem uma precisão fixa, enquanto float tem precisão variável.

EDIT (falha ao ler a pergunta inteira): Float (53) (também conhecido como real) é um número de ponto flutuante de precisão dupla (32 bits) no SQL Server. Flutuação regular é um número de ponto flutuante de precisão única. Double é uma boa combinação de precisão e simplicidade para muitos cálculos. Você pode criar um número de precisão muito alto com decimal - até 136 bits - mas também deve ter cuidado para definir sua precisão e escala corretamente, para que ele possa conter todos os seus cálculos intermediários para o número necessário de dígitos.

Brian Reiter
fonte
Você não especificou qual é preferível enquanto o caso é para transações financeiras e por quê?
priyanka.sarkar
Para o SQL Server 2008 e superior, float (53) aka float é um número de ponto flutuante de precisão dupla (64 bits), enquanto float (24) aka real é um número de ponto flutuante de precisão única (32 bits). docs.microsoft.com/pt-br/sql/t-sql/data-types/float-and-real-transact-sql
M Kloster
4

Flutuar é o tipo de dados de número aproximado, o que significa que nem todos os valores no intervalo de tipos de dados podem ser representados exatamente.

Decimal / Numérico é o tipo de dados de precisão fixa, o que significa que todos os valores no intervalo de tipos de dados podem ser representados exatamente com precisão e escala. Você pode usar decimal para economizar dinheiro.

Converter de decimal ou numérico em flutuante pode causar alguma perda de precisão. Para os tipos de dados decimais ou numéricos, o SQL Server considera cada combinação específica de precisão e escala como um tipo de dados diferente. DECIMAL (2,2) e DECIMAL (2,4) são diferentes tipos de dados. Isso significa que 11.22 e 11.2222 são tipos diferentes, embora esse não seja o caso para flutuar. Para FLOAT (6), 11.22 e 11.2222 são os mesmos tipos de dados.

Você também pode usar o tipo de dados monetários para economizar dinheiro. Este é um tipo de dados nativo com precisão de 4 dígitos por dinheiro. A maioria dos especialistas prefere esse tipo de dados para economizar dinheiro.

Referência 1 2 3

Somnath Muluk
fonte
3

O caso de Decimal

Qual é a necessidade subjacente?

Surge do fato de que, em última análise, os computadores representam internamente números em formato binário. Isso leva, inevitavelmente, a erros de arredondamento.

Considere isto:

0.1 (decimal, or "base 10") = .00011001100110011... (binary, or "base 2")

As reticências acima [...] significam "infinito". Se você olhar com cuidado, há um padrão de repetição infinito (= '0011')

Então, em algum momento, o computador precisa arredondar esse valor. Isso leva a erros de acumulação decorrentes do uso repetido de números que são inexatamente armazenados.

Diga que deseja armazenar valores financeiros (que são números que podem ter uma parte fracionária). Antes de tudo, você não pode usar números inteiros obviamente (os números inteiros não têm uma parte fracionária). Do ponto de vista puramente matemático, a tendência natural seria usar a float. Mas, em um computador, os carros alegóricos têm a parte de um número localizado após um ponto decimal - a "mantissa" - limitada. Isso leva a erros de arredondamento.

Para superar isso, os computadores oferecem tipos de dados específicos que limitam o erro de arredondamento binário nos computadores para números decimais. Esses são os tipos de dados que devem ser absolutamente utilizados para representar valores financeiros. Esses tipos de dados geralmente recebem o nome de Decimal. Esse é o caso em C #, por exemplo. Ou, DECIMALna maioria dos bancos de dados.

Varus Septimus
fonte
1

Embora a pergunta não inclua o tipo de dados MONEY, algumas pessoas que se deparam com esse encadeamento podem ficar tentadas a usar o tipo de dados MONEY para cálculos financeiros.

Desconfie do tipo de dados MONEY, é de precisão limitada.

Há muitas informações boas sobre isso nas respostas a esta pergunta do Stackoverflow:

Você deve escolher os tipos de dados DINHEIRO ou DECIMAL (x, y) no SQL Server?

Simon Tewsi
fonte