Posts Tagged ‘sintaxis’

Jugando con formatos de fechas en MySQL.

Jueves, Septiembre 4th, 2008

Este post es muy simple, pero su contenido me facilita mucho la vida desde que lo programé. Se trata de un par de simples funciones para convertir los dos formatos de fecha que más utilizo en el proyecto que estoy desarrollando. Estos dos formatos son por una parte el habitual DATE de MySQL (YYYY-MM-DD) y por otra parte un formato texto VARCHAR(8) que simplemente elimina los guiones (YYYYMMDD) de la fecha. Lo de utilizar este formato en modo texto viene porque recopilo mucha información de tablas en una base de datos externa en la que las fechas están almacenadas de esta manera.

De paso tiene la ventaja de que es insensible a configuraciones regionales que tienden a cambiar mes y día a la mínima que se les da una oportunidad...

Así pues, para moverme indistintamente con los dos formatos de fecha y no tener que andar preocupándome en cada ocasión si está en uno u otro formato, tengo estas dos minifunciones almacenadas en MySQL que me sirven de ayuda.

La primera es para pasar de formato DATE a formato VARCHAR(8):

#---------------------------------------------------------------------
# STORED FUNCTION: sf_date2strng 
#---------------------------------------------------------------------
# Author:      Albert Mata (www.albertmata.net)
# Date:        20080904
# Description: Takes a date in YYYY-MM-DD format and returns it in
#              YYYYMMDD format.
#---------------------------------------------------------------------
DROP FUNCTION IF EXISTS sf_date2strng;

DELIMITER //

CREATE FUNCTION sf_date2strng(mydate DATE) RETURNS VARCHAR(8)

BEGIN
    RETURN CONCAT(MID(mydate,1,4),MID(mydate,6,2),MID(mydate,9,2));
END
//

DELIMITER ;

Y esta segunda es para pasar de formato VARCHAR(8) a formato DATE:

#---------------------------------------------------------------------
# STORED FUNCTION: sf_strng2date 
#---------------------------------------------------------------------
# Author:      Albert Mata (www.albertmata.net)
# Date:        20080904
# Description: Takes a date in YYYYMMDD format and returns it in
#              YYYY-MM-DD format.
#---------------------------------------------------------------------
DROP FUNCTION IF EXISTS sf_strng2date;

DELIMITER //

CREATE FUNCTION sf_strng2date(mydate VARCHAR(8)) RETURNS DATE

BEGIN
    RETURN STR_TO_DATE(mydate,'%Y%c%e');
END
//

DELIMITER ;

Para almacenarlas en la base de datos MySQL basta con copiar todo este código tal cual en un archivo de texto, añadirle una primera línea...

USE nameofddbb;

...y guardar el archivo con un nombre corto y en una ruta facilita (esto es opcional, pero para qué complicarse la vida), como por ejemplo C:\in.txt. Hecho esto, basta con escribir en un símbolo de sistema de Windows (antes de entrar en MySQL):

mysql -u root -p < C:\in.txt

También podemos hacerlo con un usuario no root, pero tiene que tener suficientes permisos para poder crear un procedimiento almacenado en la base de datos concreta que hayamos especificado en esa primera línea del archivo de texto.

Una vez tenemos las funciones almacenadas en MySQL comprobamos que funcionan. Primero le introducimos una fecha para que nos la convierta a texto y vemos que funciona sin problemas:

mysql> SELECT sf_date2strng('2008-09-04');
+-----------------------------+
| sf_date2strng('2008-09-04') |
+-----------------------------+
| 20080904                    |
+-----------------------------+
1 row in set (0.00 sec)

También podemos introducirle una fecha completa (con hora) y funcionará también bien. Sin embargo nos avisará de que se ha generado un warning. Si lo miramos vemos que no es nada grave, simplemente nos informa de que ha desestimado totalmente la hora, lo cual no nos importa.

mysql> SELECT sf_date2strng('2008-09-04 18:23:45');
+--------------------------------------+
| sf_date2strng('2008-09-04 18:23:45') |
+--------------------------------------+
| 20080904                             |
+--------------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> SHOW WARNINGS;
+-------+------+---------------------------------------------+
| Level | Code | Message                                     |
+-------+------+---------------------------------------------+
| Note  | 1265 | Data truncated for column 'mydate' at row 1 |
+-------+------+---------------------------------------------+
1 row in set (0.00 sec)

A continuación probamos la segunda función, introduciéndole un texto que representa una fecha para que nos la convierta a tipo DATE:

mysql> SELECT sf_strng2date('20081026');
+---------------------------+
| sf_strng2date('20081026') |
+---------------------------+
| 2008-10-26                |
+---------------------------+
1 row in set (0.00 sec)

A partir de aquí podremos utilizar estas dos funciones en cualquier consulta, vista u otro procedimiento o función almacenada que deseemos.

Instrucciones menos habituales en MySQL (1a parte).

Martes, Agosto 26th, 2008

Utilizando la base de datos MySQL como acostumbro, constantemente estoy lidiando con las sintaxis más habituales para crear y modificar tablas, funciones, vistas y demás. No obstante, hay también por ahí un conjunto de instrucciones que alguna vez he utilizado y que solía tener que googlear porque nunca las recordaba desde la vez anterior. Hasta que me decidí a ir anotándolas, por tontas y breves que fueran. Y ahora, ya que estamos, me ha parecido buena idea compartirlas por si a alguien le sirven de algo.

Ver el código que en su día utilizamos para crear una vista.

Si por ejemplo hacemos un...

DESCRIBE tbl_tablenamex;

...sobre una tabla o una vista, nos devuelve la estructura de esa tabla o vista, con sus campos y tipos de datos y demás información básica. No obstante, en ocasiones con las vistas me interesa ver de una manera rápida con qué sintaxis exacta la creé (de dónde saqué los campos, cómo enlacé las tablas, etc.). Normalmente tengo esa información guardada en archivos de texto, ya que raramente creo una vista directamente en consola, sino que más bien suelo hacerlo a través de archivos planos. No obstante me resulta más rápido verlo directamente en la consola que tener que ir a buscar el archivo. Para ello me valgo de...

SHOW CREATE VIEW viw_viewnamexx;

...y obtengo, aunque de un modo no muy agradable de ver, la sintaxis que utilicé para crear la vista en su momento.

Reiniciar el contador autonumérico de una tabla.

A menudo utilizo campos autonuméricos en mis tablas. Aunque tienen algún inconveniente, si se utilizan únicamente a modo de campo identificador para uso fundamentalmente interno, suelen aportar mayores ventajas que inconvenientes presentan. ¿Pero cómo reiniciamos el contador autonumérico después de haber estado trasteando con la tabla? Muy fácil, en dos pasos. El primero es asegurarnos que la tabla está totalmente vacía de registros. El segundo consiste en aplicar...

ALTER TABLE tbl_tablenamex AUTO_INCREMENT = 1;

...y el contador habrá quedado convenientemente reseteado. Si queremos que se resetee pero que no comience de nuevo por el 1 sino por ejemplo por el 1001, también se lo podemos indicar con esta misma instrucción.

Listar todas las tablas en una base de datos.

En principio para hacer esto nos podemos valer de un simple...

SHOW TABLES;

...pero esto solo nos listará las tablas sin añadir mayor información, cosa que la mayor parte de las veces nos puede ser más que suficiente. Sin embargo si queremos obtener más información podemos utilizar...

SELECT *
FROM information_schema.tables
WHERE table_schema = 'nameofddbb';

...y obtendremos no solo el nombre sino también si se trata de una tabla o vista, qué motor utiliza (InnoDB, MyISAM...), el número de registros, la fecha de creación, aspectos sobre el tamaño, etc.

Listar todos los campos en una tabla.

Del mismo modo, para los campos podemos hacer como hemos dicho antes un...

DESCRIBE tbl_tablenamex;

...pero si queremos un poco más de información también podemos recurrir a...

SELECT *
FROM information_schema.columns
WHERE table_name = 'tbl_tablenamex';

...y como ocurría con las tablas obtendremos algo más de información.

Obtener información sobre rutinas.

Si lo que queremos es obtener información sobre funciones o procedimientos almacenados en una base de datos (incluyendo el código fuente con el que se crearon), podemos utilizar...

SELECT *
FROM information_schema.routines
WHERE routine_schema = 'nameofddbb';

Obtener información sobre vistas (otro método).

Si de lo que queremos obtener información más detallada (incluyendo nuevamente el código utilizado en la generación) es una vista, podemos utilizar...

SELECT *
FROM information_schema.views
WHERE table_schema = 'nameofddbb';

Obtener información sobre triggers (disparadores).

Y si lo que queremos es obtener información más detallada sobre disparadores o triggers (también incluyendo el código con el que se han generado), podemos utilizar...

SELECT *
FROM information_schema.triggers
WHERE trigger_schema = 'nameofddbb';

Copiar una tabla y opcionalmente rellenarla.

Si deseamos crear una copia de una tabla en la misma o en otra base de datos, podemos utilizar primero esta instrucción para copiar la estructura...

CREATE TABLE tbl_targettabl LIKE nameofddbb.tbl_sourcetabl;

...y nos creará una tabla destino igual que la tabla origen, solo que sin datos dentro. Para copiar a continuación todos los datos nos bastará con...

INSERT INTO tbl_targettabl
SELECT * FROM nameofddbb.tbl_sourcetabl;

De hecho, en caso de querer copiar tanto estructura como datos, también podríamos haberlo hecho en un solo paso con...

CREATE TABLE tbl_targettabl
SELECT * FROM nameofddbb.tbl_sourcetabl;

...pero para mí gusto, este método presenta el inconveniente de que si la tabla contiene claves principales no se trasladan a la copia, por lo cual yo prefiero siempre el método en dos pasos.

Y lo de añadir nameofddbb. antes del nombre de la tabla está claro que sólo será preciso cuando estemos operando con dos bases de datos distintas (si solo trabajamos con una no es preciso añadirlo).

Esto es todo por ahora. Seguro que me dejo más instrucciones de esas poco frecuentes que a veces necesitamos, así que titulo intencionadamente el post con lo de 1a parte en previsión de que más adelante pueda haber otras.