Para değerlerini MySQL'de depolamak için en iyi veri türü


279

Birçok kaydı bir MySQL veritabanında saklamak istiyorum. Hepsi para değerleri içerir. Ama her biri için kaç basamak ekleneceğini bilmiyorum.
Bu amaçla hangi veri türünü kullanmam gerekiyor?
VARCHAR veya INT (veya diğer sayısal veri türleri)?


13
deimal(10,2)kullandığım şey ... değerleri beklenen boyuta göre ayarlayabilirsiniz
Manse

Yanıtlar:


370

Paranın tam bir temsile ihtiyacı olduğundan, sadece yaklaşık olarak benzer veri türlerini kullanmayın float. Bunun için sabit noktalı bir sayısal veri türü kullanabilirsiniz

decimal(15,2)
  • 15 kesinliktir (ondalık basamaklar dahil toplam değer uzunluğu)
  • 2 ondalık noktadan sonraki basamak sayısı

Bkz. MySQL Sayısal Türleri :

Bu türler, örneğin parasal veriler gibi kesin doğruluğun korunması önemli olduğunda kullanılır .


3
bu durum için ondalık ve sayısal veri türü arasındaki fark ne olabilir?
Emilio Gort

60
MySQL decimalve numericaynı.
juergen d

21
Şahsen, numeric(19,4)yeni talepleri kolayca oynamanız ve benimsemeniz için daha iyi bir el sağlayan finansal kayıtlar için kullanıyorum .
YahyaE

10
YahyaE'ye katılıyorum, daha fazla ondalık sayı daha iyi. Bahreyn, Ürdün veya Kuveyt Dinarı gibi tipik olarak 3 ondalık basamak kullanan bazı para birimleri vardır, bu yüzden en az 3'e ihtiyacınız vardır. Dört veya beş daha iyidir.
Edwin Hoogerbeets

1
@EdwinHoogerbeets Muhasebeci değil ... İngiltere'de küçük bir biz yönetiyoruz ... Uzun zaman önce bir yerde okuduğumu hatırlıyorum, para birimi rakamlarının £, $, vb. İçin bile 4 ondalığa depolanması gerektiğini hatırlıyorum. gerçekte bazı belirsiz muhasebe bağlamları için son 2 ondalık basamağı kullanın . Onaylamak / reddetmek için bir muhasebeciye ihtiyacım var.
mike rodent

88

Kullanabilirsiniz DECIMALveya NUMERICher ikisi de aynı

DECIMAL ve NUMERIC türleri kesin sayısal veri değerlerini saklar. Bu türler, örneğin parasal veriler gibi kesin doğruluğun korunması önemli olduğunda kullanılır. MySQL'de NUMERIC DECIMAL olarak uygulanır, bu nedenle DECIMAL ile ilgili aşağıdaki açıklamalar NUMERIC için eşit olarak geçerlidir. : MySQL

yani DECIMAL(10,2)

Örnek ayarlar

İyi okuma


3
Belki kafa karıştırıcı olabilir, ancak ekran görüntünüz cevap metninizle (kesinlik, ölçek) eşleşmiyor.
Patrick Hofman

Para değerim için ondalık (10,2) kullanıyorum, ancak 867.000,00 gibi bir şey koyduğumda 867 olarak kaydediliyor. Ne yapıyorum?
codeinprogress

32

Tamsayı olması BIGINTiçin değerleri 100 ile çarpmayı kullanmayı ve saklamayı tercih ederim .

Örneğin, bir para birimi değerini temsil etmek için , değer 100'e bölebileceğimiz ve gösterebileceğimiz değeri görüntülerken 93.49olarak kaydedilecektir . Bu daha az depolama alanı kaplar.9349

Dikkat:
Çoğunlukla currency * currencyçarpma yapmayız , eğer yaparsak sonucu 100'e bölüp saklayın, böylece doğru hassasiyete geri döner.


Benzer bir şeyi Bilgisayar Sistemleri üniversite dersimdeki bir profesör tarafından anlatıldığını hatırlıyorum. Bana en kesin yol, 100 ile çarparak ve bir Tamsayı olarak kaydederek ve kullanıcıya göstermek için 100'e bölerek pennies (veya cent) depolamaktır. Bunun veritabanı sisteminin doğruluğu ve performansı açısından faydaları olduğunu düşünüyorum.
LondonAppDev

11
Avantajı nedir DECIMAL? Pennileri dolara çevirmeye ihtiyaç duyuyorsun ve bir noktada unutursan vahim.

1
Uzay tek avantajdır, ancak evet bu özelliği kullanırken daha dikkatli olmalıyız.
Dinesh PR

4
Açıkça görülmüyorsa: parayı kesirli sentlerde (örn. $0.005Veya $0.12345) depolarsanız ölçek kaldırma yöntemini kullanmaya dikkat edin, çünkü 100 ile çarpıldıktan sonra bir tam sayıya düşmeyeceklerdir. Değerlerin kesinliğini biliyorsanız, en iyi seçenek kullanmaktır DECIMAL. Ama kesinliği bilmiyorsanız (örneklerimdeki gibi) o zaman… FLOATuygun olur mu?
Quinn Comendant

1
Bu yöntemin bir avantajı, kayan nokta sayılarını depolamak için IEEE-754 kullanan JavaScript gibi bir dil kullanıldığında gelir. Bu şartname 0,1 + 0,2 === 0,3'ün doğru olduğunu garanti etmez. Para birimini bir tamsayı olarak saklamak, uygulamanızın bu tür hatalara yol açmayacağından emin olur. Bu en iyi çözüm olmayabilir. Çözümleri araştırırken bu sayfaya geldim ve henüz bitirmedim.
Gary Ott

27

İhtiyacınıza göre değişir.

DECIMAL(10,2)Genellikle kullanmak yeterlidir, ancak biraz daha kesin değerlere ihtiyacınız varsa ayarlayabilirsiniz DECIMAL(10,4).

Büyük değerler yerine birlikte Eğer çalışıyorsanız 10ile 19.


Para değerim için ondalık (10,2) kullanıyorum, ancak 867.000,00 gibi bir şey koyduğumda 867 olarak kaydediliyor. Ne yapıyorum?
codeinprogress

2
@codeinprogress Yanlış yerel ayar / ondalık ayırıcı mı kullanıyorsunuz?
David Balažic

15

Başvurunuzun bir trilyona kadar para değerlerini işlemesi gerekiyorsa, bunun çalışması gerekir: 13,2 GAAP (Genel Kabul Görmüş Muhasebe İlkeleri) ile uyumlu olmanız gerekiyorsa şunu kullanın: 13,4

Çıktının 13,2'ye yuvarlanmasından önce genellikle para değerlerinizi 13,4 olarak toplamalısınız.


5
Bitcoin'i alacaksanız, 8 ondalık basamağa ihtiyacınız olacak, ancak çoğu cüzdan 3 en.wikipedia.org/wiki/Bitcoin
Christian

Bu cevabın doğru olduğunu düşünmeyin. opendata.stackexchange.com/a/10348/13983 @ david.ee bunun için bir kaynağınız mı var?
Evan Carroll

@EvanCarroll david.ee için cevap vereyim. Bu makalenin kaynağı olabileceğini düşünüyorum bietta.com/blog/2012/03/03/best-data-types-for-currencymoney-in
naXa 14:18

@ naXa bağlantı, GAAP için 13,4 kullanma iddiasını destekleyen hiçbir kaynaktan alıntı yapmaz. Tek yaptığınız, aynı asılsız iddiayı yapan bir makaleye bağlantı oluşturmaktı.
iheanyi

6

Aslında bu programcının tercihlerine dayanmaktadır. Şahsen ben kullanıyorum: Genel Kabul Görmüş Muhasebe İlkelerine ( GAAP )numeric(15,4) uymak için .


5
Bunun "programcının tercihleri" veya "kişisel olarak kullandığınız" ile hiçbir ilgisi yoktur. Ondalık sayı tabanı gerektiren sorun etki alanı tarafından belirlenir. Bu, programcının kendi kişisel tercihlerini uyguladığı bir mesele değildir.
Marquis of Lorne

3

Kullanmayı deneyin

Decimal(19,4)

bu genellikle diğer tüm DB'lerle de çalışır


3

Biz kullanıyoruz double.

* Gasp *

Neden?

Ondalık noktasının nerede olduğu konusunda herhangi bir kısıtlama olmaksızın 15 haneli herhangi bir sayıyı temsil edebildiğinden . Her şey 8 bayt için!

Yani şunları temsil edebilir:

  • 0.123456789012345
  • 123456789012345.0

... ve aradaki her şeyi.

Bu yararlıdır çünkü küresel para birimleriyle uğraşıyoruz vedouble muhtemelen karşılaşacağımız çeşitli ondalık basamakları saklayabiliriz.

Tek bir doublealan Japon yeni cinsinden 999,999,999,999,999'ları, ABD doları cinsinden 9,999,999,999,999,99'ları ve hatta bitcoin olarak 9,999,999,9999999'ları temsil edebilir.

Eğer aynısını yapmaya çalışırsanız decimal,decimal(30, 15) 14 bayta mal .

Uyarılar

Tabii ki, double uyarılar olmadan değil.

Bununla birlikte, bazıları belirtildiği gibi doğruluk kaybı değildir . Rağmen doublekendisi olmayabilir taban 10 sistemine içten kesin , biz bunu kesin yapabilir değerini yuvarlama biz onun önemli ondalık basamağa veritabanından çekin. Gerekirse. (örneğin, çıktı alınacaksa ve temel 10 gösterimi gerekiyorsa.)

Uyarılar, onunla aritmetik yaptığımız her zaman, sonucu daha önce normalleştirmemiz gerekir (önemli ondalık basamaklara yuvarlayarak):

  1. Üzerinde karşılaştırmalar yapmak.
  2. Veritabanına geri yazmak.

Başka bir uyarı, decimal(m, d)veritabanının programların mrakamdan daha fazla rakam eklemesini engellediği durumun aksine , böyle bir doğrulama yoktur double. Bir program, kullanıcı tarafından girilen 20 basamaklı bir değer girebilir ve sonuç olarak sessizce yanlış bir tutar olarak kaydedilir.


İlk defa böyle bir cevap gördüm, ilginç. S: Veritabanına 1.41 gibi bir şamandıra yazarsam ve herhangi bir nedenle mysql'de 1.000.000.000.000 gibi çok büyük bir sayı ile çarpmam gerekir. Yuvarlanan sonuç tam olarak şöyle olacak: 1.410.000.000.000?
roelleor

@roelleor Sonuçta tam olarak 1.410.000.000.000 (binlik basamak ayırıcı olarak virgül) olması için girdinin 1.410000000000(on iki önemli ondalık basamak) olduğu varsayılır , ancak bunun 1.000.000.000.000 ile çarpılması (ondalık noktadan 13 önemli basamak olan) en az 25 basamaklı bir anlamlılık. Bu, bir çift için mevcut 15'i geçiyor, bu yüzden tasarım açısından çok kırılacağını düşünüyorum.
antak

2

O zaman bu soruya kimsenin Bitcoin fiyatı hakkında düşünmediği soruldu. BTC durumunda, muhtemelen kullanmak yetersizdir DECIMAL(15,2). Bitcoin 100.000 dolara veya daha fazlaya yükselecekse, en azından DECIMAL(18,9)uygulamalarımızdaki kripto para birimlerini desteklememiz gerekecek .

DECIMAL(18,9)MySQL'de 12 bayt yer kaplar ( 9 basamak başına 4 bayt ).


> Bir bitcoin 8 ondalık basamağa bölünebilir. Bu nedenle, 0.00000001 BTC, bir işlemde ele alınabilecek en küçük miktardır. Sanırım 9 yerine 8 mi demek istiyorsun?
danger89

1
Biliyorum, ancak 9 aynı disk alanını 8 alıyor. MySQL dokümanlarından: "DECIMAL sütun değerleri, dokuz ondalık basamağı 4 bayta paketleyen bir ikili format kullanılarak saklanır"
bizwiz

Üzgünüm, şimdi anladım. Teşekkürler.
danger89

2

BIGINTDaha az depolama alanı kullanma nedeni ile 100 veya daha fazla ile para depolamak tüm "normal" durumlarda mantıklı değildir.

  • GAAP ile uyumlu kalmak için para birimlerini depolamak yeterlidir DECIMAL(13,4)
  • MySQL kılavuzu, saklamak için 9 basamak başına 4 bayta ihtiyaç duyduğunu okur DECIMAL.
  • DECIMAL(13,4) 9 basamağı + 4 kesir basamağını temsil eder (ondalık basamaklar) => 4 + 2 bayt = 6 bayt
  • saklamak için gerekli 8 bayt ile karşılaştırın BIGINT.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.