Estou curioso para saber se existe ou não uma diferença real entre o money
tipo 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 money
e não decimal
para 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 :)
sql-server
types
Wayne Molina
fonte
fonte
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.Respostas:
Nunca você deve usar dinheiro. Não é preciso e é puro lixo; sempre use decimal / numérico.
Execute isso para ver o que quero dizer:
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.
fonte
money
excessomoney
, essa 'ilustração' é manipuladora. É um fato documentado quemoney
possui 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. Ummoney
essencialmente é um int de 64 bits e, se você lidasse com ints, multiplicaria antes de dividir.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.
Resultados no resultado correto:
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ãodecimal
s.fonte
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,money
não é um bom tipo de dados a ser usado, pois o resultado é sempre truncado de volta ao ajuste, emmoney
vez de seguir as regras normais de precisão e escala. E se você quiser calcular o desvio padrão de um conjunto demoney
valores? Sim,Sqrt(Sum(money * money))
(simplificado) realmente faz sentido.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:
1.000000 <- deve ser 0,6000000
Os
money
tipos são inteirosAs representações de texto
smallmoney
edecimal(10,4)
podem ser parecidas, mas isso não as torna intercambiáveis. Você se encolhe quando vê datas armazenadas comovarchar(10)
? Isso é a mesma coisa.Nos bastidores,
money
/smallmoney
são apenas umbigint
/int
O ponto decimal na representação de textomoney
é 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
decimal
vsmoney
, escolha o que for apropriado para suas necessidades. Osmoney
tipos 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)fonte
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!
fonte
date
tipo, 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".Bem, eu gosto
MONEY
! É um byte mais barato queDECIMAL
, 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 aINT
egers, 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
MONEY
quando o que você está lidando éMONEY
e usá-lo de acordo com as regras matemáticas a seguir (o mesmo queINT
eger).Teria sido melhor se o SQL Server promovesse a divisão e multiplicação de
MONEY
s emDECIMAL
s (ouFLOAT
s?) - possivelmente, mas eles não escolheram fazer isso; nem escolheram promoverINT
egers toFLOAT
s ao dividi-los.MONEY
não tem problema de precisão; queDECIMAL
s 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)
ondex
pode ser umDECIMAL
ou outroMONEY
,MONEY
terá uma vantagem.Além disso, não esqueça que é um primo menor
SMALLMONEY
- apenas 4 bytes, mas atinge o máximo de214,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,
DECIMAL
sofre o mesmo problema:Produz
2950.0000
(ok, então pelo menosDECIMAL
arredondado em vez deMONEY
truncado - o mesmo que um número inteiro.)fonte
MONEY
é um byte menor que um grandeDECIMAL
, 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 umDECIMAL(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.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 é
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.
fonte
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
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.
fonte
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
SUM
teste 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 ProDINHEIRO Con:
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 ...
fonte
money
colunaTodas 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:
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.
fonte
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).
fonte
Encontrei uma razão para usar decimal sobre dinheiro em assuntos de precisão.
Resultado decimal> 1.000000
MoneyResult> 0.9999
Resultado da flutuação> 1
Basta testá-lo e tomar sua decisão.
fonte
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 ...
Para o
money
tipo, 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.fonte
money
e desmallmoney
dados 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.