Jenis data terbaik untuk menyimpan nilai mata uang dalam database MySQL

Jawaban:

227

Sesuatu seperti Decimal(19,4)biasanya bekerja dengan cukup baik dalam banyak kasus. Anda dapat menyesuaikan skala dan presisi agar sesuai dengan kebutuhan angka yang perlu Anda simpan. Bahkan dalam SQL Server, saya cenderung tidak menggunakan " money" karena tidak standar.

Kibbee
sumber
52
Poin tentang ukuran: menurut MSDN ( msdn.microsoft.com/en-us/library/ms187746.aspx ), Desimal (10,4) dan Desimal (19,4) keduanya menggunakan penyimpanan 9 byte, jadi mungkin juga baik musim semi untuk tambahan 9 digit skala.
Adam Nofsinger
1
Artikel MSDN adalah tentang SQL Server tetapi pertanyaannya adalah tentang MySQL. (Saya telah bertemu pengembang yang berpikir keduanya sama sehingga yang terbaik harus jelas.)
cja
5
Apa manfaatnya (19,4)daripada menggunakan (19,2)?
ryvantage
1
Manfaat saya adalah ini .. Saya membutuhkan semua baris meja saya untuk menyamai jumlah uang tertentu. Katakanlah jumlahnya adalah $ 10,00. Saat baris baru ditambahkan, setiap perubahan jumlah baris. Jika ada 3 baris dalam tabel. 10/3 = 3.3333333333 ... tetapi dengan hanya 2 desimal mereka disimpan sebagai 3.33. Jadi, ketika Anda menjumlahkannya, 3,33 + 3,33 + 3,33 = 9,99. Kami kehilangan satu sen! Lebih buruk lagi pada dataset yang lebih besar. Simpan di 19,4 dan jumlahkan total Anda, kemudian bulatkan hasilnya menjadi 19,2 ..
Rick
49

Satu-satunya hal yang harus Anda perhatikan adalah jika Anda bermigrasi dari satu basis data ke basis data lain, Anda mungkin menemukan bahwa DECIMAL (19,4) dan DECIMAL (19,4) memiliki arti yang berbeda

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

    DBASE: 10,5 (10 integer, 5 desimal)
    MYSQL: 15,5 (15 digit, 10 integer (15-5), 5 desimal)
SeanJA
sumber
Sayangnya, tautannya sudah mati.
Marco Aurélio Deleu
1
@ MarcoAurélioDeleu - Saya telah mengubah tautan untuk menunjuk ke halaman di Mesin Wayback, sehingga Anda dapat melihatnya seperti tampak pada tahun 2009.
Tony
17

Penting juga untuk menentukan berapa banyak tempat desimal yang mungkin diperlukan untuk perhitungan Anda.

Saya mengerjakan aplikasi harga saham yang membutuhkan perhitungan harga satu juta saham. Harga saham yang dikutip harus disimpan hingga 7 digit akurasi.

Leah
sumber
7
Ini poin yang bagus - terutama di aplikasi keuangan, "harga" pasti tidak menyiratkan "uang"
Mike Woodhouse
17

Tanggapan Assaf dari

Tergantung pada berapa banyak uang yang Anda dapatkan ...

kedengarannya kurang ajar, tapi sebenarnya itu penting.

Hanya hari ini kami mengalami masalah ketika catatan gagal dimasukkan ke dalam tabel Rate kami, karena salah satu kolom (GrossRate) disetel ke Desimal (11,4), dan departemen Produk kami baru saja mendapatkan kontrak untuk kamar di beberapa resor yang menakjubkan di Bora Bora, yang dijual seharga beberapa juta Francs Pasifik per malam ... sesuatu yang tidak pernah diantisipasi ketika skema basis data dirancang 10 tahun lalu.

Scott Ferguson
sumber
2
Itulah sebabnya saya merekomendasikan desimal (19,4). Mungkin terdengar seperti berlebihan, tetapi Anda tidak pernah tahu kapan Anda harus menyimpan jumlah yang sangat besar di bidang itu.
Kibbee
2
@ Sibbee: Saya tidak akan setuju dengan Anda untuk persyaratan kami sampai hari ini. (Selama 6 tahun (11,4) baik-baik saja ...)
Scott Ferguson
@ Kibbee Kedengarannya seperti meme 640 Kb :)
Nikita Bosik
13

Untuk aplikasi akuntansi, sangat umum untuk menyimpan nilai-nilai sebagai bilangan bulat (beberapa bahkan mengatakan bahwa itu satu - satunya cara). Untuk mendapatkan ide, ambil jumlah transaksi (misalkan $ 100,23) dan gandakan dengan 100, 1000, 10000, dll. Untuk mendapatkan akurasi yang Anda butuhkan. Jadi, jika Anda hanya perlu menyimpan sen dan dapat dengan aman mengumpulkan atau menurunkan, cukup kalikan dengan 100. Dalam contoh saya, itu akan membuat 10023 sebagai bilangan bulat untuk disimpan. Anda akan menghemat ruang dalam basis data dan membandingkan dua bilangan bulat jauh lebih mudah daripada membandingkan dua pelampung. $ 0,02 saya

Dane Bendixen
sumber
Bagaimana Anda menyimpan 6.125 (6 1/8)?
PeterToTheThird
Saya kira dia akan menyimpannya sebagai bilangan bulat 6125.
Jimmy Knoot
2
Bagaimana ini akan lebih baik daripada DECIMAL? Anda harus sangat berhati-hati untuk selalu menerjemahkan uang, pabrik, atau millrays ke dalam dolar, pada waktu yang tepat.
Saya telah membaca bahwa kinerja biasanya lebih cepat dengan INT daripada DECIMAL, bahkan di versi terbaru MySQL. Ini juga lebih mudah ketika Anda perlu membawa nilai-nilai ini ke dalam PHP atau sesuatu dan membandingkan nilai-nilai.
Dane Bendixen
9

entri super terlambat tapi GAAP adalah aturan praktis yang baik ..

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.

Sumber: Jenis data terbaik untuk menyimpan nilai moneter dalam MySQL

Damian
sumber
5

Anda dapat menggunakan sesuatu seperti DECIMAL(19,2)secara default untuk semua nilai moneter Anda, tetapi jika Anda hanya akan menyimpan nilai lebih rendah dari $ 1.000, itu hanya akan membuang-buang ruang database yang berharga.

Untuk sebagian besar implementasi, DECIMAL(N,2)akan cukup, di mana nilai Nsetidaknya jumlah digit sebelum .jumlah terbesar yang Anda harapkan untuk disimpan di bidang itu + 5. Jadi, jika Anda tidak pernah berharap untuk menyimpan nilai lebih dari 999999,99, DECIMAL(11,2)harus lebih dari cukup (sampai harapan berubah).

Jika Anda ingin patuh pada GAAP , Anda bisa menggunakannya DECIMAL(N,4), di mana nilainya Nadalah setidaknya jumlah digit sebelum .jumlah terbesar yang Anda harapkan disimpan di bidang itu + 7.

John Slegers
sumber
3

Itu tergantung pada sifat data. Anda harus merenungkannya terlebih dahulu.

Kasus saya

  • desimal (13,4) yang tidak ditandatangani untuk mencatat transaksi uang
    • penyimpanan efisien (4 byte untuk setiap sisi titik desimal) 1
    • Sesuai GAAP
  • desimal (19,4) tidak ditandatangani untuk agregat
    • kita membutuhkan lebih banyak ruang untuk total beberapa transaksi multi-miliar
    • semi-kepatuhan dengan tipe data MS Currency tidak akan merugikan 2
    • ini akan membutuhkan lebih banyak ruang per catatan (11 byte - 7 kiri & 4 kanan), tapi ini bagus karena ada lebih sedikit catatan untuk agregat 1
  • desimal (10,5) untuk nilai tukar
    • mereka biasanya dikutip dengan 5 digit sama sekali sehingga Anda bisa menemukan nilai-nilai seperti 1.2345 & 12.345 tetapi tidak 12345.67890
    • ini adalah konvensi yang tersebar luas, tetapi bukan standar yang dikodifikasikan (setidaknya untuk pengetahuan pencarian cepat saya)
    • Anda bisa membuatnya desimal (18,9) dengan penyimpanan yang sama, tetapi batasan datatype adalah mekanisme validasi bawaan yang berharga

Kenapa (M, 4)?

  • ada mata uang yang terbagi menjadi seribu uang
  • ada setara uang seperti "Unidad de Fermento", "CLF" dinyatakan dengan 4 tempat desimal yang signifikan 3 , 4
  • ini sesuai dengan GAAP

Pengorbanan

  • presisi yang lebih rendah:
    • lebih sedikit biaya penyimpanan
    • perhitungan lebih cepat
    • risiko kesalahan perhitungan yang lebih rendah
    • backup & restore lebih cepat
  • presisi yang lebih tinggi:
    • kompatibilitas di masa depan (jumlahnya cenderung bertambah)
    • hemat waktu pengembangan (Anda tidak perlu membangun kembali setengah sistem ketika batasnya dipenuhi)
    • risiko kegagalan produksi yang lebih rendah karena presisi penyimpanan yang tidak memadai

Ekstrim kompatibel

Meskipun MySQL memungkinkan Anda menggunakan desimal (65,30), 31 untuk skala dan 30 untuk presisi tampaknya menjadi batasan kami jika kami ingin membiarkan opsi transfer terbuka.

Skala dan presisi maksimum dalam RDBMS paling umum:

            Skala presisi
Oracle 31 31
T-SQL 38 38
MySQL 65 30
PostgreSQL 131072 16383

6 , 7 , 8 , 9

Ekstrim yang Wajar

  1. Kenapa (27,4)?
    • Anda tidak pernah tahu kapan sistem perlu menyimpan dolar Zimbabwe

September 2015 Pemerintah Zimbabwe menyatakan akan menukar dolar Zimbabwe dengan dolar AS pada tingkat 1 USD hingga 35 kuadriliun dolar Zimbabwe 5

Kita cenderung mengatakan "ya, tentu ... saya tidak akan membutuhkan angka gila". Yah, orang Zimbabwe dulu juga mengatakan itu. Belum lama ini.

Bayangkan Anda perlu mencatat transaksi 1 juta USD dalam dolar Zimbabwe (mungkin tidak hari ini, tetapi siapa yang tahu bagaimana ini akan terlihat dalam 10 tahun dari sekarang?).

  1. (1 juta USD) * (35 Quadrylion ZWL) = (10 ^ 6) * (35 * 10 ^ 15) = 35 * 10 ^ 21
  2. kita butuh:
    • 2 digit untuk menyimpan "35"
    • 21 digit untuk menyimpan angka nol
    • 4 digit di sebelah kanan titik desimal
  3. ini membuat desimal (27,4) yang harganya 15 byte untuk setiap entri
  4. kita dapat menambahkan satu digit lagi di sebelah kiri tanpa biaya - kita memiliki desimal (28,4) selama 15 byte
  5. Sekarang kita dapat menyimpan 10 juta transaksi USD yang dinyatakan dalam dolar Zimbabwe, atau aman dari serangan hiperinflasi lain, yang diharapkan tidak akan terjadi
kshishkin
sumber
0

Meskipun ini mungkin terlambat, tetapi akan membantu orang lain. Dari pengalaman dan penelitian saya, saya menjadi tahu dan menerima desimal (19, 6). Itulah saat bekerja dengan php dan mysql. ketika bekerja dengan sejumlah besar uang dan nilai tukar

berharga
sumber