Subtracting unsigned integers with MySQL


Unsigned integer values are used in a database when you only expect to contain positive values and no negative values (less than zero). If you know a certain field will never legitimately contain negative values, then this is actually the most efficient field type to select.

There is a catch with unsigned ints however that can create problems for you if you’re not careful. That is, when you subtract unsigned ints, you will always get a positive value back no matter what. What does that mean?

Say you have a table for products with two unsigned fields: qty_in_stock and qty_sold. Lets assume for whatever reason you oversold your inventory and qty_in_stock now equals 100, but qty_sold = 101. So take the following statement:

SELECT qty_in_stock - qty_sold AS qty_remaining FROM products

You would expect qty_remaining to be -1, right? Wrong! In fact MySQL returns 18446744073709551615 !

Why would this happen? Well, because MySQL is built so that when you perform a math operation on two unsigned ints, it will always return an unsigned int. And -1 is technically an out-of-bounds value for an unsigned field type. Instead of complaining, MySQL returns the value that would have represented -1 if it were unsigned which is 18446744073709551615.

Mathematically, I suppose this is correct, however it doesn’t make any logical sense to me. If anything, I think MySQL should throw an out-of-bounds error when this happens because the default behavior seems very unintuitive to me. It is as though they are trying to say that one positive value subtracted from another can never result in a negative value. Of course this is false, but that is how MySQL works.

There are two solutions to this. The first is to simply use signed ints if you ever expect them to be used in a subtraction formula. You waste some space, but it’s an easy fix.

The second solution is, if you are able to edit your SQL statement that have the subtraction, you can use the MySQL cast function. The example from above could be converted to the following:

SELECT cast(qty_in_stock - qty_sold AS signed) AS qty_remaining FROM products

So there is a solution to this “problem” if you will. You can read more about this subject on the MySQL site at http://dev.mysql.com/doc/refman/4.1/en/cast-functions.html

  1. #1 by sumanth on August 26th, 2008

    Thanks! This helped me.

  2. #2 by Chris on January 12th, 2009

    Thanks for the solution! MySQL is strange sometimes…

(will not be published)

  1. No trackbacks yet.