--- 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. 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 ```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? 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: ```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 Won’t Save You Here’s the trap I fell into: ```sql 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 with `ALTER`. 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. ✅