Si queremos manejar dinero en MySQL, o simplemente queremos almacenar decimales sin pérdida de precisión debemos usar el tipo de dato DECIMAL.
En lo personal, la mayoría de veces olvido cuál es su sintaxis y cómo se puede usar; así que voy a explicar cómo funciona.
Sintaxis
La sintaxis del tipo de dato es así:
DECIMAL(M, D)
En donde M
es el número de dígitos y la D
es el número de dígitos a la derecha del punto.
Error común
Con la siguiente definición:
DECIMAL(3, 2)
Creeremos que el campo podrá almacenar 3 dígitos a la izquierda del punto y 2 a la derecha (por ejemplo 250.00). Pero no, no es así.
Lo que le estamos indicando a MySQL declarando la columna de esa forma es que soporte 3 dígitos en total, y que de esos 3 tome 2 para decimales.
De modo que el número positivo más grande que podremos almacenar con esa definición será 9.99 ya que son tres dígitos y dos de ellos serán utilizados como decimales.
Explicación
Debido a eso, debemos tener en mente que:
- M: El número de dígitos que puede soportar el campo
- D: El número de dígitos que se toman de
M
como decimales
Así que si queremos almacenar algo como 250.00
debemos declarar la columna así:
DECIMAL(5, 2)
Con eso estamos diciéndole al motor: “Que este campo soporte números de hasta cinco dígitos, dos de ellos a la izquierda del punto”. Y el número positivo más grande que podremos almacenar será 999.99
Ejemplos
Voy a poner una tabla con la definición del campo, un ejemplo del dato y el máximo número positivo que soporta
| Declaración | Ejemplo de lo que podemos almacenar | Máximo número positivo
| --- | ----------- | ----------- |
|`DECIMAL(5, 2)`| 500.00 |999.99
|`DECIMAL(7,3)`| 1500.650 |9999.999
|`DECIMAL(9,2)`| 1500000.90 |9999999.99
|`DECIMAL(5,4)`| 1.0075 |9.9999
|`DECIMAL(5,0)`| 10000 |99999
|`DECIMAL(65, 0)`| Un número de 65 dígitos sin punto decimal |Un número de 65 dígitos compuesto de nueves
|`DECIMAL(66, 0)`| Error, el máximo para M es 65 |Error, el máximo para M es 65
|`DECIMAL(65, 31)`| Error, el máximo para D es 30 |Error, el máximo para D es 30
|`DECIMAL(4,5)`| Error, D no puede ser mayor que M |Error, D no puede ser mayor que M
Límites
Ahora veamos los límites de este tipo de dato.
- D no debe ser más grande que M
- M sólo puede tener 65 dígitos
- D sólo puede tener 30 dígitos (de los 65 que tiene M como máximo)
Veamos un ejemplo dentro del motor
Voy a crear una tabla para probar todo esto. Intentaré definir DECIMAL(66,30)
:

Nos dice que el máximo es 65
. Ahora vamos a intentar darle a D
algo mayor que 30
:

Dice lo mismo pero ahora para lo de la derecha del punto. Ahora voy a respetar los límites, y no me marcará error:

Ya creamos la tabla, se ve así:

Voy a insertar un simple 1
para que veamos toda la precisión:

Podemos observar que tiene muchos ceros. Ahora voy a ingresar un número muy grande:
Ahora intentaré guardar el número más grande con la mayor precisión decimal:

Finalmente cabe decir que también podemos usar decimales sin signo, así:
DECIMAL(5,2) UNSIGNED
Ya que si los dejamos con signo podremos almacenar desde -999.99 hasta 999.99.
Es decir, con el unsigned
sólo forzamos a que haya valores positivos, y creo (no estoy seguro) que ahorramos espacio ya que ese es el propósito de remover el signo
Y así es como podemos jugar con el tipo de dato decimal. Aquí dejo las referencias:
12.21.2 DECIMAL Data Type Characteristics