Hablemos de tipos de datos.
Antes de nada hay que aclarar que MariaBD permite alteraciones en su comportamiento en cuanto a cómo maneja y almacena los datos. Lo normal es que cuando un valor no encaja en su tipo de datos se produzca un error. En cualquier caso, vamos a poner al servidor en el modo de funcionamiento de SQL que nos interesa para explicar los tipos de datos.
select @@GLOBAL.sql_mode;
SET @@SESSION.sql_mode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION';
La primera orden te muestra cómo está configurado tu servidor. La segunda es la que forzamos para esta sesión. Cuando terminemos y cerremos HeidiSQL, MariaDB volverá a su configuración anterior.
Ahora vamos a crear una base de datos y una tabla de pruebas.
create database probando;
use probando;
CREATE TABLE tipos(
tchar char(10),
tvarchar varchar(10),
tint int,
tfloat float,
tdec decimal(4,2),
tdate date,
ttime time
);
Fijémonos en lo que hemos hecho.
CREATE TABLE es la orden para definir el esquema de una tabla. A toda tabla hay que darle nombre. El nuestro ha sido "tipos".
Entre paréntesis, las definiciones de columna. Lo más básico es el nombre de la columna y su tipo de datos.
Los tipos de datos son un artefacto informático, en realidad una limitación de los lenguajes de programación. Ha sido la solución para hacerlos más fáciles de construir y más fiables. Quédate con la idea de que son prácticamente inevitables y que hay que conocerlos.
Los tipos de datos dependen del servidor pero, recuerda, nosotros estamos utilizando MariaDB así que disponemos de tantos tipos de datos como nos muestra la página correspondiente del manual. Los más comunes son los numéricos, de caracteres y de fechas y tiempo.
Char(n) y varchar(n) son tipos de datos para almacenar texto, caracteres alfanuméricos, y el parámetro "n" es la longitud máxima de ese texto.
Int, float, decimal son tipos numéricos, para números exclusivamente.
Date permite almacenar fechas —año, mes y día— y time tiempo —horas, minutos y segundos—.
Antes de probar los tipos de datos vamos a hacer un cambio en HeidiSQL. Lo que pretendemos es mostrar los datos tal cual se almacenan en MariaDB. Sin ir más lejos, para MariaDB el punto decimal es eso, un punto.
Accede a las "Preferencias" de HeidiSQL y desmarca —si estuviera marcada— la casilla de "formato local de números".
INSERT INTO tipos VALUES
('hola', 'hola',3,4.5,99.99,'2016-10-12','8:31:10');
select * from tipos;
De lo primero que debemos darnos cuenta es de que, a la hora de escribir nuestra orden, el texto va entrecomillado con comillas simples y los números no. Fechas y tiempo también entrecomilladas. Insistimos: números sin comillas; texto, fechas y tiempo con comillas.
¿Qué diferencia hay entre char y varchar?
MariaDB hace ciertas cosas por nosotros, para hacernos la vida más fácil. Para que nos muestre la realidad de char y varchar vamos a modificar su comportamiento con la siguiente orden. No te preocupes si no tienes muy claro qué estamos haciendo, solo es por el ejemplo.
SET @@SESSION.sql_mode=concat(@@SESSION.sql_mode,',PAD_CHAR_TO_FULL_LENGTH');
Ahora, ejecuta esta consulta:
select length(tchar), length(tvarchar), concat(tchar,'#'), concat(tvarchar,'#') from tipos;
Si observas la salida, las dos primeras columnas nos dicen que el valor almacenado en tchar mide exactamente los 10 caracteres que le hemos definido en la tabla "tipos". Sin embargo, el de tvarchar solo mide 4 caracteres. A continuación les hemos añadido un carácter final a uno y otro —con la función CONCAT(), concatenar cadenas de caracteres— y ahí se ve incluso mejor la diferencia: en la tercera columna ves los espacios finales del char precediendo a la "almohadilla"; en la cuarta no hay espacios intermedios.
El tipo char tiene una longitud fija, da igual lo que intentemos almacenar, si no llega al máximo rellena con espacios. El tipo varchar solo almacena lo que necesita, es de longitud variable, aunque con un máximo, en este caso 10. Es fácil entender que varchar ahorra espacio en el disco duro. Sin embargo, es más difícil de manejar para MariaDB, de alguna forma debe detectar dónde está el fin de la cadena. El char siempre mide los mismo, no ahorra espacio, pero es más fácil de almacenar y, lo más importante, de recuperar. No te obsesiones con esto, tú no te vas a enterar pero, para que lo entiendas, char es más rápido que varchar.
Uno no es mejor que otro, la elección se guía por el uso que vaya a tener. Por ejemplo, a la hora de imprimir un resultado, con un char tendríamos que quitar los espacios sobrantes. Sin embargo, el char es importante para definir índices. Normalmente el char se utiliza en cadenas bien definidas como pueda ser un código, y el varchar para cadenas sin una longitud clara como pueda ser el nombre y los apellidos de una persona.
¿Que ocurre si me paso de tamaño? Depende de cómo esté configurado el servidor. Si sigue estrictamente las normas del SQL estándar saltará un error. Si no, MariaDB te recorta por donde le parece más adecuado.
SET @@SESSION.sql_mode='';
INSERT INTO tipos (tchar,tvarchar) VALUES ('aaaaaaaaa0123', 'aaaaaaaaa0123');
select * from tipos;
Vayamos a los números. La principal diferencia está entre si tienen o no decimales, si son enteros o reales.
select tint, tfloat, tdec from tipos;
Hemos utilizado un tercer tipo numérico, decimal (dígitos, decimales). Con este limitamos la longitud en dígitos máxima y, de ellos, cuántos reservamos para decimales.
Prueba lo siguiente con el modo "relajado" (en modo estricto saltaría un error y no añadiría fila ninguna):
SET @@SESSION.sql_mode='';
INSERT INTO tipos (tint,tfloat,tdec) VALUES (3.75, 123456789.123456789, 999.999);
select tint, tfloat, tdec from tipos;
La primera conclusión que sacamos del ejemplo es que cada tipo de datos tiene sus límites. Si intentamos almacenar 3.75 como entero MariaDB lo redondea. En un float no podemos guardar un número arbitrariamente grande. Tampoco en un decimal en el que, además, hemos puesto límite a la longitud de las partes entera y decimal.
El caso del float es el más difícil de ver.
INSERT INTO tipos (tfloat) VALUES (123456789.123456789);
INSERT INTO tipos (tfloat) VALUES (123456.123456789);
INSERT INTO tipos (tfloat) VALUES (12345.123456789);
INSERT INTO tipos (tfloat) VALUES (.123456789);
select tfloat from tipos where tint is null;
Al final vemos que solo nos está admitiendo 6 dígitos como máximo, con el punto decimal "flotando" entre ellos. En el primer caso la parte entera es demasiado grande y redondea: pasa de 123.456.789 a 123457000. En el segundo caso, aunque hay parte decimal, la parte entera se come todo el espacio disponible. En el tercero ya cabe un decimal. Si no hay parte entera, el cuarto caso, "caben" 6 redondeando el valor a partir de esa posición.
Vayamos ahora a por las fechas y el tiempo.
select tdate, ttime, tdec from tipos;
En primer lugar, las fechas tienen un formato fijo: año, mes y día, y separados por guiones. ¿Es que no voy a poder utilizar mi formato usual, algo así como '12/10/2016'?
insert into tipos (tdate) values ('12/10/2016');
select tdate, ttime, tdec from tipos;
De momento no, hay que respetar los deseos de MariaDB, ya veremos la forma de salvar esta dificultad. Lo mismo vale para el formato de tiempo.
Volvamos ahora a lo de las comillas.
insert into tipos (tint,tdate) values ('2016-10-12',2016-10-12);
select tdate, ttime, tdec from tipos;
Cuando no respetamos el tipo de datos que espera MariaDB, el servidor intenta como puede adivinar nuestras intenciones. Por ejemplo, como primer valor esperaba un entero y se ha encontrado con texto. MariaDB intenta interpretarlo como número pero encuentra caracteres no numéricos, los guiones, que se lo impiden. Al final, guarda lo que puede.
Y como fecha hemos intentado guardar un número, el resultado de dos restas, 2016-10-12 = 1994. MariaDB no ha sabido manejarlo y ha almacenado lo mejor que ha encontrado, o sea, nada.