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)
FLOAT Made My Dollars Float Away - FLOAT vs DECIMAL in MySQL
Recently I got a task:
"Alter a table column from
FLOAT
toDECIMAL(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.
That’s when I realized: this isn’t just about one query. It’s about how FLOAT silently eats your money in MySQL.
Why FLOAT is a Problem
FLOAT
in MySQL is a binary floating-point type.
It doesn’t store exact values — only approximations.
That’s 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 it’s your salary.
Example of Data Loss
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?
Here’s the fun part. Let’s 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.
That’s why when you do:
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 exactly123456789.99
.
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 Won’t Save You
Here’s the trap I fell into:
ALTER TABLE money_float MODIFY amount DECIMAL(15,2);
You’d 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 withALTER
. You’ll 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 it’s worthless.
Stick with DECIMAL
, and your dollars will stay safe. ✅