ปัญหาความแม่นยำของ FLOAT/DOUBLE และวิธีแก้ด้วย DECIMAL
FLOAT และ DOUBLE เป็น **Floating Point (IEEE 754)** เก็บค่าประมาณการ (Approximate) อาจเกิด Rounding Error เช่น 0.1 + 0.2 ≠ 0.3
แก้ไข: ใช้ DECIMAL (Exact Numeric)
DECIMAL(M, D) หรือ NUMERIC(M, D) เก็บค่า **แม่นยำ (Exact)** เหมาะสำหรับเงิน, การวัด, ข้อมูลทางการเงิน
M= Precision (Total Digits) สูงสุด 65D= Scale (Decimal Places) สูงสุด 30, ต้อง ≤ M
Syntax
CREATE TABLE table_name (column_name DECIMAL(10, 2));
ตัวอย่าง: เก็บเงิน 2 ทศนิยม
mysql> CREATE TABLE DemoTable (Amount DECIMAL(10,2)); Query OK, 0 rows affected (0.54 sec) mysql> INSERT INTO DemoTable VALUES (2194848.90), (90309393.79), (8999999.68), (90900000.99); Query OK, 4 rows affected
ข้อมูลเก็บได้ถูกต้องทุกหลัก:
mysql> SELECT * FROM DemoTable;
+-------------+ | Amount | +-------------+ | 2194848.90 | | 90309393.79 | | 8999999.68 | | 90900000.99 | +-------------+ 4 rows in set (0.00 sec)
เปรียบเทียบ FLOAT vs DECIMAL
| คุณสมบัติ | FLOAT / DOUBLE | DECIMAL |
|---|---|---|
| Storage | 4 / 8 Bytes | Variable (~M/2 Bytes) |
| Precision | Approximate (~7 / ~15 digits) | Exact (Up to 65 digits) |
| Speed | เร็วกว่า (Hardware FPU) | ช้ากว่า (Software Math) |
| Use Case | Scientific, Graphics, Measurement | Money, Accounting, Exact Calculation |
| Rounding Error | มี | ไม่มี |
ตัวอย่างปัญหา FLOAT
mysql> CREATE TABLE t (f FLOAT, d DECIMAL(10,2)); mysql> INSERT INTO t VALUES (0.1, 0.1), (0.2, 0.2); mysql> SELECT f+f+f, d+d+d FROM t; +--------+-------+ | f+f+f | d+d+d | +--------+-------+ | 0.30000001192092896 | 0.30 | -- FLOAT ผิด! +--------+-------+
แนวทางปฏิบัติ
- **เงิน/บัญชี/ราคา** →
DECIMAL(19,4)หรือDECIMAL(10,2)ตามความต้องการ - **วิทยาศาสตร์/สถิติ/Coordinates** →
DOUBLE - **นับจำนวน** →
INT / BIGINT - Migration:
ALTER TABLE t MODIFY col DECIMAL(10,2);