ประเภทข้อมูลที่ดีที่สุดสำหรับเก็บค่าเงินใน MySQL


279

ฉันต้องการเก็บบันทึกจำนวนมากในฐานข้อมูล MySQL พวกเขาทั้งหมดมีค่าเงิน แต่ฉันไม่ทราบว่าจะใส่ตัวเลขจำนวนเท่าใดในแต่ละอัน
ฉันต้องใช้ข้อมูลชนิดใดเพื่อจุดประสงค์นี้
VARCHARหรือINT (หรือชนิดข้อมูลตัวเลขอื่น ๆ )?


13
deimal(10,2)คือสิ่งที่ฉันใช้ ... คุณสามารถปรับค่าได้ตามขนาดที่คาดหวัง
Manse

คำตอบ:


370

floatเนื่องจากเงินต้องการแสดงที่แน่นอนไม่ได้ใช้ชนิดข้อมูลที่มีเฉพาะตัวอย่างเช่น คุณสามารถใช้ชนิดข้อมูลตัวเลขคงที่สำหรับสิ่งนั้นได้

decimal(15,2)
  • 15 คือความแม่นยำ (ความยาวทั้งหมดของค่ารวมถึงตำแหน่งทศนิยม)
  • 2 คือจำนวนหลักหลังจุดทศนิยม

ดูประเภท MySQL ตัวเลข :

ประเภทเหล่านี้จะใช้เมื่อมีความสำคัญในการรักษาความแม่นยำที่แน่นอนเช่นกับข้อมูลทางการเงิน


3
อะไรคือความแตกต่างระหว่างชนิดข้อมูลทศนิยมและตัวเลขสำหรับกรณีนี้
Emilio Gort

60
ใน MySQL decimalและnumericเหมือนกัน
juergen d

21
ฉันเองใช้numeric(19,4)สำหรับบันทึกทางการเงินที่ให้มือที่ดีกว่าในการเล่นและรับคำขอใหม่ได้อย่างง่ายดาย
YahyaE

10
ฉันเห็นด้วยกับ YahyaE ทศนิยมมากกว่าดีกว่า มีบางสกุลเงินที่มักใช้ทศนิยม 3 ตำแหน่งเช่นบานาดีจอร์แดนหรือคูเวตคูเวตดังนั้นคุณต้องมีอย่างน้อย 3 สี่หรือห้าจะดีกว่า
Edwin Hoogerbeets

1
@EdwinHoogerbeets ไม่ได้เป็นนักบัญชี ... แต่ใช้ biz ขนาดเล็กในสหราชอาณาจักร ... ฉันจำได้ว่าอ่านมานานแล้วว่าตัวเลขสกุลเงินควรถูกเก็บไว้ที่ 4 ทศนิยมแม้กระทั่งสำหรับ£, $, ฯลฯ เพื่อให้การคำนวณบางอย่างอาจ จริงใช้ล่าสุด 2 ตำแหน่งทศนิยมสำหรับบริบทบัญชีปิดบังบางอย่าง จำเป็นต้องมีบัญชีเพื่อยืนยัน / ปฏิเสธ
ไมค์หนู

88

คุณสามารถใช้DECIMALหรือNUMERICทั้งสองเหมือนกัน

ประเภท DECIMAL และ NUMERIC จะเก็บค่าตัวเลขที่แน่นอน ประเภทเหล่านี้จะใช้เมื่อมีความสำคัญในการรักษาความแม่นยำที่แน่นอนเช่นกับข้อมูลทางการเงิน ใน MySQL มีการใช้ NUMERIC เป็น DECIMAL ดังนั้นหมายเหตุเกี่ยวกับ DECIMAL ต่อไปนี้จะใช้กับ NUMERIC อย่างเท่าเทียมกัน : MySQL

กล่าวคือ DECIMAL(10,2)

ตัวอย่างการตั้งค่า

อ่านดี


3
อาจทำให้เกิดความสับสน แต่ภาพหน้าจอของคุณไม่ตรงกับข้อความคำตอบของคุณ (ความแม่นยำขนาด)
Patrick Hofman

ฉันใช้ทศนิยม (10,2) สำหรับค่าเงินของฉัน แต่เมื่อฉันใส่อะไรเช่น 867,000.00 มันจะได้รับการบันทึกเป็น 867 ฉันทำอะไรผิด
codeinprogress

32

ฉันชอบที่จะใช้BIGINTและเก็บค่าโดยคูณด้วย 100เพื่อให้มันกลายเป็นจำนวนเต็ม

สำหรับตัวอย่างเช่นเพื่อแสดงค่าสกุลเงินของ93.49ค่าจะถูกเก็บไว้เป็น9349ในขณะที่แสดงค่าที่เราสามารถหารด้วย 100และแสดง สิ่งนี้จะใช้พื้นที่เก็บข้อมูลน้อยกว่า

ข้อควรระวัง:
ส่วนใหญ่เราจะไม่ทำการcurrency * currencyคูณในกรณีที่เราทำมันแล้วหารผลลัพธ์ด้วย 100 และเก็บเพื่อให้มันกลับไปสู่ความแม่นยำที่เหมาะสม


ฉันจำได้ว่าได้รับการบอกเล่าสิ่งที่คล้ายกันโดยอาจารย์ในหลักสูตรระบบมหาวิทยาลัยของฉัน ฉันได้รับการสอนวิธีการที่แม่นยำที่สุดคือการจัดเก็บเป็นเพนนี (หรือเซ็นต์) โดยคูณด้วย 100 และบันทึกเป็นจำนวนเต็มและหารด้วย 100 เพื่อแสดงให้ผู้ใช้เห็น ฉันเดาว่านี่มีประโยชน์ในแง่ของความแม่นยำและประสิทธิภาพของระบบฐานข้อมูล
LondonAppDev

11
อะไรคือข้อได้เปรียบมากกว่าDECIMAL? คุณสร้างความต้องการในการแปลเพนนีเป็นดอลลาร์และความฉิบหายถ้าคุณลืมมันในบางจุด

1
Space เป็นข้อได้เปรียบเพียงอย่างเดียว แต่ใช่เราต้องระวังให้มากขึ้นเมื่อใช้คุณสมบัตินี้
Dinesh PR

4
ในกรณีที่ไม่ชัดเจน: ระวังการใช้วิธีการกำจัดตะกรันหากคุณเก็บเงินไว้ในรูปเศษส่วน (เช่น$0.005หรือ$0.12345) เพราะจะไม่ลดลงเป็นจำนวนเต็มหลังจากคูณด้วย 100 ถ้าคุณทราบความแม่นยำของค่าที่ชัดเจน DECIMALตัวเลือกที่ดีที่สุดคือการใช้งาน แต่ถ้าคุณไม่รู้ความแม่นยำ (เหมือนในตัวอย่างของฉัน) แล้ว…จะFLOATเหมาะสมไหม
Quinn Comendant

1
ข้อดีของวิธีนี้เกิดขึ้นเมื่อใช้ภาษาเช่น JavaScript ที่ใช้ IEEE-754 เพื่อเก็บหมายเลขทศนิยม ข้อกำหนดนี้ไม่รับประกันว่า 0.1 + 0.2 === 0.3 เป็นจริง การจัดเก็บสกุลเงินเป็นจำนวนเต็มจะทำให้มั่นใจได้ว่าแอปพลิเคชันของคุณจะไม่เกิดข้อผิดพลาดประเภทนั้น นี่อาจไม่ใช่ทางออกที่ดีที่สุด ฉันมาที่หน้านี้ในขณะที่ทำการค้นคว้าวิธีแก้ปัญหาและยังไม่เสร็จ
Gary Ott

27

ขึ้นอยู่กับความต้องการของคุณ

การใช้DECIMAL(10,2)มักจะเพียงพอ แต่ถ้าคุณต้องการค่าที่แม่นยำกว่าเล็กน้อยคุณสามารถตั้งค่าDECIMAL(10,4)ได้

หากคุณทำงานกับค่าใหญ่แทนที่ด้วย1019


ฉันใช้ทศนิยม (10,2) สำหรับค่าเงินของฉัน แต่เมื่อฉันใส่อะไรเช่น 867,000.00 มันจะได้รับการบันทึกเป็น 867 ฉันทำอะไรผิด
codeinprogress

2
@codeinprogress ใช้ตัวคั่นตำแหน่ง / ทศนิยมผิดหรือไม่
David Balažic

15

หากแอปพลิเคชันของคุณต้องการจัดการกับค่าเงินสูงถึงล้านล้านสิ่งนี้ควรใช้: 13,2 ถ้าคุณจำเป็นต้องปฏิบัติตาม GAAP (หลักการบัญชีที่ยอมรับโดยทั่วไป) ให้ใช้: 13,4

โดยปกติคุณควรรวมมูลค่าเงินของคุณที่ 13,4 ก่อนที่จะปัดเศษผลลัพธ์เป็น 13,2


5
หากคุณกำลังจะใช้ Bitcoin คุณจะต้องมีทศนิยม 8 ตำแหน่งแม้ว่ากระเป๋าส่วนใหญ่จะไปที่ mBTC ซึ่งเป็น 3 en.wikipedia.org/wiki/Bitcoin
คริสเตียน

อย่าคิดว่าคำตอบนี้เป็นจริง opendata.stackexchange.com/a/10348/13983 @ david.ee มีแหล่งที่มาสำหรับสิ่งนั้นหรือไม่
Evan Carroll

@EvanCarroll ให้ฉันตอบ david.ee ฉันคิดว่าบทความนี้อาจเป็นแหล่งที่มาrietta.com/blog/2012/03/03/best-data-types-for-currencymoney-in
naXa

@naXa ลิงก์ไม่อ้างถึงสิ่งใดจากแหล่งใด ๆ ที่สนับสนุนการอ้างสิทธิ์ในการใช้ 13,4 สำหรับ GAAP สิ่งที่คุณทำคือการเชื่อมโยงไปยังบทความที่ทำให้การเรียกร้องพร้อมเพรียงเดียวกัน
iheanyi

6

อันที่จริงสิ่งนี้ขึ้นอยู่กับความชอบของโปรแกรมเมอร์ ผมเองใช้: numeric(15,4)เพื่อให้สอดคล้องกับหลักการบัญชีที่รับรอง ( GAAP )


5
มันไม่มีอะไรเกี่ยวข้องกับ "การตั้งค่าของโปรแกรมเมอร์" หรือสิ่งที่คุณใช้เป็นการส่วนตัว มันถูกกำหนดโดยโดเมนปัญหาซึ่งต้องมีฐานสิบทศนิยม นี่ไม่ใช่เรื่องที่โปรแกรมเมอร์จะใช้ความชอบส่วนตัวของเขาเอง
มาร์ควิสแห่ง Lorne

3

ลองใช้

Decimal(19,4)

สิ่งนี้มักจะใช้ได้กับฐานข้อมูลอื่น ๆ ด้วย


3

doubleเราใช้

* * * * * * * * หอบ

ทำไม?

เพราะมันสามารถเป็นตัวแทนใด ๆ จำนวน 15 หลักที่มีข้อ จำกัด ในการที่ไม่มีจุดทศนิยมคือ ทั้งหมดนี้มีขนาด 8 ไบต์!

ดังนั้นจึงสามารถเป็นตัวแทนของ:

  • 0.123456789012345
  • 123456789012345.0

... และทุกสิ่งในระหว่าง

สิ่งนี้มีประโยชน์เพราะเรากำลังเผชิญกับสกุลเงินทั่วโลกและdoubleสามารถเก็บจำนวนทศนิยมหลายตำแหน่งที่เราน่าจะพบ

doubleเขตข้อมูลเดียวสามารถแสดงถึง 999,999,999,999,999s ในเยนญี่ปุ่น, 9,999,999,999,999.99s ในสกุลเงินดอลลาร์สหรัฐและแม้กระทั่ง 9,999,999.99999999s ใน bitcoins

หากคุณลองทำเช่นเดียวกันdecimalคุณต้องมีdecimal(30, 15)ค่าใช้จ่าย 14 ไบต์

คำเตือน

แน่นอนว่าการใช้doubleไม่ได้โดยไม่มีคำเตือน

อย่างไรก็ตามมันไม่ได้สูญเสียความแม่นยำเนื่องจากบางคนมักจะชี้ให้เห็น แม้ว่าdoubleตัวของมันเองอาจจะไม่ถูกต้องภายในระบบ 10 ฐานแต่เราสามารถทำให้แน่นอนโดยการปัดค่าที่เราดึงจากฐานข้อมูลไปยังตำแหน่งทศนิยมที่มีนัยสำคัญ หากจำเป็นนั่นก็คือ (เช่นถ้ามันจะถูกส่งออกและจำเป็นต้องมีการแทนฐาน 10)

คำเตือนคือเมื่อใดก็ตามที่เราทำการคำนวณทางคณิตศาสตร์เราจำเป็นต้องทำให้ผลลัพธ์เป็นปกติ (โดยปัดเศษเป็นทศนิยมที่มีนัยสำคัญ) ก่อน:

  1. ทำการเปรียบเทียบกับมัน
  2. เขียนกลับไปที่ฐานข้อมูล

ชนิดของข้อแม้ก็คือแตกต่างจากdecimal(m, d)ที่ฐานข้อมูลจะป้องกันไม่ให้โปรแกรมจากการใส่หมายเลขที่มีมากกว่าตัวเลขที่ไม่มีการตรวจสอบดังกล่าวอยู่ด้วยm doubleโปรแกรมสามารถใส่ค่าที่ป้อนเข้าของผู้ใช้เป็นตัวเลข 20 หลักและท้ายที่สุดจะถูกบันทึกอย่างเงียบ ๆ ว่าเป็นจำนวนที่ไม่ถูกต้อง


ครั้งแรกที่ฉันเห็นคำตอบเช่นนี้น่าสนใจ ถาม: ถ้าฉันเขียน float เช่น 1.41 ไปยังฐานข้อมูลและด้วยเหตุผลบางอย่างฉันต้องคูณมันด้วยจำนวนมหาศาลใน mysql เช่น 1.000.000.000.000 ผลลัพธ์ที่ได้จะกลมมน: 1.410.000.000.000
roelleor

@roelleor เพื่อให้ได้ผลลัพธ์เท่ากับ 1,410,000,000,000 (เครื่องหมายจุลภาคเป็นตัวคั่นหลักพัน) อินพุตจะถือว่าเป็น1.410000000000(ทศนิยมสิบสองตำแหน่งที่มีนัยสำคัญ) แต่คูณด้วย 1,000,000,000,000 (ซึ่งเป็น 13 หลักสำคัญที่เหลือจุดทศนิยม) หมายความว่าเรากำลังทำงานด้วยที่ อย่างน้อย 25 หลักที่รวมกัน ไกลเกินกว่า 15 ที่มีอยู่สำหรับสองครั้งดังนั้นการออกแบบที่ชาญฉลาดฉันคิดว่ามันจะเสียมาก
antak

2

ในช่วงเวลาที่ถูกถามคำถามนี้ไม่มีใครคิดเกี่ยวกับราคา Bitcoin ในกรณีของ BTC DECIMAL(15,2)มันอาจจะไม่เพียงพอที่จะใช้งาน หาก Bitcoin จะเพิ่มขึ้นเป็น $ 100,000 หรือมากกว่านั้นเราจะต้องมีอย่างน้อยDECIMAL(18,9)เพื่อรองรับการเข้ารหัสลับในแอพของเรา

DECIMAL(18,9)ใช้พื้นที่ 12 ไบต์ใน MySQL ( 4 ไบต์ต่อ 9 หลัก )


> Bitcoin สามารถแบ่งออกเป็นทศนิยม 8 ตำแหน่ง ดังนั้น 0.00000001 BTC เป็นจำนวนเงินน้อยที่สุดที่สามารถจัดการได้ในการทำธุรกรรม ฉันคิดว่าคุณหมายถึง 8 แทน 9?
danger89

1
ฉันรู้ แต่ 9 ใช้พื้นที่ดิสก์เท่ากับ 8 จากเอกสารของ MySQL: "ค่าสำหรับคอลัมน์ DECIMAL จะถูกจัดเก็บโดยใช้รูปแบบไบนารีที่บรรจุทศนิยมเก้าหลักเป็น 4 ไบต์"
bizwiz

ขออภัยตอนนี้ฉันเข้าใจคุณแล้ว ขอบคุณ
danger89

2

การจัดเก็บเงินเป็นBIGINTทวีคูณ 100 หรือมากกว่าด้วยเหตุผลที่ใช้พื้นที่เก็บข้อมูลน้อยลงทำให้ไม่มีเหตุผลในทุกสถานการณ์ "ปกติ"

  • หากต้องการอยู่ในแนวเดียวกับ GAAP การเก็บสกุลเงินก็เพียงพอ DECIMAL(13,4)
  • คู่มือ MySQL อ่านที่ต้องการ 4 ไบต์ต่อ 9 DECIMALหลักในการจัดเก็บ
  • DECIMAL(13,4) แทนตัวเลข 9 หลัก + 4 หลัก (ตำแหน่งทศนิยม) => 4 + 2 ไบต์ = 6 ไบต์
  • เปรียบเทียบกับ 8 BIGINTไบต์จำเป็นต้องใช้ในการจัดเก็บ


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.