ปัญหา: DECIMAL(19,2) ปัดเศษอัตโนมัติ
MySQL จะ ROUND (ปัดเศษ) ค่าที่มีทศนิยมมากกว่าที่กำหนด:
INSERT INTO demo59 VALUES (15.346); -- เก็บเป็น 15.35 (ปัดขึ้น)
วิธีแก้: ใช้ TRUNCATE() ตัดทิ้งทศนิยมเกิน
INSERT INTO demo59 VALUES (TRUNCATE(15.346, 2)); -- เก็บเป็น 15.34
ตัวอย่าง: ตาราง demo59
CREATE TABLE demo59 (price DECIMAL(19,2)); INSERT INTO demo59 VALUES (TRUNCATE(15.346, 2)), (TRUNCATE(20.379, 2)), (TRUNCATE(25.555, 2)), (TRUNCATE(100.456, 2));
ผลลัพธ์: ตัดทิ้ง ไม่ปัดเศษ
+--------+ | price | +--------+ | 15.34 | | 20.37 | | 25.55 | | 100.45 | +--------+
TRUNCATE vs ROUND
| ค่า Input | TRUNCATE(x,2) | ROUND(x,2) | MySQL Default (INSERT) |
|---|---|---|---|
| 15.346 | 15.34 | 15.35 | 15.35 |
| 20.379 | 20.37 | 20.38 | 20.38 |
| 25.555 | 25.55 | 25.56 | 25.56 |
| 100.456 | 100.45 | 100.46 | 100.46 |
TRUNCATE() ไวยากรณ์
TRUNCATE(number, decimals)
decimals > 0: ทศนิยม (ตัดทิ้ง)decimals = 0: จำนวนเต็มdecimals < 0: ตัดที่หลักสิบ ร้อย พัน... (เช่น TRUNCATE(1234, -2) = 1200)
กรณีศึกษา: ราคาสินค้า/เงิน
ทางการเงินมักต้องการ Truncation (ตัดทิ้ง) ไม่ใช่ Rounding เพื่อไม่ให้รายได้เพิ่มขึ้นจากการปัดเศษ
วิธีอื่น: ตั้งค่า SQL Mode
SET sql_mode = 'NO_AUTO_ROUND'; -- MySQL 8.0.23+ -- หรือ SET sql_mode = 'STRICT_ALL_TABLES'; -- Error แทนการปัดเศษ
แต่แนะนำให้ควบคุมที่ Application Layer (TRUNCATE) เพื่อชัดเจนและพกพาได้
ชนิดข้อมูลเงิน: DECIMAL vs FLOAT
| คุณสมบัติ | DECIMAL(M,D) | FLOAT/DOUBLE |
|---|---|---|
| Precision | Exact (ค่าที่แน่นอน) | Approximate (ค่าประมาณ) |
| Storage | M/2 + 2 bytes (ประมาณ) | 4/8 bytes |
| เหมาะสำหรับ | เงิน, การบัญชี, measurement | วิทยาศาสตร์, engineering |
| คำนวณเร็ว | ช้ากว่า (software) | เร็ว (hardware FPU) |
เสมอ: ใช้ DECIMAL สำหรับเงิน