Update con Subselect en Mysql

Es posible que en algunas oportunidades necesitemos hacer una actualización a una tabla en donde la clave a utilizar en el where nos sea desconocida, y que sólo podamos obtenerla partiendo de una segunda clave en una segunda tabla.

El truco para ésto es utilizar subconsultas.

Lo más probable es que al pensar en esto, escriban un ejemplo como el siguiente:

UPDATE
  tabla1
SET
  campo = 'nuevo_valor'
WHERE
  campo_de_referencia = (
    SELECT
      tabla1.valor
    FROM
      tabla1,
      tabla2
    WHERE
      tabla1.campo = 'viejo_valor'
      AND
      tabla1.clave_primaria = tabla2.clave_foranea
      AND
      tabla2.campo_de_referencia = 'otro_valor'
  )
;

Lamentablemente, ésto no va a funcionar y van a obtener el siguiente error.

You can't specify target table 'tabla1' for update in FROM clause

Continue reading

Restaurar un backup plano en PostgreSql

En los posts previos sobre temas referentes a backups en PostgreSql, vimos un caso en el cual, en lugar de realizar el backup generando un dump comprimido, lo hacíamos en formato plano (en particular, el post hablaba sobre hacer un backup de sólo algunas tablas de una base de datos).

Ahora bien, cómo ¿hacemos para volver a introducir esos datos?.

Simplemente basta con ejecutar este comando:

psql -U usuario -d basededatos -h host -f archivoplano.sql

Automáticamente se nos pedirá la contraseña

Password for user usuario:

Una vez ingresada, nuestros datos pasarán a insertarse en PostgreSql.

Cómo crear un trigger con un Definer específico en Mysql

Normalmente, cuando se trabaja en entornos de desarrollo locales, se suele dejar al usuario con mayor privilegio y con eso aguantamos hasta el momento de pasar a producción.

Es en ese pasaje cuando descubrimos que el usuario que tenemos asignado está totalmente restringido sólo a nuestra base de datos, y hay ciertas operaciones que pueden resultar imposibles de resolver.

Un escenario posible seria al intentar crear un trigger, obtengamos un error por falta de privilegios.

Si además de éste usuario, podemos acceder a uno con privilegios más elevados (el usuario root es el habitual), podríamos crear el trigger.

Esto tampoco nos va a servir, porque cuando el usuario sin privilegios quiere ejecutar el trigger, le será negada la operación ya que el propietario del trigger es quien lo creó (en este coloquial ejemplo, sería propiedad del usuario root).

Ahora bien, la forma de poder crear un trigger pero asignándole un propietario que no se corresponde con el usuario que esté ejecutando, seria la siguiente:

CREATE DEFINER = 'usuario'@'host' TRIGGER mi_trigger BEFORE INSERT ON mi_tabla
  FOR EACH ROW BEGIN
 
  /* El código que tengamos que usar */
 
END;

De ésta forma, al crearlo con el usuario con privilegios, vamos a poder ejecutar la sentencia de creación del trigger y éste va a estar disponible para el usuario restringido que le indiquemos.

(Más que post esto parece un post-it)

Backup de tablas específicas en PostgreSql

Ya vimos cómo se hacen los backups, como se los automatiza e incluso, cómo restaurar esos backups en PostgreSql.

Hace unos días tuve un requerimiento por el cual, si bien la base de datos en cuestión ya se backupea, me solicitaban hacer un backup con mayor periodicidad, pero sólo de un conjunto de tablas.

Bien, gracias a la flexibilidad de nuestro motor favorito, esto es muy sencillo.

Repasemos cómo hacíamos para hacer un dump completo de nuestro base de datos.

pg_dump -i -h localhost -p 5432 -U postgres -F c -b -v -f "/home/damian/backups/mibase.backup" mibase

Para exportar sólo un conjunto de tablas, tenemos que hacer un pequeño cambio.

pg_dump -i -h localhost -p 5432 -U postgres -t tabla -F p -b -v -f "/home/damian/backups/mitabla.sql" mibase

La diferencia entre ambos scripts radica en que agregamos el parámetro -t seguido del nombre de nuestra tabla (en este caso, con poca inspiración, usé tabla).

Lo que vamos a obtener es, solamente,  un backup de la tabla indicada, con su estructura y datos.

Si lo que necesitamos son un conjunto de tablas, tenemos dos formas de hacerlo.  La primera es usando el parámetro -t tantas veces como tablas vayamos a requerir.

pg_dump -i -h localhost -p 5432 -U postgres -t usuarios -t documentos -t logs -F p -b -v -f "/home/damian/backups/mistablas.sql" mibase

La segunda forma, es utilizar patrones (si es que se aplica a nuestro caso).

pg_dump -i -h localhost -p 5432 -U postgres -t productos_* -F p -b -v -f "/home/damian/backups/mistablas.sql" mibase

En ambos casos, se hará un backup de las tablas, vistas y/o secuencias que coincidan con lo indicado.

Continue reading

Duplicando una tabla en Mysql

Hay ocasiones en las que necesitamos hacer pruebas sobre una tabla que se encuentra en producción.

Una forma rápida de hacer esa prueba sin afectar los datos, es hacer una copia de la tabla.

En realidad, si tenemos tiempo siempre será más cómodo llevar esos datos a un entorno de staging para trabajar más tranquilos; vamos a pensar que no tenemos tiempo… y mucho menos un entorno se staging.

Si queremos duplicar nuestra tabla, sólo debemos ejecutar la siguiente instrucción:

CREATE TABLE tabla_nueva LIKE tabla_original;

De ésta forma. obtenemos una tabla idéntica en cuanto a estructura.

Si necesitamos los datos de esa tabla en nuestra copia, insertamos todos los registros de la original de la siguiente forma:

INSERT INTO tabla_nueva SELECT * FROM tabla_original;

Al haber una correspondencia exacta en cuanto a las columnas y tipos de datos, los registros son insertados sin mayor problema.

Hay una segunda forma de obtener el mismo resultado que las dos consultas previas. Podemos, con una sola instrucción, lograr la misma tabla.

En este caso, debemos ejecutar:

CREATE TABLE tabla_nueva SELECT * FROM tabla_original;

Con esto, dos formas muy rápidas de duplicar una tabla y, si se quiere, sus datos.

Cambiando el Definer de un Procedure en Mysql

En el día de ayer, nos tocó hacer un deploy en un VPS.

Hubo un pequeño error a causa de la falta de control (tanto de nuestro lado como del de los implementadores), y cuando se importó la base de datos, se crearon los Procedure con un usuario propietario que no era el mismo que teníamos para acceder a la base de datos.

Luego de lidiar un rato, logramos que nos facilitaran el usuario root de Mysql, y ahí fue otro cantar.

Antes de conseguir el usuario, uno de los caminos era arreglar el script sql y mandarlo nuevamente para que se borrara la base de datos y se volviera a importar.

Si bien cumple su cometido, hay otro aún más sencillo e igual de efectivo.

Ya con un usuario con los permisos necesarios, para conocer qué Procedures tenemos definidos en nuestras bases de datos dentro de Mysql, sólo es necesario correr ésta consulta.

SELECT * FROM mysql.proc;

Así veremos todos los que tengamos definidos, sin importar ninguna condición.

Continue reading

Convirtiendo de Timestamp a Date desde Mysql

Cuando estaba a punto de irme de la oficina, Guille me tiró una preguntita, de esas que hacen que cuando no te acordás, te pongas a probar y probar hasta resolverlo.

La pregunta se refería a cómo pasar una fecha en formato Timestamp al formato Date (una representación más humana).

Lo primero que pensé fue en usar Php (por asumir qué así lo quería hacer), pero no, lo que quería era sacar el registro, directamente desde la base de datos, aplicando la conversión en el propio Mysql al momento de la consulta.

Como ya me ha pasado en otras ocasiones, supuse que encontraría en la documentación alguna función mágica que resolviera el problema… y por suerte, no me equivoqué.

Para convertir directamente desde la consulta una fecha desde timestamp a date, sólo hay que aplicar la siguiente función:

select from_unixtime(1224815188);

El resultado que obtenemos es:

2008-10-24 00:26:28

Nada más, con eso, problema resuelto.

Para más referencias sobre funciones de fecha, pueden mirar en la documentación oficial.

(Otro post cortito y al pié).

Restaurar backups de Mysql

En ésta oportunidad, vamos a ver cómo restaurar una base de datos en Mysql. Además, algunas aclaraciones sobre el uso de mysqldump que pueden ayudarnos con las restauraciones de bases de datos.

La forma de restaurar una base de datos Mysql desde la consola, tomando un backup, sería asi.

mysql -u usuario -p basededatos < basededatos.sql

El escenario que estoy suponiendo, implica que la base de datos que están queriendo importar no existe en su servidor Mysql.

Si este supuesto es correcto, se van a encontrar con un problemita, o mejor dicho, con un mensaje al ejecutar el comando.

ERROR 1049 (42000): Unknown database 'basededatos'

Esto se debe a la inexistencia de la base dentro de nuestro Mysql.

Tenemos dos maneras de resolver ésta situación.

  1. Editar el archivo sql y agregarle a mano los comandos necesarios para la creación de la base.
  2. Agregar dos parámetros a nuestro comando mysqldump.

Continue reading

Restaurar backups de PostgreSql

Vamos a continuar con las operaciones que deben ser habituales para el mantenimiento de nuestras base de datos.

Hasta ahora ya habíamos visto cómo hacer un backup en Postgresql, y también, cómo hacerlo de manera automática.

Vamos ahora a la otra punta del circuito: restaurar una base desde nuestros backups.

El comando que vamos a utilizar (y conocer) es pg_restore.

Si lo aplicara a los ejemplos que antes dí sobre pg_dump, nuestro ejemplo de pg_restore seria el siguiente.

pg_restore -i -h localhost -p 5432 -U postgres -d mibase -v "/home/damian/backups/mibase.backup"

Una vez que lo ejecutemos, se nos pedirá la contraseña del usuario que vamos a usar.

Continue reading