Archivo de la etiqueta: MySQL Tips

Trucos de MySQL

Regla de la suma en bases de datos – MySQL Tips

Esta entrada no es específicamente para bases de datos MySQL, y se puede aplicar a cualquier otra base de datos.

Este es un pequeño truco que utilizo a la hora de explicar a alguien como decidir que tipo de dato a establecer a la hora de crear campos en una tabla en una base de datos, y es hacernos la siguiente pregunta ¿vas a sumarlo?, si la respuesta es no el tipo de campo puede establecerse de tipo varchar y si vamos a sumarlo sera de tipo numérico. Por ejemplo, los códigos postales o los teléfonos, ¿vamos a sumar códigos postales o teléfonos? la respuesta es no, por lo tanto los pondremos como tipo varchar, además en el tema de los códigos postales no hay tanto problema pero en el tema de los teléfonos… cada usuario te lo puede poner de cualquier manera, y si ponemos controles de validación del teléfono, pero al final lo que queremos es tener el teléfono del usuario.

Anuncio publicitario

Como extraer un valor numerico de una cadena en una consulta MySQL – MySQL Tips

MySQLPuede ser que alguna vez nos veamos en la necesidad que extraer los números que hay almacenados dentro de campo en el cual están combinados los números y texto, por ejemplo ( 1 litro, 1 hora, 25 euros, $4,  horas), etc…)

Si el numero esta al principio de la cadena

En estas situación la solución es muy sencilla, y es la que nos encontraremos la mayoría de las veces, simplemente utilizamos la función CONVERT().

CONVERT() es una función que nos convierte datos entre distintos tipos de caracteres. A esta función le pasaremos como parámetros la cadena o el campo en el cual este el dato que queramos extraer y SIGNED, el cual indicara que queremos que nos lo convierta a un entero, la función quedaría así:


SELECT CONVERT('25 euros', SIGNED)

Esta consulta devolverá 25, pero que pasaría si el numero no estuviera al principio de la cadena de texto,  pues que nos devolverá 0. Por lo tanto solo nos sirve la función CONVERT() cuando la cadena empieza con numero si no no sirve.

Si el numero esta en el segundo lugar

Esta situación es un poco mas complicada, y tendremos que utilizar REGEXP() e IF.  Hace unos días ya hice una entrada referente a RLIKE y REGEXP así que decir que nos permite realizar búsquedas y comparaciones con patrones, y el IF generalmente se usa a la hora de crear procedimientos o funciones, pero también se puede usar dentro de una consulta, basicamente el IF se usa de la siguiente manera:

IF (condicion, si verdadero, si falso)

Imaginemos que nos han introducido los importes de esta manera ‘€ 25’, y queremos con una consulta sacar la suma de todos los importes.


SELECT SUM(
IF (
CONVERT(campo, SIGNED) != 0,
campo,
IF (
campo REGEXP('[0-9]'),
CONVERT(SUBSTR(campo FROM 2) , SIGNED),
0
)
)
)
FROM tabla;

Básicamente lo que hago es primero comprobar si hay un numero en el principio, en caso que que lo detecte lo devuelve, si no lo detecta, o devuelve 0, comprobamos con REGEXP() a ver si hay un numero en la cadena, en el caso que lo encuentre hago un CONVERT() desde la posición 2 de la cadena por medio de un SUBSTR(), si no devuelvo 0.

El numero puede estar en cualquier parte de la cadena

Para esta situación ya tenemos que recurrir a crear una función, no es recomendable ponernos a anidar IF. Partiendo de la combinación de REGEXP(), CONVERT() y SUBSTR() he realizado la siguiente función la cual nos devolverá el primer numero que encuentre en la cadena, este donde este.


DROP FUNCTION IF EXISTS extractNumber;
DELIMITER //
CREATE FUNCTION extractNumber (cadena1 VARCHAR(255))
RETURNS INT(11)
DETERMINISTIC
READS SQL DATA
BEGIN
DECLARE posicion, resultado, longitud INT(11) DEFAULT 0;
DECLARE cadena2 VARCHAR(255);
SET longitud = LENGTH(cadena1);
SET resultado = CONVERT(cadena1, SIGNED);
IF resultado = 0 THEN
IF cadena1 REGEXP('[0-9]') THEN
SET posicion = 2;
checkString:WHILE posicion <= longitud DO
SET cadena2 = SUBSTR(cadena1 FROM posicion);
IF CONVERT(cadena2, SIGNED) != 0 THEN
SET resultado = CONVERT(cadena2, SIGNED);
LEAVE checkString;
END IF;
SET posicion = posicion + 1;
END WHILE;
END IF;
END IF;
RETURN resultado;
END //
DELIMITER ;

Limitaciones de la función extractNumber()

La mayoría de las pruebas las he realizado con números enteros, en plan «Un camión con 500 kilos de patatas» o en el plan «tortilla de 12 huevos», en todos esos casos funciona perfectamente, al igual que si ponemos «1€» o «€1» o «Total Euros: 20», pero si hay decimales solo devuelve la parte entera de estos.

Formato Fecha en MySQL – MySQL Tips

Una de las «pegas» que tiene MySQL es que por defecto gestiona las fechas en modo ’00-00-0000′ es decir año-mes-dia. Y siempre nos toca crear una función para transformar estas fechas tanto al pasarlas a la base de datos, como para recuperarlas. A la hora de la recuperación algo que nos puede ahorrar trabajo es, a la hora de realizar la consulta, devolver la fecha formateada, para ello utilizaremos DATE_FORMAT.

Nuestra consulta podría quedar de la siguiente manera


SELECT id, name, DATE_FORMAT(date, '%d-%m-%Y) as date

Como primer parámetro de DATE_FORMAT especificamos el campo que contiene la fecha, y luego como segundo parámetro especificamos el formato en el cual queremos que nos devuelva la fecha en este caso sera ’00-00-0000′

 

Mas información en http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_date-format

Enhanced by Zemanta

LOAD DATA INFILE desde un terminal remoto – MySQL Tips

Siguiendo con las entradas relacionadas con mis notas mentales, hoy me he vuelto a cruzar con una situación que se me plantea de vez en cuando y siempre tengo que tirar de la documentación.

El escenario es el siguiente, tengo un programa en php que se ejecuta en terminal que me realiza una consulta e extracción de datos de una base de datos paradox que esta en un servidor, si he dicho paradox, y me genera un fichero csv el cual a continuación por medio de una consulta de load data infile se me vuelca a una base de datos mysql que tengo en otro servidor. Resulta que la consulta load data infile no he conseguido que se me ejecute, en cuando lo solucione publicare la solución así que lo que hago es una vez terminado el proceso de volcado me conecto al servidor vía terminal y ejecuto la consulta load data infile desde la terminal. Si esto lo hago de esta manera y no ejecutando la consulta directamente es debido a lo lento que funciona el paradox. El proceso de volcado de los datos de paradox al fichero oscila entre los 8-10 minutos, realizando la operación directa el proceso duraba entre 45 minutos a 1 hora.

Primero me conecto al servidor remoto mysql con un usuario y contraseña que tenga permisos para acceso remoto, añadiendo al final la opción –local-infile=1 para poder subir ficheros


#mysql -u [usuario] -p -h [host remoto] --local-infile=1

A continuación ejecuto la consulta para que me vuelque el fichero


LOAD DATA LOCAL INFILE [fichero] REPLACE INTO TABLE [db.table]     CHARACTER SET [tipo caracteres]    FIELDS TERMINATED BY  [terminación campos]     ([columna1], [columna2], ..);

En [fichero] ponemos entre comillas la ruta completa del fichero en nuestro ordenador,  en [db.table] el nombre de la base de datos y la tabla en la que vamos a volcar los datos, en tipo carácter ponemos entre comillas el tipo de codificación p.e cp1250, utf8, en [terminación campos] como están delimitados los campos, p.e ; y finalmente entre paréntesis las columnas del la tabla.

Una vez ejecutado puedo decir que en mi caso se volcaron 42673 registros en 0.53 segundos, esta misma operación la he realizado generando un fichero sql para la inserción de los datos y el tiempo era infinitamente superior a este.

 

Crear una clave foranea con MySQL – Notas Mentales – MySQL Tips

MySQLCon esta entrada voy a inaugurar una serie de minientradas que iré creando, que voy a llamar notas mentales, serán cosas muy cortas y que si no las usamos con frecuencia, siempre que tenemos que tirar de ellas nos toca googlear.

La primera es la consulta para crear una clave foránea en MySQL en una tabla ya creada

 

ALTER TABLE `miTabla` ADD FOREIGN KEY (campodemiTabla) REFERENCES `otraTabla` (`Id`) ;