Jenis data terbaik untuk menyimpan nilai uang di MySQL

279

Saya ingin menyimpan banyak catatan dalam database MySQL. Semuanya mengandung nilai uang. Tapi saya tidak tahu berapa banyak digit yang akan dimasukkan untuk masing-masing.
Jenis data apa yang harus saya gunakan untuk tujuan ini?
VARCHAR atau INT (atau tipe data numerik lainnya)?

Mohammad Saberi
sumber
13
deimal(10,2)adalah apa yang saya gunakan ... Anda dapat menyesuaikan nilai tergantung pada ukuran yang diharapkan
Pastori
9
Pertanyaan terkait adalah Jenis Data Terbaik untuk Mata Uang ;).
shA.t

Jawaban:

370

Karena uang memerlukan representasi yang tepat, jangan gunakan tipe data yang hanya perkiraan saja float. Anda dapat menggunakan tipe data angka titik tetap untuk yang seperti itu

decimal(15,2)
  • 15 adalah presisi (total panjang nilai termasuk tempat desimal)
  • 2 adalah jumlah digit setelah titik desimal

Lihat Jenis Numerik MySQL :

Jenis-jenis ini digunakan ketika penting untuk menjaga presisi yang tepat, misalnya dengan data moneter .

juergen d
sumber
3
apa yang bisa menjadi perbedaan antara tipe data desimal dan numerik untuk kasus ini?
Emilio Gort
60
Di MySQL decimaldan numericsama.
juergen d
21
Saya pribadi menggunakan numeric(19,4)untuk catatan keuangan yang memberi Anda tangan yang lebih baik untuk bermain dan mengadopsi permintaan baru dengan mudah.
YahyaE
10
Saya setuju dengan YahyaE, lebih banyak desimal lebih baik. Ada beberapa mata uang yang biasanya menggunakan 3 tempat desimal, seperti Bahrain, Yordania, atau Kuwait Dinars, sehingga Anda membutuhkan setidaknya 3. Empat atau lima lebih baik.
Edwin Hoogerbeets
1
@ EdwinHoogerbeets Bukan menjadi seorang akuntan ... tetapi menjalankan bisnis kecil di Inggris ... Saya ingat pernah membaca di suatu tempat dahulu bahwa angka mata uang harus disimpan ke 4 desimal bahkan untuk £, $, dll. Sehingga perhitungan tertentu mungkin sebenarnya menggunakan 2 tempat desimal terakhir untuk konteks akuntansi tertentu yang tidak jelas. Kami membutuhkan akuntan untuk mengonfirmasi / membantah.
mike rodent
88

Anda bisa menggunakan DECIMALatau NUMERICkeduanya sama

Jenis DECIMAL dan NUMERIC menyimpan nilai data numerik yang tepat. Jenis-jenis ini digunakan ketika penting untuk menjaga presisi yang tepat, misalnya dengan data moneter. Di MySQL, NUMERIC diimplementasikan sebagai DECIMAL, jadi pernyataan berikut tentang DECIMAL berlaku sama untuk NUMERIC. : MySQL

yaitu DECIMAL(10,2)

Pengaturan contoh

Baca bagus

NullPoiиteя
sumber
3
Mungkin membingungkan, tetapi tangkapan layar Anda tidak cocok dengan teks jawaban Anda (presisi, skala).
Patrick Hofman
Saya menggunakan desimal (10,2) untuk nilai uang saya, namun ketika saya meletakkan sesuatu seperti 867.000,00 akan disimpan sebagai 867. apa yang saya lakukan salah?
Kemajuan kode
32

Saya lebih suka menggunakan BIGINT, dan menyimpan nilai-nilai dengan mengalikan dengan 100 , sehingga akan menjadi bilangan bulat.

Untuk misalnya, untuk mewakili nilai mata uang 93.49, nilai tersebut akan disimpan sebagai 9349, sambil menampilkan nilai yang dapat kita bagi dengan 100 dan ditampilkan. Ini akan menempati lebih sedikit ruang penyimpanan.

Perhatian:
Sebagian besar kita tidak melakukan currency * currencyperkalian, jika kita melakukannya maka bagi hasil dengan 100 dan simpan, sehingga kembali ke presisi yang tepat.

Dinesh PR
sumber
Saya ingat diberitahu hal yang sama oleh seorang profesor pada kursus universitas Sistem Komputer saya. Saya diajari cara yang paling tepat adalah menyimpan dalam uang (atau sen) dengan mengalikan dengan 100 dan menyimpan sebagai Integer dan membaginya dengan 100 untuk menampilkannya kepada pengguna. Saya kira ini memiliki manfaat dalam hal akurasi dan kinerja sistem basis data.
LondonAppDev
11
Apa kelebihannya DECIMAL? Anda perlu menerjemahkan uang menjadi dolar, dan celakalah jika Anda melupakannya di beberapa titik.
1
Ruang adalah satu-satunya keuntungan, tapi ya kita harus lebih berhati-hati saat menggunakan fitur ini.
Dinesh PR
4
Jika tidak jelas: berhati-hatilah menggunakan metode penghilangan skala jika Anda menyimpan uang dalam pecahan sen (misalnya, $0.005atau $0.12345) karena mereka tidak akan berkurang menjadi bilangan bulat setelah dikalikan dengan 100. Jika Anda tahu ketepatan nilai-nilai itu jelas Pilihan terbaik adalah menggunakan DECIMAL. Tetapi jika Anda tidak tahu ketepatan (seperti dalam contoh saya) maka ... akankah FLOATsesuai?
Quinn Comendant
1
Keuntungan dari metode ini datang ketika menggunakan bahasa seperti JavaScript yang menggunakan IEEE-754 untuk menyimpan angka floating point. Spesifikasi ini tidak menjamin bahwa 0,1 + 0,2 === 0,3 benar. Menyimpan mata uang sebagai bilangan bulat memberikan kepastian bahwa aplikasi Anda tidak akan menimbulkan kesalahan semacam itu. Ini mungkin bukan solusi terbaik. Saya tiba di halaman ini ketika mencari solusi dan saya belum selesai.
Gary Ott
27

Tergantung kebutuhan Anda.

Menggunakan DECIMAL(10,2)biasanya sudah cukup tetapi jika Anda membutuhkan nilai yang lebih tepat Anda dapat mengatur DECIMAL(10,4).

Jika Anda bekerja dengan nilai besar gantikan 10dengan 19.

Svetoslav
sumber
Saya menggunakan desimal (10,2) untuk nilai uang saya, namun ketika saya meletakkan sesuatu seperti 867.000,00 akan disimpan sebagai 867. apa yang saya lakukan salah?
Kemajuan kode
2
@codeinprogress Menggunakan pemisah lokal / desimal yang salah?
David Balažic
15

Jika aplikasi Anda perlu menangani nilai uang hingga satu triliun maka ini harus bekerja: 13,2 Jika Anda harus mematuhi GAAP (Prinsip Akuntansi yang Diterima Secara Umum) maka gunakan: 13,4

Biasanya Anda harus menjumlahkan nilai uang Anda pada 13,4 sebelum pembulatan output menjadi 13,2.

david.ee
sumber
5
Jika Anda ingin mengambil Bitcoin, Anda akan membutuhkan 8 tempat desimal, meskipun sebagian besar dompet masuk ke mBTC yaitu 3 en.wikipedia.org/wiki/Bitcoin
Christian
Jangan berpikir jawaban ini benar. opendata.stackexchange.com/a/10348/13983 @ david.ee punya sumber untuk itu?
Evan Carroll
@ EvanCarroll izinkan saya menjawab untuk david.ee. Saya pikir artikel ini dapat menjadi sumber rietta.com/blog/2012/03/03/best-data-types-for-currencymoney-in
naXa
@naXa tautan tidak mengutip apa pun dari sumber mana pun yang mendukung klaim menggunakan 13,4 untuk GAAP. Yang Anda lakukan hanyalah tautan ke artikel yang membuat klaim tidak berdasar yang sama.
iheanyi
6

Memang ini bergantung pada preferensi programmer. Saya pribadi menggunakan: numeric(15,4)untuk mematuhi Prinsip Akuntansi yang Diterima Secara Umum ( GAAP ) .

Chagbert
sumber
5
Ini tidak ada hubungannya dengan "preferensi programmer" atau apa yang Anda 'gunakan secara pribadi'. Itu ditentukan oleh domain masalah, yang membutuhkan radix desimal. Ini bukan masalah di mana programmer dapat menggunakan preferensi pribadinya sendiri.
Marquis of Lorne
3

Coba gunakan

Decimal(19,4)

ini biasanya bekerja dengan setiap DB lainnya juga

Deepesh
sumber
3

Kami menggunakan double.

* terkesiap *

Mengapa?

Karena itu dapat mewakili angka 15 digit tanpa kendala di mana titik desimal berada . Semua untuk 8 byte sangat sedikit!

Jadi itu bisa mewakili:

  • 0.123456789012345
  • 123456789012345.0

... dan apa pun di antaranya.

Ini berguna karena kita sedang berhadapan dengan mata uang global , dandouble dapat menyimpan berbagai jumlah tempat desimal yang kemungkinan akan kita temui.

Satu doublebidang tunggal dapat mewakili 999.999.999.999.999dalam yen Jepang, 9.999.999.999.999,999dalam dolar AS dan bahkan 9999.999.999.99999999dalam bitcoin

Jika Anda mencoba melakukan hal yang sama dengan decimal, Anda perludecimal(30, 15) biaya 14 byte.

Peringatan

Tentu saja menggunakan double bukan tanpa peringatan.

Namun, ini bukan kehilangan keakuratan karena beberapa cenderung menunjukkan. Meskipun doubleitu sendiri mungkin tidak tepat secara internal ke sistem basis 10 , kita dapat membuatnya tepat dengan membulatkan nilainya kita tarik dari basis data ke tempat desimalnya yang signifikan. Jika perlu itu. (mis. Jika itu akan dikeluarkan, dan representasi basis 10 diperlukan.)

Peringatannya adalah, setiap kali kita melakukan aritmatika dengannya, kita perlu menormalkan hasilnya (dengan membulatkannya ke tempat desimal yang signifikan) sebelum:

  1. Melakukan perbandingan di atasnya.
  2. Menulisnya kembali ke database.

Peringatan jenis lain adalah, tidak seperti di decimal(m, d)mana basis data akan mencegah program memasukkan angka dengan lebih dari mdigit, tidak ada validasi seperti itu double. Suatu program dapat memasukkan nilai yang dimasukkan pengguna sebesar 20 digit dan akhirnya akan dicatat secara diam-diam sebagai jumlah yang tidak akurat.

antak
sumber
Pertama kali saya melihat jawaban seperti ini, menarik. T: Jika saya menulis float seperti 1,41 ke database dan untuk beberapa alasan saya perlu mengalikannya dengan sejumlah besar di mysql, seperti 1.000.000.000.000. Apakah hasil yang dibulatkan tepat menjadi: 1.410.000.000.000?
roelleor
@roelleor Agar hasilnya tepat 1.410.000.000.000 (koma sebagai pemisah ribuan) input diasumsikan 1.410000000000(dua belas tempat desimal yang signifikan), tetapi mengalikannya dengan 1.000.000.000.000 (yang merupakan 13 digit signifikan dari titik desimal) berarti kita bekerja dengan di Setidaknya gabungan 25 digit. Sejauh ini jauh melampaui 15 tersedia untuk ganda, jadi desain-bijaksana saya pikir itu akan sangat rusak.
antak
2

Pada saat pertanyaan ini ditanyakan, tidak ada yang memikirkan harga Bitcoin. Dalam kasus BTC, mungkin tidak cukup untuk digunakan DECIMAL(15,2). Jika Bitcoin akan naik menjadi $ 100.000 atau lebih, kita akan memerlukan setidaknya DECIMAL(18,9)untuk mendukung cryptocurrency di aplikasi kita.

DECIMAL(18,9)membutuhkan 12 byte ruang di MySQL ( 4 byte per 9 digit ).

bizwiz
sumber
> Bitcoin dapat dibagi menjadi 8 desimal. Oleh karena itu, 0,00000001 BTC adalah jumlah terkecil yang dapat ditangani dalam transaksi. Saya pikir maksud Anda 8 bukannya 9?
hazard89
1
Saya tahu, tetapi 9 membutuhkan ruang disk yang sama dengan 8. Dari dokumen MySQL: "Nilai untuk kolom DECIMAL disimpan menggunakan format biner yang mengemas sembilan angka desimal menjadi 4 byte"
bizwiz
Ow maaf, sekarang saya mengerti. Terima kasih.
hazard89
2

Menyimpan uang BIGINTdikalikan 100 atau lebih dengan alasan untuk menggunakan ruang penyimpanan lebih sedikit tidak masuk akal dalam semua situasi "normal".

digitalstraw
sumber