Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » Mysql »

Procedimientos almacenados mysql

Estas en el tema de Procedimientos almacenados mysql en el foro de Mysql en Foros del Web. Buenas, Tengo instalado MySQL 5.0.51a y estoy intentando hacer un procedimiento almacenado que elimine registros si su fecha de creación superan la semana... Pero no ...
  #1 (permalink)  
Antiguo 02/03/2011, 03:29
 
Fecha de Ingreso: noviembre-2009
Mensajes: 226
Antigüedad: 14 años, 5 meses
Puntos: 19
Procedimientos almacenados mysql

Buenas,

Tengo instalado MySQL 5.0.51a y estoy intentando hacer un procedimiento almacenado que elimine registros si su fecha de creación superan la semana... Pero no me funciona pegando el código en phpMyAdmin. El código es:

delimiter //

Código MySQL:
Ver original
  1. CREATE procedure eliminaPrensaExterna()
  2. DECLARE fecha,fechaActual DATE;
  3. SELECT CURDATE() INTO fechaActual;
  4. DECLARE cursor_pe CURSOR FOR SELECT distinct(fchPublicacion) FROM prensa_externa WHERE estado=0 OR estado=2;
  5. DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET hecho=1;
  6. OPEN cursor_pe;
  7.    FETCH cursor_pe INTO fecha;
  8.    IF NOT hecho THEN
  9.       IF fechaAcutal+0>fecha+7 THEN
  10.          DELETE FROM prensa_externa WHERE fchPublicacion=fecha AND (estado=0 OR estado=2);
  11.       END IF;
  12.    END IF;
  13. UNTIL hecho END REPEAT;
  14. CLOSE cursor_pe;
  15.  
  16. //

¿Alguien sabe si falla algo, o simplemente esta versión de MySQL no soporta procedimientos almacenados?

Muchas gracias!
  #2 (permalink)  
Antiguo 02/03/2011, 05:17
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Procedimientos almacenados mysql

Los procedimientos almacenados se implementaron precisamente para la versión 5.0.x, por lo que tu problema no está allí: está en el código que tiene un defecto básico: No puedes leer y borrar en la misma tabla al mismo tiempo...

Me explico: Un CURSOR abre una tabla en modo de lectura exclusivo, por lo que automáticamente está bloqueada para toda otra acción, excepto dirty reads. Este bloqueo dura mientras el CURSOR esté abierto, porque en realidad estás recorriendo los registros uno a uno.
Como la tabla está bloqueada, simplemente no puedes borrar un registro en base a una lectura de la misma tabla, y menos aún el registro sobre el que en ese momento estás parado. Sería igual que cortar la rama del árbol en la que te estás sosteniendo...
Tu segundo problema es que esta acción debería estar devolviendo un error de ejecución, que tu no estás capturando. Es de buena programación capturar todos los mensajes de error que se producen, especialmente en la etapa de desarrollo.

Además de estas consideraciones, ese procedimiento podría ser más simple, y no estás usando en algunos casos las sentencias correctas para las acciones a realizar.
Por lo pronto, ten en cuenta que el borrado de los registros tiene una condición bastante simple: estado debe ser 0 ó 2 y la fecha de publicación, la de hace siete días. Las dos cosas tiene forma simples de escribirse, y para las fechas es siempre mejor usar funciones que hacer operaciones aritméticas.
Eso sería simplemente:
Código MySQL:
Ver original
  1. DELETE FROM prensa_externa
  2. WHERE fchPublicacion = SUB_DATE(CURDATE(), INTERVAL 7 DAY) AND estado IN(0,2);

o bien:
Código MySQL:
Ver original
  1. DELETE FROM prensa_externa
  2. WHERE ADD_DATE(fchPublicacion, INTERVAL 7 DAY) = CURDATE() AND estado IN(0,2);

Si lo quieres en un SP:
Código MySQL:
Ver original
  1. DELIMITER$$
  2. DROP PROCEDURE IF EXISTS eliminaPrensaExterna()$$
  3. CREATE PROCEDURE eliminaPrensaExterna()
  4.     DECLARE fechaActual DATE;
  5.     SET = fechaActual = CURDATE();
  6.     DELETE FROM prensa_externa
  7.     WHERE fchPublicacion = SUB_DATE(fechaActual, INTERVAL 7 DAY) AND estado IN(0,2);
  8. END$$

Toma nota de que para asignar valores a las variables no necsitas usar SELECT INTO, sino SET. SELECT INTO se usa fundamentalmente si los valores provienen de un SELECT,, pero no si son producto de funciones u operaciones con datos ya existentes.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)

Última edición por gnzsoloyo; 02/03/2011 a las 06:00
  #3 (permalink)  
Antiguo 02/03/2011, 05:44
 
Fecha de Ingreso: noviembre-2009
Mensajes: 226
Antigüedad: 14 años, 5 meses
Puntos: 19
Respuesta: Procedimientos almacenados mysql

Buenas,

Muchísimas gracias por tu ayuda.

Tengo preguntas para ti :D.

Lo primero, no te falta razón :S... No puedo borrar algo que saco de un cursor... ¿Hay alguna función para borrar el elemento anterior de la posición actual del cursor?

¿Cómo capturo los errores? Pon un ejemplo, por favor.

Ya sé que se podía hacer fácilmente con una consulta y ejecutarla con PHP, pero es una acción que se ejecutará muy a menudo... Por lo que es preferible guardarla como procedimiento almacenado, ¿no?

Ha quedado clarísimo lo de SET y no SELECT.

Muchísimas gracias, eres un genio.
  #4 (permalink)  
Antiguo 02/03/2011, 05:59
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Procedimientos almacenados mysql

Cita:
¿Cómo capturo los errores? Pon un ejemplo, por favor.
La captura de errores se hace por programación, por lo que dependerá del lenguaje usado para la aplicación que vayas a diseñar.

En el caso de los SP, la ejecución misma del SP debe devolver un error, que suelen aparecer como mensajes en la misma interfase que usas para las pruebas (phpMyAdmin, en tu caso, yo prefiero usar MySQL Workbench). COmo los SP no son debuggeables en MySQL, la única forma de obtener los errores es con HANDLERs, controlando los diferentes SQLSTATE, pero puede volverse muy engorroso.

Respecto de los cursores, estos son grandes consumidores de procesador y tiempo, por lo que son recomendables si y sólo si debes forzosamente verificar o realizar operaciones con un conjunto dado de datos en cada registro. Usarlos para localizar un conjunto de registros que cumplen una condición, pero no para operar con los datos, a mi entender no es una buena práctica.

Mi recomendación es que si quieres obtener un conjunto de registros que luego serán borrados, es más simple y rápido hacerlo con tablas temporales. Además, las tablas temporales se borran solas al cerrar la conexión, por lo que no molestan.

Así pues, hay dos propuestas: Una es la que ya te hice:
Código MySQL:
Ver original
  1. DELIMITER$$
  2. DROP PROCEDURE IF EXISTS eliminaPrensaExterna()$$
  3. CREATE PROCEDURE eliminaPrensaExterna()
  4.     DECLARE fechaActual DATE;
  5.     SET = fechaActual = CURDATE();
  6.     DELETE FROM prensa_externa
  7.     WHERE fchPublicacion = SUB_DATE(CURDATE(), INTERVAL 7 DAY) AND estado IN(0,2);
  8. END$$
La otra sería con tablas temporales:
Código MySQL:
Ver original
  1. DELIMITER$$
  2. DROP PROCEDURE IF EXISTS eliminaPrensaExterna()$$
  3. CREATE PROCEDURE eliminaPrensaExterna()
  4.     DROP TEMPORARY TABLE IF EXISTS t_prensa_externa t_prensa_externa ;
  5.     CREATE TEMPORARY TABLE t_prensa_externa LIKE prensa_externa;
  6.     INSERT INTO t_prensa_externa
  7.     SELECT *
  8.     FROM prensa_externa
  9.     WHERE fchPublicacion = SUB_DATE(CURDATE(), INTERVAL 7 DAY) AND estado IN(0,2);
  10.     DELETE FROM prensa_externa
  11.     WHERE id_prensa_externa IN (SELECT id_prensa_externa  FROM t_prensa_externa);
  12.     SELECT *
  13.     FROM t_prensa_externa;
  14. END$$
Este SP devuelve como salida una tabla conteniendo los registros que fueron borrados de la tabla. Desaparecerá cuando la conexión del usuario se cierre.

Postdata: Los códigos que te había puesto antes tenían algunos errores de sintaxis.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #5 (permalink)  
Antiguo 02/03/2011, 08:56
 
Fecha de Ingreso: noviembre-2009
Mensajes: 226
Antigüedad: 14 años, 5 meses
Puntos: 19
Respuesta: Procedimientos almacenados mysql

Muchas gracias gnzsoloyo... El stored procedure funciona perfectamente, pero tengo un problema al ejecutarlo...

Lo ejecuto de la siguiente forma:
Código MySQL:
Ver original
  1. call eliminaPrensaExterna();

Pero no funciona... Me devuelve el error: #1312 - PROCEDURE bbdd.eliminaPrensaExterna can't return a result set in the given context

¿Me puedes ayudar? He buscado, y hay gente que lo ha solucionado cambiando la sentencia de conexión a BBDD...

Muchas gracias.
  #6 (permalink)  
Antiguo 02/03/2011, 09:09
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Procedimientos almacenados mysql

Cita:
#1312 - PROCEDURE bbdd.eliminaPrensaExterna can't return a result set in the given context
Este es un tema para el Foro de PHP, pero te puedo dar un tip previo: Eso sucede cuando usas las funciones MySQL de PHP como mysql_query(), y lo que debes usar es el modelo OO, que es el MySQLI.
El problema sucede porque la tabla devuelta por una consulta debe ser una tabla real en el caso del mysql_query(), y no es el caso, porque la fuente de datos no es una consulta en buffer de consultas sino que proviene de un stored procedure. En ese caso, la otra librería (MYSQLI) si puede operar contra SP.

SI el lenguaje fuese VB.Net o C#.net, por ejemplo, este problema no existiría.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #7 (permalink)  
Antiguo 02/03/2011, 09:15
 
Fecha de Ingreso: noviembre-2009
Mensajes: 226
Antigüedad: 14 años, 5 meses
Puntos: 19
Respuesta: Procedimientos almacenados mysql

Gracias gnzsoloyo, pero el problema está en que este SP lo estoy ejecutando directamente sobre phpMyAdmin...

Miraré lo que comentas sobre MySQLi.

Gracias de nuevo.
  #8 (permalink)  
Antiguo 02/03/2011, 09:44
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Procedimientos almacenados mysql

Es muy probable que phpMyAdmin esté usando internamente precisamente esa librería. No te olvides que es una interfase programada en PHP...
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #9 (permalink)  
Antiguo 04/03/2011, 01:31
 
Fecha de Ingreso: noviembre-2009
Mensajes: 226
Antigüedad: 14 años, 5 meses
Puntos: 19
Respuesta: Procedimientos almacenados mysql

Solucionado, muchas gracias gnzsoloyo.

El problema era un bug de phpMyAdmin, pero he actualizado y ya está :D

Gracias por tu inestimable ayuda!

Etiquetas: procedimiento, almacenar
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 00:08.