Melhor tipo de dados para armazenar valores de moeda em um banco de dados MySQL

Respostas:

227

Algo como Decimal(19,4)geralmente funciona muito bem na maioria dos casos. Você pode ajustar a escala e a precisão para atender às necessidades dos números que você precisa armazenar. Mesmo no SQL Server, costumo não usar " money" por não ser padrão.

Kibbee
fonte
52
Um ponto sobre o tamanho: de acordo com o MSDN ( msdn.microsoft.com/en-us/library/ms187746.aspx ), decimal (10,4) e decimal (19,4), ambos usam 9 bytes de armazenamento; bem primavera para esses 9 dígitos extras de escala.
Adam Nofsinger 24/03/10
1
O artigo do MSDN é sobre o SQL Server, mas a pergunta é sobre o MySQL. (Eu conheci desenvolvedores que pensam que ambos são os mesmos de modo melhor para ser claro.)
CJA
5
Qual é o benefício de usar em (19,4)vez de (19,2)?
ryvantage
1
Meu benefício foi esse. Eu precisava de todas as minhas linhas da tabela para igualar uma quantia específica de dinheiro. Digamos que esse valor seja de US $ 10,00. À medida que novas linhas são adicionadas, o valor de cada linha é alterado. Se houver três linhas na tabela. 10/3 = 3,33333333333 ... mas com apenas 2 casas decimais, eles são armazenados como 3,33. Então, quando você soma, 3,33 + 3,33 + 3,33 = 9,99. Perdemos um centavo! Fica ainda pior em um conjunto de dados maior. Guarde-o em 19,4 e somar os totais, em seguida, volta a saída para 19,2 ..
Rick
49

A única coisa que você deve observar é que, se você migrar de um banco de dados para outro, poderá achar que DECIMAL (19,4) e DECIMAL (19,4) significam coisas diferentes

( http://dev.mysql.com/doc/refman/5.1/en/precision-math-decimal-changes.html )

    DBASE: 10,5 (10 inteiros, 5 decimais)
    MYSQL: 15,5 (15 dígitos, 10 inteiro (15-5), 5 decimal)
SeanJA
fonte
Infelizmente, o link está morto.
Marco Aurélio Deleu 19/08/19
1
@ MarcoAurélioDeleu - Alterei o link para apontar para a página na Wayback Machine, para que você possa vê-la como foi vista em 2009.
Tony
17

Também é importante calcular quantas casas decimais talvez sejam necessárias para seus cálculos.

Trabalhei em um aplicativo de preço de ações que exigia o cálculo do preço de um milhão de ações. O preço da ação cotado teve que ser armazenado com 7 dígitos de precisão.

Leah
fonte
7
É um ponto bom - especialmente em aplicações financeiras, "preço" certamente não significa "dinheiro"
Mike Woodhouse
17

A resposta de Assaf de

Depende de quanto dinheiro você conseguiu ...

parece irreverente, mas na verdade é pertinente.

Só hoje tivemos um problema em que um registro falhou ao ser inserido em nossa tabela de taxas, porque uma das colunas (GrossRate) está definida como Decimal (11,4) e nosso departamento de produtos conseguiu um contrato para quartos em algum resort incrível em Bora Bora, que é vendida por vários milhões de francos do Pacífico por noite ... algo que nunca foi antecipado quando o esquema do banco de dados foi projetado 10 anos atrás.

Scott Ferguson
fonte
2
É por isso que eu recomendei o decimal (19,4). Pode parecer um exagero, mas você nunca sabe quando precisará armazenar uma quantidade muito grande nesse campo.
22409 Kibbee
2
@Kibbee: Eu não teria concordado com você sobre nossos requisitos até hoje. (Por 6 anos (11,4) foi perfeitamente bem ...)
Scott Ferguson
@Kibbee Isso soa como 640 Kb meme :) #
Nikita Bosik
13

Para aplicativos de contabilidade, é muito comum armazenar os valores como números inteiros (alguns chegam a dizer que é o único caminho). Para ter uma idéia, calcule o valor das transações (suponha $ 100,23) e multiplique por 100, 1000, 10000 etc. para obter a precisão necessária. Portanto, se você precisar armazenar apenas centavos e puder arredondar para cima ou para baixo com segurança, basta multiplicar por 100. No meu exemplo, isso tornaria 10023 o número inteiro a ser armazenado. Você economizará espaço no banco de dados e comparar dois números inteiros é muito mais fácil do que comparar dois carros alegóricos. Meus US $ 0,02.

Dane Bendixen
fonte
Como você armazena 6.125 (6 1/8)?
PeterToTheThird
Eu acho que ele iria armazená-lo como um número inteiro 6125.
Jimmy Knoot
2
Como isso seria melhor do que DECIMAL? Você precisaria ter muito cuidado para sempre converter moedas de um centavo, moinhos ou millrays em dólares, nos momentos apropriados.
Eu li que o desempenho normalmente é mais rápido com o INT do que o DECIMAL, mesmo nas versões mais recentes do MySQL. Também é mais fácil quando você precisa trazer esses valores para o PHP ou algo assim e comparar valores.
Dane Bendixen
9

entrada super tardia, mas o GAAP é uma boa regra geral.

Se o seu aplicativo precisar lidar com valores monetários de até um trilhão, isso deve funcionar: 13,2 Se você precisar cumprir os GAAP (princípios de contabilidade geralmente aceitos), use: 13,4

Normalmente você deve somar seus valores monetários em 13,4 antes de arredondar a saída para 13,2.

Fonte: Melhor tipo de dados para armazenar valor monetário no MySQL

Damian
fonte
5

Você pode usar algo como DECIMAL(19,2)por padrão para todos os seus valores monetários, mas se você apenas armazenar valores inferiores a US $ 1.000, isso será apenas um desperdício de espaço valioso no banco de dados.

Para a maioria das implementações, DECIMAL(N,2)seria suficiente, onde o valor de Né pelo menos o número de dígitos antes .da maior soma que você espera que seja armazenada nesse campo + 5. Portanto, se você nunca espera armazenar valores maiores que 999999.99, DECIMAL(11,2)deve ser mais do que suficiente (até as expectativas mudarem).

Se você deseja ser compatível com GAAP , pode ir com DECIMAL(N,4), onde o valor de Né pelo menos o número de dígitos antes .da maior soma que você espera que seja armazenada nesse campo + 7.

John Slegers
fonte
3

Depende da natureza dos dados. Você precisa contemplar isso de antemão.

O meu caso

  • decimal (13,4) não assinado para registrar transações em dinheiro
    • armazenamento eficiente (4 bytes para cada lado do ponto decimal de qualquer maneira) 1
    • Compatível com GAAP
  • decimal (19,4) não assinado para agregados
    • precisamos de mais espaço para totais de várias transações de vários bilhões
    • semi-conformidade com o tipo de dados MS Currency não prejudicará 2
    • será necessário mais espaço por registro (11 bytes - 7 à esquerda e 4 à direita), mas isso é bom, pois há menos registros para agregados 1
  • decimal (10,5) para taxas de câmbio
    • eles são normalmente citados com 5 dígitos no total, para que você possa encontrar valores como 1,2345 e 12,345, mas não 12345,67890
    • é uma convenção generalizada, mas não é um padrão codificado (pelo menos para meu conhecimento de pesquisa rápida)
    • você pode torná-lo decimal (18,9) com o mesmo armazenamento, mas as restrições de tipo de dados são um valioso mecanismo de validação interno

Por que (M, 4)?

  • existem moedas que se dividem em mil centavos
  • existem equivalentes monetários como "Unidad de Fermento", "CLF" expressos com 4 casas decimais significativas 3 , 4
  • é compatível com GAAP

Troca

  • menor precisão:
    • menor custo de armazenamento
    • cálculos mais rápidos
    • menor risco de erro de cálculo
    • backup e restauração mais rápidos
  • maior precisão:
    • compatibilidade futura (os números tendem a aumentar)
    • economia de tempo de desenvolvimento (você não precisará reconstruir metade de um sistema quando os limites forem atingidos)
    • menor risco de falha na produção devido à precisão insuficiente de armazenamento

Extreme Compatível

Embora o MySQL permita que você use decimal (65,30), 31 para escala e 30 para precisão parecem ser nossos limites se quisermos deixar a opção de transferência em aberto.

Escala e precisão máximas nos RDBMS mais comuns:

            Escala de precisão
Oracle 31 31
T-SQL 38 38
MySQL 65 30
PostgreSQL 131072 16383

6 , 7 , 8 , 9

Extrema razoável

  1. Por que (27,4)?
    • você nunca sabe quando o sistema precisa armazenar dólares do Zimbábue

Setembro de 2015 O governo do Zimbábue declarou que trocaria dólares do Zimbábue por dólares dos EUA a uma taxa de 1 USD a 35 quadrilhões de dólares do Zimbábue 5

Nós tendemos a dizer "sim, claro ... eu não vou precisar dessas figuras malucas". Bem, os zimbabuenses costumavam dizer isso também. Não faz muito tempo.

Vamos imaginar que você precise registrar uma transação de US $ 1 milhão em dólares do Zimbábue (talvez hoje improvável hoje, mas quem sabe como será isso daqui a 10 anos?).

  1. (1 mln USD) * (35 Quadrylion ZWL) = (10 ^ 6) * (35 * 10 ^ 15) = 35 * 10 ^ 21
  2. nós precisamos:
    • 2 dígitos para armazenar "35"
    • 21 dígitos para armazenar os zeros
    • 4 dígitos à direita da vírgula decimal
  3. isso torna decimal (27,4), o que nos custa 15 bytes para cada entrada
  4. podemos adicionar mais um dígito à esquerda sem custos - temos decimal (28,4) por 15 bytes
  5. Agora podemos armazenar transações de US $ 10 milhões, expressas em dólares do Zimbábue, ou protegidas de outra greve de hiperinflação, que, esperamos, não acontecerá
kshishkin
fonte
0

Embora isso possa ser tarde, mas será útil para outra pessoa. Da minha experiência e pesquisa, vim a conhecer e aceitar decimal (19, 6). Isso é quando se trabalha com php e mysql. ao trabalhar com grande quantidade de dinheiro e taxa de câmbio

precioso
fonte