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


442

Estou curioso para saber se existe ou não uma diferença real entre o moneytipo de dados e algo como decimal(19,4)(que é o que o dinheiro usa internamente, acredito).

Estou ciente de que moneyé específico para o SQL Server. Quero saber se há um motivo convincente para escolher um sobre o outro; a maioria das amostras do SQL Server (por exemplo, o banco de dados AdventureWorks) usa moneye não decimalpara informações como preço.

Devo apenas continuar usando o tipo de dados money ou há um benefício em usar decimal? O dinheiro tem menos caracteres para digitar, mas esse não é um motivo válido :)


12
DECIMAL(19, 4) é uma escolha popular. verifique isso também verifique aqui Formatos de Moeda Mundial para decidir quantas casas decimais usar, a esperança ajuda.
shaijut

Gostaria de saber por que o tipo de dado monetário tem 4 casas decimais ... e não 2, ou seja, 100 centavos de dólar por dólar, sendo necessárias apenas 2 casas decimais? Para armazenar um registro de quantias em dinheiro inferiores a US $ 9999,99, eu usaria um tipo de dados decimal (6,2). Eu não estou preocupado com a divisão ou cálculos se multiplicam, apenas armazenar e somatório ..
Allan F

Respostas:


326

Nunca você deve usar dinheiro. Não é preciso e é puro lixo; sempre use decimal / numérico.

Execute isso para ver o que quero dizer:

DECLARE
    @mon1 MONEY,
    @mon2 MONEY,
    @mon3 MONEY,
    @mon4 MONEY,
    @num1 DECIMAL(19,4),
    @num2 DECIMAL(19,4),
    @num3 DECIMAL(19,4),
    @num4 DECIMAL(19,4)

    SELECT
    @mon1 = 100, @mon2 = 339, @mon3 = 10000,
    @num1 = 100, @num2 = 339, @num3 = 10000

    SET @mon4 = @mon1/@mon2*@mon3
    SET @num4 = @num1/@num2*@num3

    SELECT @mon4 AS moneyresult,
    @num4 AS numericresult

Saída: 2949.0000 2949.8525

Para algumas das pessoas que disseram que você não divide dinheiro por dinheiro:

Aqui está uma das minhas consultas para calcular correlações, e mudar isso para dinheiro gera resultados incorretos.

select t1.index_id,t2.index_id,(avg(t1.monret*t2.monret)
    -(avg(t1.monret) * avg(t2.monret)))
            /((sqrt(avg(square(t1.monret)) - square(avg(t1.monret))))
            *(sqrt(avg(square(t2.monret)) - square(avg(t2.monret))))),
current_timestamp,@MaxDate
            from Table1 t1  join Table1 t2  on t1.Date = traDate
            group by t1.index_id,t2.index_id

61
"Nunca" é uma palavra forte. "Dinheiro" é útil para transmitir resultados para esse tipo para exibição ao usuário de uma maneira sensível à cultura, mas você está certo de que é muito ruim usar os próprios cálculos.
Joel Coehoorn

36
Seu exemplo não é significativo, pois ninguém jamais multiplicará dois objetos do tipo dinheiro. Se você quiser provar seu ponto, precisa comparar a multiplicação de um dinheiro por um decimal com a multiplicação de um decimal por um decimal.
Brian

27
.. mas ainda é intrigante o motivo pelo qual dinheiro * dinheiro não teria a precisão do dinheiro.
Aprendendo

4
@ Learning: ele tem uma precisão de dinheiro. No entanto, você ainda acaba com erros de arredondamento que podem se acumular ao longo do tempo. O tipo decimal não usa aritmética binária: garante que obtém os mesmos resultados da base 10 que você obteria no papel.
Joel Coehoorn

55
Multiplicação e divisão do moneyexcesso money, essa 'ilustração' é manipuladora. É um fato documentado que moneypossui uma precisão fixa e muito limitada. Nesses casos, deve-se primeiro multiplicar e depois dividir. Altere a ordem dos operadores neste exemplo e você obterá resultados idênticos. Um moneyessencialmente é um int de 64 bits e, se você lidasse com ints, multiplicaria antes de dividir.
227 Andriy M

272

O SQLMenace disse que o dinheiro é inexato. Mas você não multiplica / divide dinheiro por dinheiro! Quanto é 3 dólares vezes 50 centavos? 150 dollarcents? Você multiplica / divide dinheiro por escalares, que devem ser decimais.

DECLARE
@mon1 MONEY,
@mon4 MONEY,
@num1 DECIMAL(19,4),
@num2 DECIMAL(19,4),
@num3 DECIMAL(19,4),
@num4 DECIMAL(19,4)

SELECT
@mon1 = 100,
@num1 = 100, @num2 = 339, @num3 = 10000

SET @mon4 = @mon1/@num2*@num3
SET @num4 = @num1/@num2*@num3

SELECT @mon4 AS moneyresult,
@num4 AS numericresult

Resultados no resultado correto:

moneyresult numericresult
--------------------- ----------------------------- ----------
2949.8525 2949.8525

moneyé bom desde que você não precise mais do que quatro dígitos decimais e verifique se seus escalares - que não representam dinheiro - são decimals.


57
Quantas moedas de um centavo você pode obter uma nota de dólar? uma resposta para isso requer dinheiro / dinheiro.
Aprendendo

48
@ Learning nesse caso, o resultado não é dinheiro, mas uma flutuação. (Análise dimensional básica).
Richard

11
@ Learning: Você pergunta ao banco de dados quantos centavos por dólar? De qualquer forma, isso retornaria o resultado certo. Seu problema era que o dinheiro / dinheiro era apenas preciso para quatro dígitos (era 0,2949) e, quando multiplicado por 10000, tornava-se 2949,0000.
Configurator

26
@mson Ele está correto e não faz críticas pessoais, como você fez com base em uma observação de uma linha, não ajuda. Se ele não dividir por US $ 0,01, mas sim por 0,01, o resultado será US $ 100 em vez de 100. Há 100 centavos em um dólar, não US $ 100 centavos. Unidades são importantes! Definitivamente, existe um ótimo lugar para mergulhar, e talvez multiplicar, dinheiro por dinheiro.
andrewb

19
Se eu quiser gastar US $ 1000 para comprar ações com preço de US $ 36, isso não é um uso legítimo money / money? A resposta é unidades inteiras sem nenhum sinal de cifrão, o que está correto! Esse é um cenário perfeitamente razoável, sugerindo que, devido a casos extremos estranhos como esse, moneynão é um bom tipo de dados a ser usado, pois o resultado é sempre truncado de volta ao ajuste, em moneyvez de seguir as regras normais de precisão e escala. E se você quiser calcular o desvio padrão de um conjunto de moneyvalores? Sim, Sqrt(Sum(money * money))(simplificado) realmente faz sentido.
ErikE

59

Tudo é perigoso se você não sabe o que está fazendo

Mesmo os tipos decimais de alta precisão não podem salvar o dia:

declare @num1 numeric(38,22)
declare @num2 numeric(38,22)
set @num1 = .0000006
set @num2 = 1.0
select @num1 * @num2 * 1000000

1.000000 <- deve ser 0,6000000


Os moneytipos são inteiros

As representações de texto smallmoneye decimal(10,4)podem ser parecidas, mas isso não as torna intercambiáveis. Você se encolhe quando vê datas armazenadas como varchar(10)? Isso é a mesma coisa.

Nos bastidores, money/ smallmoneysão apenas um bigint/ int O ponto decimal na representação de texto moneyé um buço visual, assim como os traços em uma data aaaa-mm-dd. SQL não armazena esses internamente.

Em relação a decimalvs money, escolha o que for apropriado para suas necessidades. Os moneytipos existem porque o armazenamento de valores contábeis como múltiplos inteiros de 1/10000 de unidade é muito comum. Além disso, se você estiver lidando com dinheiro e cálculos reais além da simples adição e subtração, não deve fazer isso no nível do banco de dados! Faça isso no nível do aplicativo com uma biblioteca que suporte o Banker's Rounding (IEEE 754)


1
Você pode explicar o que aconteceu neste exemplo?
Sergey Popov

4
Excesso de escala. Em escalas pequenas, numérico (a, b) * numérico (c, d) produz numérico (a-b + c-d + 1, máximo (b, d)). No entanto, se (a + b + c + d)> 38, o SQL limita a escala, roubando a precisão do lado da fração para preencher o lado inteiro, causando o erro de arredondamento.
Anon 15/05

Todos os cálculos numéricos são suscetíveis a perda de precisão devido à escala: em vez de computação selecionar 1000000 * @ num1 * @ num2
Mitch Wheat

O exemplo de Anon é específico da versão e do banco de dados. mas o ponto tenha cuidado é válido. no sqlanywhere versão 1.1, o exemplo fornece 0,600000 corretamente. (Eu sei que estamos falando sobre ms sql aqui). outro ponto sobre o tipo de dinheiro estar ausente em outro banco de dados, existem maneiras de chamar decimal ou numérico como dinheiro, como a criação de domínio.
Gg89 # 19/14

3
Eu acho que essa é a resposta mais esclarecedora, porque você explicou não apenas os erros que são propagados, mas o que realmente está acontecendo nos bastidores, e por que o DINHEIRO existe em primeiro lugar. Não sei por que demorou quatro anos para obter essa resposta, mas talvez seja porque há muito foco no "problema" do cálculo e não muito nos porquês e comos de dinheiro versus decimal.
Steve Sether

44

Sei que WayneM afirmou que sabe que o dinheiro é específico para o SQL Server. No entanto, ele está perguntando se há algum motivo para usar dinheiro em decimal ou vice-versa e acho que um motivo óbvio ainda deve ser declarado e que o uso de decimal significa que é menos uma coisa com que se preocupar se você precisar alterar seu DBMS - o que pode acontecer.

Torne seus sistemas o mais flexível possível!


1
Possivelmente, mas em teoria você pode declarar um domínio chamado Money em outro DBMS (que suporta a declaração de domínios).
Debated

Como alguém atualmente convertendo um banco de dados do SQL Server em Amazon Redshift, posso garantir que esse é um problema genuíno. Tente evitar tipos de dados personalizados para uma plataforma de banco de dados específica, a menos que haja razões comerciais muito sólidas para usá-los.
Nathan Griffiths

@Nathn, dado o sistema de tipo fraco do Redshift em comparação com o PostgreSQL ou SQL Server, por exemplo, nenhum datetipo, eu diria que você sempre terá esses problemas. Você deve dizer "Não use tipos obsoletos quando o banco de dados já fornece tipos melhores e mais compatíveis com os padrões e avisa contra os obsoletos".
Panagiotis Kanavos

@PanagiotisKanavos - dinheiro não é obsoleto
Martin Smith

O @MartinSmith ficou chocado ao ver isso, pois ele não pode realmente lidar com valores monetários como o BTC em 2017. Ou diferenciar entre valores de GBP e EUR - mesmo que eles se movam em direção à paridade: P. De qualquer forma, se mudar para Redshift introduz um monte de dor
Panagiotis Kanavos

32

Bem, eu gosto MONEY! É um byte mais barato que DECIMAL, e os cálculos são mais rápidos porque (sob as cobertas) operações de adição e subtração são essencialmente operações inteiras. O exemplo de @ SQLMenace - que é um ótimo aviso para os inconscientes - pode ser aplicado igualmente a INTegers, onde o resultado seria zero. Mas isso não é motivo para não usar números inteiros - quando apropriado .

Portanto, é perfeitamente 'seguro' e apropriado usar MONEYquando o que você está lidando é MONEYe usá-lo de acordo com as regras matemáticas a seguir (o mesmo que INTeger).

Teria sido melhor se o SQL Server promovesse a divisão e multiplicação de MONEYs em DECIMALs (ou FLOATs?) - possivelmente, mas eles não escolheram fazer isso; nem escolheram promover INTegers to FLOATs ao dividi-los.

MONEYnão tem problema de precisão; que DECIMALs começa a ter um tipo intermediário maior usado durante cálculos é apenas um 'recurso' de usar esse tipo (e eu não sou realmente certo o quão longe que 'recurso' estende).

Para responder à pergunta específica, uma "razão convincente"? Bem, se você quiser um desempenho máximo absoluto em um local SUM(x)onde xpode ser um DECIMALou outro MONEY, MONEYterá uma vantagem.

Além disso, não esqueça que é um primo menor SMALLMONEY- apenas 4 bytes, mas atinge o máximo de 214,748.3647- o que é bem pequeno para dinheiro - e, portanto, nem sempre é um bom ajuste.

Para provar o argumento de usar tipos intermediários maiores, se você atribuir o intermediário explicitamente a uma variável, DECIMALsofre o mesmo problema:

declare @a decimal(19,4)
declare @b decimal(19,4)
declare @c decimal(19,4)
declare @d decimal(19,4)

select @a = 100, @b = 339, @c = 10000

set @d = @a/@b

set @d = @d*@c

select @d

Produz 2950.0000(ok, então pelo menos DECIMALarredondado em vez de MONEYtruncado - o mesmo que um número inteiro.)


21
MONEYé um byte menor que um grande DECIMAL , com até 19 dígitos de precisão. No entanto, a maioria dos cálculos monetários do mundo real (até US $ 9,99 M) pode caber em um DECIMAL(9, 2), o que requer apenas cinco bytes. Você pode economizar tamanho, se preocupar menos com erros de arredondamento e tornar seu código mais portátil.

Enquanto @JonofAllTrades estiver correto, você também poderá recuperar o desempenho inteiro usando simplesmente um número inteiro que contém centavos ou centavos e salvar o byte extra que codifica a posição do ponto decimal e que deve ser verificado ao adicionar decimais.
dsz

"Portanto, é perfeitamente 'seguro' e apropriado usar o DINHEIRO quando estiver lidando com DINHEIRO e usá-lo de acordo com as regras matemáticas a seguir" -> no entanto, veja também a resposta de Anon: "Tudo é perigoso se você não saber o que você está fazendo ". Você nunca pode prever como as pessoas acabarão consultando o sistema que você está criando, melhor para evitar a possibilidade de uso indevido quando possível. O ganho minúsculo no armazenamento não vale a pena IMHO.
Nathan Griffiths

1
Tente armazenar um valor de Bitcoin. Tem 8 decimais
Panagiotis Kanavos

13

Acabamos de nos deparar com um problema muito semelhante e agora sou um +1 por nunca usar o Money, exceto na apresentação de nível superior. Temos várias tabelas (efetivamente um comprovante de vendas e uma fatura de vendas), cada uma das quais contém um ou mais campos do Money por motivos históricos, e precisamos executar um cálculo proporcional para determinar quanto do imposto total da fatura é relevante para cada um. linha no comprovante de vendas. Nosso cálculo é

vat proportion = total invoice vat x (voucher line value / total invoice value)

Isso resulta em um cálculo de dinheiro / dinheiro do mundo real que causa erros de escala na parte da divisão, que então se multiplica em uma proporção incorreta do tanque. Quando esses valores são adicionados posteriormente, terminamos com uma soma das proporções de IVA que não somam o valor total da fatura. Se um dos valores entre parênteses fosse decimal (estou prestes a lançar um deles como tal), a proporção da cuba estaria correta.

Quando os colchetes não estavam lá originalmente, isso costumava funcionar, acho que por causa dos valores maiores envolvidos, ele efetivamente simulava uma escala mais alta. Adicionamos os colchetes porque ele fazia a multiplicação primeiro, o que, em alguns casos raros, diminuía a precisão disponível para o cálculo, mas isso agora causou esse erro muito mais comum.


8
Mas isso ocorre apenas porque um desenvolvedor ignorante ignorou as regras para os cálculos do IVA e as limitações de precisão documentadas do dinheiro.
TomTom

1
@ TomTom, mas o que você está dizendo sobre a possibilidade de uso indevido desse tipo de dado é um argumento a favor de evitar usá-lo.
Nathan Griffiths

@ Nathan N. Estou apontando que o argumento dado como motivo para nunca usá-lo é basicamente um desenvolvedor incompetente, portanto o argumento é falso.
TomTom

1
@ TomTom, infelizmente, existem muitos desenvolvedores incompetentes (assim como muitos incríveis) e para mim, a menos que eu possa garantir como esses dados serão consultados no futuro e ninguém jamais cometeria o tipo de erro descrito aqui , é melhor errar por precaução e usar um tipo decimal. Dito isso, depois de ler todas essas respostas, posso ver que existem alguns casos de uso específicos em que o dinheiro seria o tipo ideal de usar, só não o usaria, a menos que houvesse um caso de uso muito bom para ele (por exemplo, a coluna será sempre agregados pelo SUM, carregando em massa grandes quantidades de dados financeiros).
Nathan Griffiths

@ TomTom não são apenas as limitações de precisão. A representação interna também pode causar problemas. O dinheiro é um tipo de conveniência para capturar desenvolvedores ignorantes, e não um ótimo tipo que os desenvolvedores estão usando indevidamente. O exemplo do IVA, independentemente das regras para calculá-lo, claramente deve afugentar desenvolvedores não ignorantes ao aplicar o específico ao geral.
precisa

12

Como um contraponto ao impulso geral das outras respostas. Veja os muitos benefícios do dinheiro ... Tipo de dados! no Guia do SQLCAT para o mecanismo relacional

Especificamente, gostaria de salientar o seguinte

Trabalhando nas implementações de clientes, encontramos alguns números de desempenho interessantes sobre o tipo de dados monetários. Por exemplo, quando o Analysis Services foi definido como o tipo de dados da moeda (do dobro) para corresponder ao tipo de dados monetários do SQL Server, houve uma melhoria de 13% na velocidade de processamento (linhas / s). Para obter um desempenho mais rápido no SSIS (SQL Server Integration Services) para carregar 1,18 TB em menos de trinta minutos, conforme observado no SSIS 2008 - desempenho ETL recorde mundial, observou-se que a alteração das quatro colunas decimais (9,2) com um tamanho de 5 bytes na tabela TPC-H LINEITEM em dinheiro (8 bytes) melhoraram a velocidade de inserção em massa em 20% ... O motivo da melhoria de desempenho é devido ao protocolo TDS (Tabular Data Stream) do SQL Server, que possui o principal princípio de design para transferir dados em formato binário compacto e o mais próximo possível do formato de armazenamento interno do SQL Server. Empiricamente, isso foi observado durante o SSIS 2008 - teste de desempenho ETL recorde mundial usando Kernrate; o protocolo caiu significativamente quando o tipo de dados foi mudado para dinheiro a partir de decimal. Isso torna a transferência de dados o mais eficiente possível. Um tipo de dados complexo precisa de análise e ciclos de CPU adicionais para lidar com um tipo de largura fixa.

Portanto, a resposta para a pergunta é "depende". Você precisa ter mais cuidado com certas operações aritméticas para preservar a precisão, mas pode achar que as considerações de desempenho valem a pena.


Como você armazenaria bitcoin então?
Panagiotis Kanavos

@PanagiotisKanavos - Não faço ideia. Eu nunca procurei no bitcoin e praticamente não sei nada sobre isso!
Martin Smith

6

Quero dar uma visão diferente de DINHEIRO vs. NUMÉRICO, com base amplamente em minha própria experiência e experiência ... Meu ponto de vista aqui é DINHEIRO, porque eu trabalhei com ele por um longo tempo e nunca usei muito NUMÉRICO .. .

DINHEIRO Pro:

  • Tipo de dados nativo . Ele usa um tipo de dados nativo ( inteiro ) igual ao registro da CPU (32 ou 64 bits), para que o cálculo não precise de sobrecarga desnecessária, por isso é menor e mais rápido ... O DINHEIRO precisa de 8 bytes e NUMÉRICO (19, 4 ) precisa de 9 bytes (12,5% maior) ...

    O DINHEIRO é mais rápido, desde que seja usado para o que deveria ser (como dinheiro). Quão rápido? Meu SUMteste simples com 1 milhão de dados mostra que o DINHEIRO é 275 ms e o NUMERIC 517 ms ... Isso é quase o dobro da velocidade ... Por que o teste SUM? Veja o próximo ponto Pro

  • Melhor por dinheiro . O DINHEIRO é melhor para armazenar dinheiro e realizar operações, por exemplo, em contabilidade. Um único relatório pode executar milhões de adições (SUM) e algumas multiplicações após a conclusão da operação SUM. Para aplicações contábeis muito grandes, é quase o dobro da velocidade e é extremamente significativo ...
  • Baixa precisão de dinheiro . Dinheiro na vida real não precisa ser muito preciso. Quero dizer, muitas pessoas podem se importar com 1 centavo de dólar, mas que cerca de 0,01 centavo? De fato, no meu país, os bancos não se preocupam mais com centavos (dígito após vírgula decimal); Eu não sei sobre o banco dos EUA ou outro país ...

DINHEIRO Con:

  • Precisão limitada . O DINHEIRO possui apenas quatro dígitos (após a vírgula) de precisão, portanto, ele precisa ser convertido antes de realizar operações como divisão ... Mas, novamente money, não precisa ser tão preciso e deve ser usado como dinheiro, não apenas como número...

Mas ... Grande, mas aqui está mesmo seu aplicativo envolvido com dinheiro real, mas não o use em muitas operações SUM, como na contabilidade. Se você usar muitas divisões e multiplicações, não deverá usar DINHEIRO ...


1
Se você diz que o dinheiro é mais rápido que o decimal, precisa nos dizer coisas como quais rdbms, em qual hardware, executando o SO, com quais dados específicos executando a consulta específica sobre a qual você está falando. Além disso, se não for COMPLETAMENTE exato, NÃO estou fazendo nenhuma operação financeira com ele, porque o homem do imposto ficará bastante descontente por recuperar números ruins. Você se preocupa com o milésimo centavo se estiver lidando com moedas dos EUA, por exemplo. Se o dinheiro não está fazendo isso, não é utilizável.
Haakon Løtveit

3
@ HaakonLøtveit todo este segmento de perguntas e respostas é sobre o tipo de dados "dinheiro" do SQL Server, então acho que eles não precisam especificar isso na resposta. O dinheiro pode ser mais rápido de usar do que o decimal em algumas circunstâncias (por exemplo, carregar dados); consulte a resposta de Martin Smith para obter mais detalhes. Concordo com a maioria desta resposta, pois há certos casos de uso que podem tornar o Money uma opção mais eficiente que o decimal, no entanto, a menos que exista um caso muito convincente para usá-lo, acho que deve ser evitado.
Nathan Griffiths

1
Bitcoin tem 8 casas decimais. Você não pode nem armazená-lo em uma moneycoluna
Panagiotis Kanavos

4

Todas as postagens anteriores trazem pontos válidos, mas alguns não respondem à pergunta com precisão.

A pergunta é: por que alguém prefere dinheiro quando já sabemos que é um tipo de dados menos preciso e pode causar erros se usado em cálculos complexos?

Você usa dinheiro quando não faz cálculos complexos e pode trocar essa precisão por outras necessidades.

Por exemplo, quando você não precisa fazer esses cálculos e precisa importar dados de cadeias de texto de moeda válidas. Essa conversão automática funciona apenas com o tipo de dados MONEY:

SELECT CONVERT(MONEY, '$1,000.68')

Eu sei que você pode fazer sua própria rotina de importação. Mas, às vezes, você não deseja recriar uma rotina de importação com formatos de código de idioma específicos em todo o mundo.

Outro exemplo, quando você não precisa fazer esses cálculos (é necessário apenas armazenar um valor) e salvar 1 byte (o dinheiro leva 8 bytes e o decimal (19,4) leva 9 bytes). Em algumas aplicações (CPU rápida, grande RAM, E / S lenta), como apenas ler uma quantidade enorme de dados, isso também pode ser mais rápido.


2

Você não deve usar dinheiro quando precisar fazer multiplicações / divisões no valor. O dinheiro é armazenado da mesma maneira que um número inteiro é armazenado, enquanto o decimal é armazenado como um ponto decimal e dígitos decimais. Isso significa que o dinheiro diminui a precisão na maioria dos casos, enquanto o decimal só o faz quando convertido de volta à sua escala original. O dinheiro é ponto fixo, portanto sua escala não muda durante os cálculos. No entanto, como é um ponto fixo quando é impressa como uma sequência decimal (em oposição a uma posição fixa em uma sequência base 2), os valores até a escala de 4 são representados exatamente. Portanto, para adição e subtração, o dinheiro é bom.

Um decimal é representado internamente na base 10 e, portanto, a posição do ponto decimal também é baseada no número da base 10. O que faz com que sua parte fracionária represente seu valor exatamente, exatamente como no dinheiro. A diferença é que valores intermediários de decimal podem manter a precisão até 38 dígitos.

Com um número de ponto flutuante, o valor é armazenado em binário como se fosse um número inteiro, e a posição do ponto decimal (ou binário, ahem) é relativa aos bits que representam o número. Por ser um ponto decimal binário, os números da base 10 perdem a precisão logo após o ponto decimal. 1/5, ou 0,2, não pode ser representado com precisão dessa maneira. Nem dinheiro nem decimal sofrem com essa limitação.

É fácil converter dinheiro para decimal, executar os cálculos e depois armazenar o valor resultante em um campo ou variável monetário.

No meu ponto de vista, quero que coisas que acontecem com números aconteçam sem ter que pensar muito neles. Se todos os cálculos forem convertidos em decimal, então eu gostaria de usar decimal. Eu salvaria o campo do dinheiro para fins de exibição.

Em termos de tamanho, não vejo diferença suficiente para mudar de idéia. O dinheiro ocupa de 4 a 8 bytes, enquanto o decimal pode ser 5, 9, 13 e 17. Os 9 bytes podem cobrir todo o intervalo que os 8 bytes de dinheiro. Em termos de índice (a comparação e a pesquisa devem ser comparáveis).


Obrigado pelo Upvote. Estou olhando para isso e, enquanto eu entendo o que estava tentando dizer, também vejo isso muito confuso. Talvez eu o reescreva mais tarde com alguns exemplos de bits versus decimais.
precisa

2

Encontrei uma razão para usar decimal sobre dinheiro em assuntos de precisão.

DECLARE @dOne   DECIMAL(19,4),
        @dThree DECIMAL(19,4),
        @mOne   MONEY,
        @mThree MONEY,
        @fOne   FLOAT,
        @fThree FLOAT

 SELECT @dOne   = 1,
        @dThree = 3,    
        @mOne   = 1,
        @mThree = 3,    
        @fOne   = 1,
        @fThree = 3

 SELECT (@dOne/@dThree)*@dThree AS DecimalResult,
        (@mOne/@mThree)*@mThree AS MoneyResult,
        (@fOne/@fThree)*@fThree AS FloatResult

Resultado decimal> 1.000000

MoneyResult> 0.9999

Resultado da flutuação> 1

Basta testá-lo e tomar sua decisão.


2
Gostaríamos muito de ouvir (ler, isto é) sua conclusão.
Peter Mortensen

@PeterMortensen Acho que se eu quiser ter integridade e precisão entre os tipos Money e Decimal, minha decisão deve ser Decimal.
QMaster 20/08/19

1
Considere atualizar sua resposta com o resultado real acima. Em seguida, seu conclusão será imediatamente óbvio para leitura ninguém :-)
Agreax

1
@Ageax O resultado foi adicionado à resposta.
QMaster 25/09/19

1

Acabei de ver esta entrada do blog: Dinheiro vs. decimal no SQL Server .

O que basicamente diz que o dinheiro tem um problema de precisão ...

declare @m money
declare @d decimal(9,2)

set @m = 19.34
set @d = 19.34

select (@m/1000)*1000
select (@d/1000)*1000

Para o moneytipo, você receberá 19.30 em vez de 19.34. Não tenho certeza se existe um cenário de aplicativo que divide dinheiro em 1000 partes para cálculo, mas este exemplo expõe algumas limitações.


15
Não é um "problema", é "por especificações": «Os tipos moneye de smallmoneydados são precisos para dez milésimos das unidades monetárias que eles representam.» como dito em msdn.microsoft.com/en-us/library/ms179882.aspx, para que qualquer pessoa que diga "é lixo" não saiba do que está falando.
Albireo
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.