Add new blog post: FLOAT Made My Dollars Float Away - FLOAT vs DECIMAL in MySQL (#91)

This commit is contained in:
Al Asad Nur Riyad
2025-09-19 00:56:10 +06:00
committed by GitHub
parent 13da7d4a79
commit 6a2ed6dee5
2 changed files with 149 additions and 0 deletions

View File

@@ -0,0 +1,149 @@
---
title: FLOAT Made My Dollars Float Away - FLOAT vs DECIMAL in MySQL 💸
date: 19th Sep 2025
description: Recently I got a task Alter a table column from `FLOAT` to `DECIMAL(10,2)
image: /blogs-img/blog8.png
alt: FLOAT Made My Dollars Float Away - FLOAT vs DECIMAL in MySQL 💸
ogImage: /blogs-img/blog8.png
tags: ['mysql', 'float', 'decimal']
published: true
---
### FLOAT Made My Dollars Float Away - FLOAT vs DECIMAL in MySQL
Recently I got a task:
> **"Alter a table column from `FLOAT` to `DECIMAL(10,2)`"**
I thought:
_"Pff, easy task. Just run an `ALTER TABLE` and done. Why is this even a ticket?"_
But then I read the description.
Turns out, **FLOAT was causing data loss**, and I needed to convert it without losing data.
Thats when I realized: this isnt just about one query. Its about how **FLOAT silently eats your money** in MySQL.
### Why FLOAT is a Problem
`FLOAT` in MySQL is a **binary floating-point type**.
It doesnt store exact values — only approximations.
Thats fine for rocket science 🚀 or graphics rendering 🎮, but for **money** where every cent matters? Disaster.
Think of `FLOAT` as a leaky bucket. You pour in `$1,000,000.25`… and it gives you back `$999,999.94`.
Not funny when its your salary.
### Example of Data Loss
```sql
CREATE TABLE money_float (
id INT AUTO_INCREMENT PRIMARY KEY,
amount FLOAT
);
INSERT INTO money_float (amount) VALUES (1000000.25), (123456789.99);
SELECT * FROM money_float;
```
Result:
| id | amount |
| --- | ------------ |
| 1 | 1000000.25 |
| 2 | 123456792.00 |
We inserted `123456789.99`, but got back `123456792.00`.
The bigger the number, the worse the corruption.
### But Why Does FLOAT Lose Data?
Heres the fun part. Lets make it simple.
- `FLOAT` stores numbers in **binary (base 2)**.
- But not every decimal number can be written exactly in binary.
Example:
- In decimal, `0.1` is simple.
- In binary, `0.1` is **infinite repeating**: `0.0001100110011…`
- So `FLOAT` cuts it off at some point and stores an approximation.
Thats why when you do:
```sql
INSERT INTO money_float (amount) VALUES (0.1);
SELECT amount FROM money_float;
```
You might see something like `0.10000000149`.
Now imagine this tiny error repeated in **millions of dollars**.
Errors pile up, and suddenly your 9-digit amount looks… off.
### DECIMAL to the Rescue
`DECIMAL` stores numbers differently:
- Instead of binary approximation, it stores **exact digits as strings** internally.
- That means `123456789.99` is stored as exactly `123456789.99`.
```sql
CREATE TABLE money_decimal (
id INT AUTO_INCREMENT PRIMARY KEY,
amount DECIMAL(15,2)
);
INSERT INTO money_decimal (amount) VALUES (1000000.25), (123456789.99);
SELECT * FROM money_decimal;
```
Result:
| id | amount |
| --- | ------------ |
| 1 | 1000000.25 |
| 2 | 123456789.99 |
Perfect. ✅ No rounding surprises.
### Why ALTER Wont Save You
Heres the trap I fell into:
```sql
ALTER TABLE money_float MODIFY amount DECIMAL(15,2);
```
Youd think this fixes it, right?
Nope. ❌
The data was already corrupted when it was first inserted as `FLOAT`.
`ALTER` just moves the already-broken value into `DECIMAL`.
Garbage in → garbage out.
### Visual: FLOAT vs DECIMAL
```
FLOAT (approximation in binary):
123456789.99 ---> 123456792.00 💀
DECIMAL (exact digits):
123456789.99 ---> 123456789.99 ✅
```
### Lessons Learned
- Never use `FLOAT`/`DOUBLE` for money.
- Always use `DECIMAL(precision, scale)` (e.g., `DECIMAL(15,2)`).
- If your table already has money in `FLOAT`, you cannot fix the lost precision with `ALTER`. Youll need to re-import or clean it at the source.
### Final Thought
Using `FLOAT` for money is like paying your salary in **Monopoly money**. 🎲💵
It looks okay until you try to spend it — then you realize its worthless.
Stick with `DECIMAL`, and your dollars will stay safe. ✅

BIN
public/blogs-img/blog8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 816 KiB