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

Ayuda para crear un procedimiento

Estas en el tema de Ayuda para crear un procedimiento en el foro de Mysql en Foros del Web. Hola. Ante todo muchas gracias. Estoy intentando crear un procedimiento en MySQL 5.0 , pero me devuelve este error: "Variable or condition declaration after cursor ...
  #1 (permalink)  
Antiguo 18/03/2009, 03:53
 
Fecha de Ingreso: febrero-2008
Mensajes: 37
Antigüedad: 16 años, 2 meses
Puntos: 0
Ayuda para crear un procedimiento

Hola.

Ante todo muchas gracias.

Estoy intentando crear un procedimiento en MySQL 5.0 , pero me devuelve este error:

"Variable or condition declaration after cursor or handler declaration"

Este es el código del procedimiento. A ver si alguien me puede decir algo.



************************************************** ***************
CREATE PROCEDURE `C_MUNICIPIOS`()
NOT DETERMINISTIC
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE C1 CURSOR FOR SELECT C_PROVINCIA, C_MUNICIPIO FROM MUNICIPIOS;
DECLARE PROVINCIA VARCHAR(5);
DECLARE MUNICIPIO VARCHAR(5);
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;

OPEN C1;

REPEAT
FETCH C1 INTO PROVINCIA, MUNICIPIO;

IF NOT DONE THEN
UPDATE `municipios`
SET C_MUNICIPIO=PROVINCIA & MUNICIPIO
WHERE C_PROVINCIA=PROVINCIA AND C_MUNICIPIO=MUNICIPIO;
END IF
UNTIL DONE END REPEAT;
END;

************************************************** ***************

Bueno, espero que alguien me diga porque ocurre esto.
Muchas gracias a todos de antemano.
  #2 (permalink)  
Antiguo 18/03/2009, 06:20
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, 4 meses
Puntos: 2658
Respuesta: Ayuda para crear un procedimiento

Dos errores de sintaxis y uno de proceso:
1. No declaraste la variable DONE. Debe ser declarada e inicializada a cero.
2. El END IF lleva cierre de sentencia porque es una estructura.

El error de proceso se verá cuando lo corras: Si estás haciendo un FETCH de una tabla implica que la estás leyendo, por lo tanto no puedes escribirle nada. Tiene en ese momento un bloqueo de escritura a nivel de tabla, entre otras cosas porque MySQL no puede saber si lo que vas a modificar no va a afectar el filtro que estás usando para seleccionar.
Me explico: Si el WHERE busca el valor X en un campo, obtiene un conjunto de registros, pero si la misma acción lo modifica a ese campo ¿cómo puede estar leyéndolo si ya no cumple con la condición de filtro? ¿En qué estado se encuentra, lo lee o no? Es un problema de consistencia. Por eso no se permiten escrituras de una tabla en proceso de lectura.
Tienes que crear una tabla intermedia y luego usar esa tabla para actualizar la MUNICIPIOS.
El código quedaría:
Código sql:
Ver original
  1. DELIMITER $$
  2.  
  3. DROP PROCEDURE IF EXISTS `C_MUNICIPIOS` $$
  4. CREATE PROCEDURE `C_MUNICIPIOS`()
  5. NOT DETERMINISTIC
  6. SQL SECURITY DEFINER
  7. COMMENT ''
  8. BEGIN
  9.   DECLARE PROVINCIA VARCHAR(5);
  10.   DECLARE MUNICIPIO VARCHAR(5);
  11.   DECLARE DONE INT DEFAULT 0;
  12.   DECLARE C1 CURSOR FOR SELECT C_PROVINCIA, C_MUNICIPIO FROM MUNICIPIOS;
  13.   DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
  14.   OPEN C1;
  15.   REPEAT
  16.     FETCH C1 INTO PROVINCIA, MUNICIPIO;
  17.     IF NOT DONE THEN
  18.       UPDATE `municipios`
  19.       SET C_MUNICIPIO=PROVINCIA & MUNICIPIO
  20.       WHERE C_PROVINCIA=PROVINCIA AND C_MUNICIPIO=MUNICIPIO;
  21.     END IF;
  22.   UNTIL DONE END REPEAT;
  23. END $$
  24.  
  25. DELIMITER ;
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #3 (permalink)  
Antiguo 18/03/2009, 16:25
 
Fecha de Ingreso: febrero-2008
Mensajes: 37
Antigüedad: 16 años, 2 meses
Puntos: 0
Respuesta: Ayuda para crear un procedimiento

Muchas gracias gnzsoloyo por contestar.

Con todo esto se demuestra que soy un pringao jejejeje, y que llevo mucho tiempo sin tocar nada de sql porque lo del IF y el DONE por ejemplo se me habia pasado, ahora, lo de actualizar una tabla sobre la misma que estoy haciendo una selección, no lo sabia.

Bueno, has comentado que deberia de hacer una tabla intermedia, pero observo que en tu código eso no lo haces tampoco, asi que: ¿cómo debería de crear dicha tabla?

Una vez más, MIL GRACIAS.
  #4 (permalink)  
Antiguo 19/03/2009, 05:54
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, 4 meses
Puntos: 2658
Respuesta: Ayuda para crear un procedimiento

No me quería alejar de la explicación, por lo que simplemente modifiqué lo que ya habías hecho.
En realidad, para mantener el ejemplo dentro de lo ya escrito, la cosa sería mas o menos así:

Código sql:
Ver original
  1. DELIMITER $$
  2.  
  3. DROP PROCEDURE IF EXISTS `C_MUNICIPIOS` $$
  4. CREATE PROCEDURE `C_MUNICIPIOS`()
  5. NOT DETERMINISTIC
  6. SQL SECURITY DEFINER
  7. COMMENT ''
  8. BEGIN
  9.   DECLARE PROVINCIA VARCHAR(5);
  10.   DECLARE MUNICIPIO VARCHAR(5);
  11.   DECLARE DONE INT DEFAULT 0;
  12.   DECLARE C1 CURSOR FOR SELECT C_PROVINCIA, C_MUNICIPIO FROM MUNICIPIOS_TEMP;
  13.   DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
  14.  
  15.   /*Borra la tabla temporal si existe*/
  16.   DROP TABLE IF EXISTS MUNICIPIOS_TEMP;
  17.  
  18.   /* Crea la tabla nuevamente con el contenido necesario */
  19.   CREATE TABLE MUNICIPIOS_TEMP AS
  20.   SELECT C_PROVINCIA, C_MUNICIPIO FROM MUNICIPIOS;
  21.   OPEN C1;
  22.   REPEAT
  23.     FETCH C1 INTO PROVINCIA, MUNICIPIO;
  24.     IF NOT DONE THEN
  25.     UPDATE `municipios`
  26.       SET C_MUNICIPIO=CONCAT(PROVINCIA,MUNICIPIO)
  27.       WHERE C_PROVINCIA=PROVINCIA AND C_MUNICIPIO=MUNICIPIO;
  28.     END IF;
  29.   UNTIL DONE END REPEAT;
  30.   CLOSE C1;
  31.   /*Borra la tabla temporal*/
  32.   DROP TABLE IF EXISTS MUNICIPIOS_TEMP;
  33.  
  34. END $$
  35.  
  36. DELIMITER ;

Eso debería ser suficiente. Como el cursor pasa a ser sinónimo de la sentencia, y comienza a operar recién al ser abierto, ya no está leyendo la tabla origen, sino la recién creada.

Notas:
1. No te olvides de cerrar el cursor para poder borrar la tabla. Los cursores no deben permanecer abiertos si no los necesitas más.

2. La sentencia DELIMITER sirve para cambiar momentáneamente el fin del sentencia para poder cargar el SP por conosola, o bien en una interfaz del tipo MySQL Query Browser.
__________________
¿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 24/03/2009, 02:02
 
Fecha de Ingreso: febrero-2008
Mensajes: 37
Antigüedad: 16 años, 2 meses
Puntos: 0
Respuesta: Ayuda para crear un procedimiento

Buenas.

Realicé el procedimiento como me sugirió "gnzsoloyo" pero me daba el mismo error: "Variable or condition declaration after cursor or handler declaration", y no consigo saber porque me da este error. Asi que me puse a pensar para poder hacer la misma operación pero de forma más sencialla sin tener que crear una tabla temporal intermedia, pero me continua devolviendo el mismo error.

el codigo que tengo actualmente es:


CREATE PROCEDURE `new_proc`()
NOT DETERMINISTIC
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE DONE INT DEFAULT O;
DECLARE C1 CURSOR FOR SELECT C_PROVINCIA, C_MUNICIPIO, C_POSTAL FROM MUNICIPIOS;
DECLARE PROVINCIA VARCHAR(5);
DECLARE MUNICIPIO VARCHAR(5);
DECLARE CP VARCHAR(5);

DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;


OPEN C1;

REPEAT
FETCH C1 INTO PROVINCIA, MUNICIPIO, CP ;

IF NOT DONE THEN

UPDATE `municipios`
SET C_MUNICIPIO=CONCAT(PROV,MUNI)
WHERE C_PROVINCIA=PROV AND C_POSTAL=CP
END IF
UNTIL DONE END REPEAT;

END ;


¿Alguien sabe por qué da el error: "Variable or condition declaration after cursor or handler declaration"?


Un saludo.
  #6 (permalink)  
Antiguo 25/03/2009, 07:04
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, 4 meses
Puntos: 2658
Respuesta: Ayuda para crear un procedimiento

Porque los cursores se declaran después de todas las variables y los handlers después de todas las declaraciones. No se pueden crear variable luego de declarar un HANDLER. Nunca.
Código sql:
Ver original
  1. CREATE PROCEDURE `new_proc`()
  2. NOT DETERMINISTIC
  3. SQL SECURITY DEFINER
  4. COMMENT ''
  5. BEGIN
  6.    DECLARE DONE INT DEFAULT O;
  7.    DECLARE PROVINCIA VARCHAR(5);
  8.    DECLARE MUNICIPIO VARCHAR(5);
  9.    DECLARE CP VARCHAR(5);
  10.    DECLARE C1 CURSOR FOR SELECT C_PROVINCIA, C_MUNICIPIO, C_POSTAL FROM MUNICIPIOS;
  11.    DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
  12.  
  13.  
  14.    OPEN C1;
  15.  
  16.    REPEAT
  17.    FETCH C1 INTO PROVINCIA, MUNICIPIO, CP ;
  18.       IF NOT DONE THEN
  19.          UPDATE `municipios`
  20.          SET C_MUNICIPIO=CONCAT(PROV,MUNI)
  21.          WHERE C_PROVINCIA=PROV AND C_POSTAL=CP;
  22.       END IF;
  23.    UNTIL DONE END REPEAT;
  24.  
  25. END ;
__________________
¿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 25/03/2009, 07:28
 
Fecha de Ingreso: febrero-2008
Mensajes: 37
Antigüedad: 16 años, 2 meses
Puntos: 0
Respuesta: Ayuda para crear un procedimiento

Muchas gracias gnzsoloyo, eso era lo que me pasaba, no sabia lo del orden de las declaraciones.

Ya se puede daro por cerrado este hilo.

De nuevo mil gracia gnzsoloyo y un saludo a todos.
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 07:46.