ความแตกต่างระหว่างตัวเลขทศนิยมและทศนิยมใน SQL Server


322

อะไรคือความแตกต่างระหว่างnumeric, floatและdecimalประเภทข้อมูลและที่ควรจะใช้ในสถานการณ์ที่?

สำหรับธุรกรรมทางการเงินใด ๆ (เช่นสำหรับฟิลด์เงินเดือน) รายการใดที่ต้องการและทำไม


1
การเชื่อมโยงทศนิยมและตัวเลขดังกล่าวข้างต้นความต้องการปรับปรุงdocs.microsoft.com/en-us/sql/t-sql/data-types/... ลิงก์ข้างต้นไม่มีอยู่อีกต่อไป
Nigel Ainscoe

1
โดยปกติแล้วเมื่อต้องรับมือกับวิชาทางการเงินที่น่าสนใจในการทำงานร่วมกับจำนวนเต็มประเภทนอกเหนือจากจุดลอยตัวคนและเก็บค่าเป็นเซนต์แทนดอลลาร์เช่น
เปโดร

คำตอบ:


494

ใช้ชนิดข้อมูลลอยหรือข้อมูลจริงก็ต่อเมื่อความแม่นยำที่กำหนดโดยทศนิยม (สูงสุด 38 หลัก) ไม่เพียงพอ

  • ชนิดข้อมูลตัวเลขโดยประมาณไม่เก็บค่าที่แน่นอนที่ระบุไว้สำหรับตัวเลขจำนวนมาก พวกมันเก็บค่าประมาณที่ใกล้เคียงที่สุดไว้อย่างมาก ( Technet )

  • หลีกเลี่ยงการใช้ลอยจริงหรือคอลัมน์ใน WHERE เงื่อนไขการค้นหาข้อโดยเฉพาะอย่างยิ่ง = และ <> ผู้ประกอบการ ( เปอเรเตอร์ )

ดังนั้นโดยทั่วไปเนื่องจากความแม่นยำที่กำหนดโดยทศนิยมคือ [10E38 ~ 38 หลัก] หากหมายเลขของคุณสามารถใส่ได้และพื้นที่เก็บข้อมูลที่มีขนาดเล็กลง (และอาจเร็ว) ของ Float ไม่สำคัญและจัดการกับพฤติกรรมที่ผิดปกติและปัญหาของประเภทตัวเลขโดยประมาณ ยอมรับใช้ทศนิยมทั่วไป

ข้อมูลที่เป็นประโยชน์มากขึ้น

  • numeric = decimal (5 ถึง 17 ไบต์) ( ชนิดข้อมูลตัวเลขที่แน่นอน )
    • จะจับคู่กับทศนิยมใน. NET
    • ทั้งสองมี (18, 0) เป็นพารามิเตอร์เริ่มต้น (ความแม่นยำขนาด) ในเซิร์ฟเวอร์ SQL
    • สเกล = จำนวนสูงสุดของตัวเลขทศนิยมที่สามารถเก็บไว้ทางด้านขวาของจุดทศนิยม
    • โปรดทราบว่าเงิน (8 ไบต์) และ smallmoney (4 ไบต์) เป็นที่แน่นอนและแมปไปยังทศนิยมใน. NET และมีทศนิยม 4 ตำแหน่ง ( MSDN )
    • ทศนิยมและตัวเลข (Transact-SQL) - MSDN
  • จริง (4 ไบต์) ( ชนิดข้อมูลตัวเลขโดยประมาณ )
  • ลอย (8 ไบต์) ( ชนิดข้อมูลตัวเลขโดยประมาณ )
    • จะแมปกับ Double ใน. NET
  • ชนิดตัวเลขที่แน่นอนทุกชนิดให้ผลลัพธ์เหมือนกันเสมอไม่ว่าจะใช้สถาปัตยกรรมโปรเซสเซอร์ประเภทใดหรือขนาดของตัวเลข
  • พารามิเตอร์ที่ให้มาเป็นข้อมูลชนิดลอยกำหนดจำนวนบิตที่ใช้ในการจัดเก็บmantissaของจำนวนจุดลอยตัว
  • ชนิดข้อมูลตัวเลขโดยประมาณมักใช้พื้นที่เก็บข้อมูลน้อยกว่าและมีความเร็วที่ดีขึ้น (มากถึง 20x) และคุณควรพิจารณาเมื่อมีการแปลงใน. NET

ชนิดข้อมูลตัวเลขที่แน่นอน ชนิดข้อมูลตัวเลขโดยประมาณ

แหล่งที่มาหลัก : ชุดการฝึกอบรม Self-Paced MCTS (ตรวจสอบ 70-433): การพัฒนาฐานข้อมูลMicrosoft® SQL Server® 2008 - บทที่ 3 - ตารางประเภทข้อมูลและบทเรียนความสมบูรณ์ของการเปิดเผยข้อมูลบทที่ 1 - การเลือกประเภทข้อมูล (แนวทาง) - หน้า 93


17
use the float or real data types only if the precision provided by decimal is insufficient- ฉันคิดว่าของจริงนั้นมีความถูกต้องน้อยกว่าทศนิยมดังนั้นทำไมคุณถึงใช้งานจริงถ้าทศนิยมไม่เพียงพอ?
BornToCode

7
ที่แท้จริงคือความแม่นยำน้อยกว่าจึงไม่แนะนำเว้นแต่การจัดเก็บตัวเลขใหญ่ขนาดใหญ่ที่ทศนิยม (> 10e38) เป็นสิ่งจำเป็นหรือพื้นที่การพิจารณา .i เดาความแม่นยำที่นี่ในค่าที่เป็นไปอ้างวิธีการและขนาดไม่ได้เป็นความถูกต้อง
Iman

12
@BornToCode "ความแม่นยำ" ที่นี่หมายถึงค่าที่คุณต้องการจัดเก็บในวงกว้าง ถ้าคุณต้องการเก็บค่าระหว่าง 1e10 ถึง 1e-10 ก็decimalจะใช้ได้ นั่นเป็นความแม่นยำของการ 20. หากคุณจำเป็นต้องเก็บค่าระหว่างการพูด, 1e20 และ 1e20 ดีdecimal ไม่สามารถทำเช่นนั้นได้ นั่นคือความแม่นยำ 40 หลัก คุณไม่สามารถจัดเก็บ 1e20 และ 1e-20 ในdecimalฟิลด์เดียวกันได้ แต่คุณสามารถใช้floatซึ่งจัดเก็บทุกอย่างภายในเป็นล็อกฐาน 2 ซึ่งอนุญาตให้มีความแม่นยำอย่างเต็มรูปแบบในเขตข้อมูลเดียวด้วยข้อเสียเปรียบที่เฉพาะตัวเลข 8 หลักแรกเท่านั้นที่จะถูกต้อง
เบคอนบิต

ฉันสามความเห็นของ BornToCode และ Iman ฉันเพิ่งทดลอง (ใช้ SQL Server 2012) และดูเหมือนว่า epsilon ของเครื่องสำหรับ float (53) ซึ่งเป็นประเภททศนิยมที่แม่นยำที่สุดคือ 2.22044604925031E-16 ดังนั้นคุณจะได้ตัวเลขสำคัญออกมาประมาณ 15 ตัว ในทางกลับกันฉันจะได้ตัวเลขที่สำคัญ 38 ค่าจากทศนิยม
Stewart

"ใช้float... " - พูดว่าใคร นั่นคือคำพูดหรือความคิดเห็นของคุณ?
user443854

24

แนวทางจาก MSDN: การใช้ทศนิยมทศนิยมและข้อมูลจริง

ความแม่นยำสูงสุดเริ่มต้นของชนิดข้อมูลตัวเลขและทศนิยมคือ 38 ใน Transact-SQL ตัวเลขจะทำงานเทียบเท่ากับชนิดข้อมูลทศนิยม ใช้ชนิดข้อมูลเลขฐานสิบเพื่อเก็บตัวเลขด้วยทศนิยมเมื่อค่าข้อมูลต้องถูกจัดเก็บตรงตามที่ระบุ

พฤติกรรมของลอยและของจริงเป็นไปตามข้อกำหนด IEEE 754 กับชนิดข้อมูลตัวเลขโดยประมาณ เนื่องจากลักษณะโดยประมาณของ float และชนิดข้อมูลจริงอย่าใช้ชนิดข้อมูลเหล่านี้เมื่อจำเป็นต้องมีพฤติกรรมเชิงตัวเลขเช่นแอปพลิเคชันทางการเงินในการดำเนินการที่เกี่ยวข้องกับการปัดเศษหรือในการตรวจสอบความเท่าเทียมกัน ให้ใช้ชนิดข้อมูลจำนวนเต็มทศนิยมเงินหรือ smallmoney แทน หลีกเลี่ยงการใช้คอลัมน์ลอยหรือของจริงในเงื่อนไขการค้นหาคำสั่งย่อยโดยเฉพาะอย่างยิ่งตัวดำเนินการ = และ <> วิธีที่ดีที่สุดคือ จำกัด การลอยและคอลัมน์จริงเป็น> หรือ <การเปรียบเทียบ


จำนวนทศนิยมที่ระบุไว้ในScaleคอลัมน์
Cees Timmerman

1
หากคุณต้องการ 'ตรงตามที่ระบุ' จากมุมมองมาตรฐานมีข้อได้เปรียบบางประการnumericเนื่องจากจะไม่มีการจัดเก็บที่แม่นยำกว่าที่คุณขอ: ดูstackoverflow.com/a/759606/626804
Ed Avis

13

ไม่ใช่คำตอบที่สมบูรณ์ แต่เป็นลิงก์ที่มีประโยชน์:

"ฉันมักคำนวณกับค่าทศนิยมในบางกรณีการคัดเลือกค่าทศนิยมให้ลอยโดยเร็วก่อนการคำนวณใด ๆ

http://sqlblog.com/blogs/alexander_kuznetsov/archive/2008/12/20/for-better-precision-cast-decimals-before-calculations.aspx


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

3
ชนิดข้อมูลที่เป็นตัวเลขทั้งหมดสามารถประสบกับปัญหาโอเวอร์โฟลและอันเดอร์โฟลว์ได้ โอเวอร์โฟลว์เป็นข้อผิดพลาดที่ชัดเจนอย่างไรก็ตามอันเดอร์โฟลว์เงียบ ลักษณะของอันเดอร์โฟล์สำหรับdecimalและfloatมีความแตกต่างกัน ทศนิยมเก็บรักษากับ underflow มากที่สุดโดยการเพิ่มความแม่นยำหรือมาตราส่วน อย่างไรก็ตามเมื่อคุณถึงขีด จำกัด ของตัวเลขที่มีนัยสำคัญในรูปทศนิยมทศนิยมจะต่ำ (และความแม่นยำจะหายไป) โฟลตมีช่วงกว้างของสเกลที่เป็นไปได้และมันเป็นข้อ จำกัด ของสเกลที่จริง ๆ แล้วเป็นสาเหตุของอันเดอร์โฟล์ ดังนั้นการลอยสามารถมีขนาดที่ดีขึ้น อย่างไรก็ตามมันยังคงเป็นประเภทที่ไม่แน่นอน
ErikE

13

พวกเขาต่างกันในลำดับความสำคัญของประเภทข้อมูล

ทศนิยมและตัวเลขเป็นฟังก์ชันเดียวกันแต่ยังมีลำดับความสำคัญของชนิดข้อมูลซึ่งอาจมีความสำคัญในบางกรณี

SELECT SQL_VARIANT_PROPERTY(CAST(1 AS NUMERIC) + CAST(1 AS DECIMAL),'basetype')

ส่งผลให้เป็นชนิดข้อมูลที่เป็นตัวเลขเพราะมันใช้เวลาข้อมูลที่สำคัญชนิด

รายการชนิดข้อมูลที่ละเอียดตามลำดับความสำคัญ:

ลิงค์อ้างอิง


7

ทศนิยมมีความแม่นยำคงที่ในขณะที่ลอยมีความแม่นยำของตัวแปร

แก้ไข (ล้มเหลวในการอ่านคำถามทั้งหมด): Float (53) (aka จริง) เป็นเลขทศนิยมที่มีความแม่นยำสองเท่า (32 บิต) ใน SQL Server Regular Float เป็นตัวเลขความแม่นยำจุดเดียว Double เป็นส่วนผสมที่ลงตัวของความแม่นยำและความเรียบง่ายสำหรับการคำนวณจำนวนมาก คุณสามารถสร้างตัวเลขที่มีความแม่นยำสูงซึ่งมีทศนิยม - มากถึง 136- บิต - แต่คุณต้องระวังด้วยว่าคุณต้องกำหนดความแม่นยำและมาตราส่วนของคุณอย่างถูกต้อง


คุณไม่ได้ระบุว่าจะเลือกสิ่งใดดีกว่าในขณะที่คดีไปทำธุรกรรมทางการเงินและเพราะเหตุใด
priyanka.sarkar

สำหรับ SQL Server 2008 และสูงกว่า float (53) aka float เป็นเลขทศนิยมที่มีความแม่นยำสองเท่า (64- บิต) ขณะที่ float (24) aka จริงคือหมายเลขทศนิยมที่มีความแม่นยำเดียว (32 บิต) docs.microsoft.com/en-us/sql/t-sql/data-types/float-and-real-transact-sql
M Kloster

4

Floatเป็นชนิดข้อมูลตัวเลขโดยประมาณซึ่งหมายความว่าไม่ใช่ทุกค่าในช่วงชนิดข้อมูลที่สามารถแสดงได้อย่างแม่นยำ

ทศนิยม / ตัวเลขเป็นชนิดข้อมูลคงที่ซึ่งหมายความว่าค่าทั้งหมดในช่วงชนิดข้อมูลสามารถแสดงได้อย่างแม่นยำด้วยความแม่นยำและมาตราส่วน คุณสามารถใช้ทศนิยมเพื่อประหยัดเงิน

การแปลงจากทศนิยมหรือตัวเลขเป็นลอยอาจทำให้สูญเสียความแม่นยำ สำหรับชนิดข้อมูลทศนิยมหรือตัวเลข SQL Server พิจารณาการรวมกันของความแม่นยำและมาตราส่วนเฉพาะแต่ละชนิดเป็นชนิดข้อมูลที่แตกต่างกัน DECIMAL (2,2) และ DECIMAL (2,4) เป็นชนิดข้อมูลที่แตกต่างกัน ซึ่งหมายความว่า 11.22 และ 11.2222 เป็นประเภทที่แตกต่างกัน แต่นี่ไม่ใช่กรณีของการลอย สำหรับ FLOAT (6) 11.22 และ 11.2222 เป็นชนิดข้อมูลเดียวกัน

คุณยังสามารถใช้ประเภทข้อมูลการเงินเพื่อประหยัดเงินได้ นี่คือประเภทข้อมูลดั้งเดิมที่มีความแม่นยำ 4 หลักสำหรับเงิน ผู้เชี่ยวชาญส่วนใหญ่ชอบประเภทข้อมูลนี้เพื่อประหยัดเงิน

การอ้างอิง 1 2 3


3

กรณีสำหรับทศนิยม

มันจำเป็นต้องมีอะไรบ้าง?

มันเกิดขึ้นจากข้อเท็จจริงที่ว่าในท้ายที่สุดคอมพิวเตอร์จะแสดงตัวเลขภายในในรูปแบบไบนารี ที่นำไปสู่การปัดเศษข้อผิดพลาดอย่างหลีกเลี่ยงไม่

พิจารณาสิ่งนี้:

0.1 (decimal, or "base 10") = .00011001100110011... (binary, or "base 2")

จุดไข่ปลาด้านบน [... ] หมายถึง 'infinite' หากคุณดูอย่างระมัดระวังจะมีรูปแบบการทำซ้ำไม่สิ้นสุด (= '0011')

ดังนั้นในบางจุดคอมพิวเตอร์จะต้องปัดเศษค่านั้น สิ่งนี้นำไปสู่ข้อผิดพลาดของการสะสมที่เกิดจากการใช้ตัวเลขซ้ำ ๆ ซึ่งถูกจัดเก็บอย่างไม่แน่นอน

สมมติว่าคุณต้องการเก็บยอดเงิน (ซึ่งเป็นตัวเลขที่อาจมีส่วนที่เป็นเศษส่วน) ก่อนอื่นคุณไม่สามารถใช้จำนวนเต็มได้อย่างชัดเจน (จำนวนเต็มไม่มีส่วนที่เป็นเศษส่วน) floatจากจุดทางคณิตศาสตร์อย่างหมดจดในมุมมองของแนวโน้มตามธรรมชาติที่จะใช้ แต่ในคอมพิวเตอร์ลอยมีส่วนหนึ่งของตัวเลขที่อยู่หลังจุดทศนิยม - "mantissa" - จำกัด ที่นำไปสู่ข้อผิดพลาดในการปัดเศษ

เพื่อเอาชนะสิ่งนี้คอมพิวเตอร์เสนอประเภทข้อมูลเฉพาะที่ จำกัด ข้อผิดพลาดในการปัดเศษไบนารีในคอมพิวเตอร์สำหรับตัวเลขทศนิยม นี่คือประเภทข้อมูลที่ควรนำมาใช้เพื่อแสดงจำนวนเงิน Decimalชนิดข้อมูลเหล่านี้มักจะไปโดยชื่อของ เช่นในกรณี C # หรือDECIMALในฐานข้อมูลส่วนใหญ่


1

แม้ว่าคำถามจะไม่รวมถึงชนิดข้อมูล MONEY บางคนที่เข้ามาในเธรดนี้อาจถูกล่อลวงให้ใช้ชนิดข้อมูล MONEY สำหรับการคำนวณทางการเงิน

ระวังชนิดข้อมูล MONEY มันมีความแม่นยำ จำกัด

มีข้อมูลที่ดีมากมายเกี่ยวกับมันในคำตอบของคำถาม Stackoverflow นี้:

คุณควรเลือกประเภทข้อมูล MONEY หรือ DECIMAL (x, y) ใน SQL Server หรือไม่

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