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

TRigger. Set @var en consulta.

Estas en el tema de TRigger. Set @var en consulta. en el foro de Mysql en Foros del Web. Hola gente, Podrias ver que me falta, no consigo hacer que funcione. Código: BEGIN IF NEW.Jname != OLD.Jname THEN SET @cont = 1; SET @bds ...
  #1 (permalink)  
Antiguo 29/09/2013, 17:55
 
Fecha de Ingreso: julio-2010
Mensajes: 134
Antigüedad: 13 años, 9 meses
Puntos: 0
TRigger. Set @var en consulta.

Hola gente,

Podrias ver que me falta, no consigo hacer que funcione.

Código:

BEGIN

IF NEW.Jname != OLD.Jname THEN
SET @cont = 1;
SET @bds = ('aux,prugeok,pruebas');


    WHILE @cont <= 3 DO 
    
    	    SET @bd = (SELECT CASE 
                WHEN @bds REGEXP CONCAT('((,).*){',@cont,'}') 
                THEN SUBSTRING_INDEX(SUBSTRING_INDEX(@bds,',',@cont+1),',',-1) 
                ELSE NULL
            END);
            
           use @bd;
    	    
            SET @nombre =  (SELECT name FROM j25_users WHERE name = OLD.Jname);
            IF @nombre != NULL THEN
            	UPDATE j25_users SET name = NEW.Jname WHERE name = OLD.Jname;
            END IF;
            SET @cont = @cont + 1; 
    END WHILE; 

END IF;

END
Pues me da error en la linea de use @bd.
He comprobado lo que se guarda en @bd con un select, y funciona bien.
Pero nada. He probado tambien usando @bd.tabla.campo en las consultas siguiente, pero igualmente me falla.

Haber si me podeis ayudar!!!

Gracias!
  #2 (permalink)  
Antiguo 29/09/2013, 20:48
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: TRigger. Set @var en consulta.

MySQL no es ni Oracle, ni SQL Server. No puedes usar un valor en una variable como objeto de BBDD en forma directa.
El contenido de esas variables puede ser de cadenas de texto con nombres de bases, tablas o columnas. Pero no son bases, tablas o columnas, porque no existen esos elementos como tipos de dato.
Para que los tome como denominaciones de objetos, deben integrarse en una prepared statements, y ejecutarse con ella. De lo contrario seguirán siendo simplemente cadenas de texto, como cualquier otra. Ergo, no puedes usarlas así, al menos en MySQL.
__________________
¿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 30/09/2013, 03:35
 
Fecha de Ingreso: julio-2010
Mensajes: 134
Antigüedad: 13 años, 9 meses
Puntos: 0
Respuesta: TRigger. Set @var en consulta.

GRacias, efectivamente era eso. Hace tiempo que no hago metodos en bd, y se me mezcla oracle, SQL y MYSQL.

Ahora tengo otro problema:

Dynamic SQL is not allowed in stored function or trigger SQL=UPDATE `j25_users`.......

Estuve buscando informacion, y decian que hiciera un procedimiento donde metieran el trigger, y luego hiciera un trigger que llamara al procedimiento. Pero me sigue diciendo exactamente lo mismo

¿Una ayudita?

GRacias!


EDITO: decir que lo que he intentado hacer es cambiar la linea esa por:

SET @username = CONCAT('USE ',@bd,' ');
PREPARE stmt1 FROM @username;
EXECUTE stmt1;

Última edición por daicon; 30/09/2013 a las 04:01
  #4 (permalink)  
Antiguo 30/09/2013, 04:12
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: TRigger. Set @var en consulta.

Cita:
y decian que hiciera un procedimiento donde metieran el trigger, y luego hiciera un trigger que llamara al procedimiento.
Eso funciona en Oracle o SQL Server.
MySQL no lo permite por principios de seguridad de procesos, a fin de evitar que se utilicen como medios de sortear restricciones de permisos, e incluso para prevenir deadlocks producto de SP que llaman a tablas que afecten otros triggers.
En definitiva, no es viable..
De todos modos, la lógica del script que propones es perfectamente viable en un SP (e incluso es más seguro y simple de administrar), por lo que no se ve la necesidad de implementarlo en un TRIGGER.
Salvo que sea un requisito obligatorio de diseño, mi consejo es que implementes eso en un SP.
Los trigger tienen deben relacionarse con acciones que si o si ocurran cada vez que se hace un ABM en una tabla, y no procesos opcionales. AL menos no en MySQL.
__________________
¿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 30/09/2013, 04:19
 
Fecha de Ingreso: julio-2010
Mensajes: 134
Antigüedad: 13 años, 9 meses
Puntos: 0
Respuesta: TRigger. Set @var en consulta.

Cita:
Iniciado por gnzsoloyo Ver Mensaje
Eso funciona en Oracle o SQL Server.
MySQL no lo permite por principios de seguridad de procesos, a fin de evitar que se utilicen como medios de sortear restricciones de permisos, e incluso para prevenir deadlocks producto de SP que llaman a tablas que afecten otros triggers.
En definitiva, no es viable..
De todos modos, la lógica del script que propones es perfectamente viable en un SP (e incluso es más seguro y simple de administrar), por lo que no se ve la necesidad de implementarlo en un TRIGGER.
Salvo que sea un requisito obligatorio de diseño, mi consejo es que implementes eso en un SP.
Los trigger tienen deben relacionarse con acciones que si o si ocurran cada vez que se hace un ABM en una tabla, y no procesos opcionales. AL menos no en MySQL.
Uff, a ver... guíame un poco que me he perdido.

No entiendo eso que dices de implementar mi codigo en un SP, ya que... como controlo cuando lanzarlo? EDITO: Corrigeme si me equivoco, pero si quiero usar el SP como si fuera un trigger, tengo que llamarlo desde el codigo PHP? En el sitio donde se cambiarían los datos? Si es asi, puf... no se, no lo veo muy adecuado, al menos en mi caso.
Necesito que desde mysql se haga las modificaciones pertinentes en la BD cuando se detecte algun cambio. FIN EDICION

Mi idea de hacerlo en un trigger, es por que necesito lanzar ese codigo SIEMPRE que se modifice un campo de la tabla..

Es verdad que al principio tengo un IF, que creo que has podido pensar que a veces se ejecutara y otras no, pero no es correcto del todo, ya que, depues de ese IF, vendran otros tantos IF, los cuales comprobaran que columna se ha modificado de la tabla, y lanzar el codigo en el caso correcto.

Última edición por daicon; 30/09/2013 a las 07:51
  #6 (permalink)  
Antiguo 30/09/2013, 12:15
 
Fecha de Ingreso: julio-2010
Mensajes: 134
Antigüedad: 13 años, 9 meses
Puntos: 0
Alternativa a lanzar SP desde un Trigger

Hola,

Vengo de un hilo anterior, pero creo que es conveniente hacer otro con el problema ahora bien explicado.

Necesito buscar una alternativa que lance un SP desde un Trigger, ya que como algunos sabéis esto no esta permitido en Mysql.

Este es el codigo que tenia dentro del trigger:

Código:
BEGIN

IF NEW.Jname != OLD.Jname THEN
SET @cont = 1;
SET @bds = ('aux,prugeok,pruebas');


    WHILE @cont <= 3 DO 
    
    	    SET @bd = (SELECT CASE 
                WHEN @bds REGEXP CONCAT('((,).*){',@cont,'}') 
                THEN SUBSTRING_INDEX(SUBSTRING_INDEX(@bds,',',@cont+1),',',-1) 
                ELSE NULL
            END);
            
           SET @username = CONCAT('USE ',@bd,' ');
           PREPARE stmt1 FROM @username;
           EXECUTE stmt1;
    	    
            SET @nombre =  (SELECT name FROM j25_users WHERE name = OLD.Jname);
            IF @nombre != NULL THEN
            	UPDATE j25_users SET name = NEW.Jname WHERE name = OLD.Jname;
            END IF;
            SET @cont = @cont + 1; 
    END WHILE; 

END IF;

END
Decidi meterlo en un SP y llamarlo desde el Trigger, pero no funciona como ya sabeis.

Entonces... ¿Cual es el camino a seguir?

Necesito que se lance ese codigo cada vez que se realice un update en una tabla. Ademas, mas adelante necesito añadir mas IF, ya que necesito hacer varias comprobaciones, y segun que campo se modifice hacer una cosa u otra.

Otra pregunta. Los SP, no se pueden usar como los trigger no? y decirles que se ejecuten cuando se actulice algun campo?
Si esto es asi, que caminos me quedan?
  #7 (permalink)  
Antiguo 30/09/2013, 12:26
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: TRigger. Set @var en consulta.

No se pueden abrir dos hilos para tratar un mismo tema, especialmente cuando es una continuación del mismo planteo.
Ten paciencia. Ya te responderemos.
Yo en este momento no puedo ocuparme mucho porque estoy en horario de trabajo y en la empresa, pero de todos modos te anticipo un poco lo que te quería expresar en el otro post: Todo lo que planteas se puede implementar por un SP simplemente porque lo que haces en ese SP es mandar a hacer el UPDATE y crear el UPDATE en él, con las validaciones que estás poniendo en este TRIGGER.
En la empresa donde trabajo, toda esta lógica se resuelve en SP, incluyendo esquemas de validaciones con inserciones o updates como estos, dentro del mismo cuerpo del SP. y lo hacemos porque son directivas específicas de desarrollo a nivel empresa. No por capricho.
Esta noche te contesto, si es que no te han respondido ya para ese momento.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #8 (permalink)  
Antiguo 30/09/2013, 12:57
 
Fecha de Ingreso: julio-2010
Mensajes: 134
Antigüedad: 13 años, 9 meses
Puntos: 0
Respuesta: TRigger. Set @var en consulta.

Cita:
Iniciado por gnzsoloyo Ver Mensaje
No se pueden abrir dos hilos para tratar un mismo tema, especialmente cuando es una continuación del mismo planteo.
Ten paciencia. Ya te responderemos.
Yo en este momento no puedo ocuparme mucho porque estoy en horario de trabajo y en la empresa, pero de todos modos te anticipo un poco lo que te quería expresar en el otro post: Todo lo que planteas se puede implementar por un SP simplemente porque lo que haces en ese SP es mandar a hacer el UPDATE y crear el UPDATE en él, con las validaciones que estás poniendo en este TRIGGER.
En la empresa donde trabajo, toda esta lógica se resuelve en SP, incluyendo esquemas de validaciones con inserciones o updates como estos, dentro del mismo cuerpo del SP. y lo hacemos porque son directivas específicas de desarrollo a nivel empresa. No por capricho.
Esta noche te contesto, si es que no te han respondido ya para ese momento.
VAle gracias, no pasa nada, cuando puedas. Pense que era mejor idea. No pasa nada.

Pues no, no termino de verlo, ya que creo que me faltan algunos conceptos de como funcionan los SP.
Para mi, siempre he visto los trigger como algo para lanzar trozos de codigo depues/antes de que se produzca un update/insercio/delete en la tabla. Y una forma de hacerlo en la misma BD.
Un SP, procddimiento o funcion, nunca he tenido muy claro las diferencias, ya que lo estudie hace tiempo, pero lo veo como procesos que lanzar desde el codigo de la web, o desde dentro de otros procedimientos/funciones/triggers.

Entonces.... supongo que en algo estoy perdido, por que sigo sin ver como usar un SP, y que se lance cuando ocurre algun update (en mi caso) en la tabla que deseo.

Gracias, y contesta cuando puedas!

Última edición por daicon; 30/09/2013 a las 14:14
  #9 (permalink)  
Antiguo 01/10/2013, 06:48
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: TRigger. Set @var en consulta.

Para empezar a prepararte un modelo de SP, necesito saber una sola cosa: ¿Qué es exactamente lo que hace ese código que intentas usar?
Especialmente, necesito entender esto:
Código MySQL:
Ver original
  1. SET @bd = (SELECT CASE
  2.                 WHEN @bds REGEXP CONCAT('((,).*){',@cont,'}')
  3.                 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(@bds,',',@cont+1),',',-1)
  4.                 ELSE NULL
  5.             END);
¿Qué se supone que haces con eso? ¿Qué obtienes?
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #10 (permalink)  
Antiguo 01/10/2013, 07:51
 
Fecha de Ingreso: julio-2010
Mensajes: 134
Antigüedad: 13 años, 9 meses
Puntos: 0
Respuesta: TRigger. Set @var en consulta.

Cita:
Iniciado por gnzsoloyo Ver Mensaje
Para empezar a prepararte un modelo de SP, necesito saber una sola cosa: ¿Qué es exactamente lo que hace ese código que intentas usar?
Especialmente, necesito entender esto:
Código MySQL:
Ver original
  1. SET @bd = (SELECT CASE
  2.                 WHEN @bds REGEXP CONCAT('((,).*){',@cont,'}')
  3.                 THEN SUBSTRING_INDEX(SUBSTRING_INDEX(@bds,',',@cont+1),',',-1)
  4.                 ELSE NULL
  5.             END);
¿Qué se supone que haces con eso? ¿Qué obtienes?
Te explico ese código ya que me costo bastante dar con el.
Te explico primero lo que quiero hacer.

Tengo varias BD. Todas son similares. Hay usuarios que existen en las diferentes bd, con los mismos datos.
Tengo una BD (llamémosla Principal), con una sola tabla, donde estoy recopilando y guardando los nombres de usuarios, con sus campos principales, de todas las demás BD. Cada nombre de usuario es UNICO.

Entonces....
Cada vez que un usuario actualiza algún campo de su tabla en la BD donde se encuentra, Tengo un trigger que actualiza los campos en la BD Principal.

Hasta AQUI todo bien.

Ahora lo que necesito es que, cuando la BD principal detecta que se ha producido un UPDATE, propagar la información por las demás BD donde se encuentre ese usuario.

Entonces, lo que he hecho, como puedes ver en el código es guardar en:
@bds = ('aux,prugeok,pruebas');
El nombre de las BD que tengo (Ya que por royo de permisos en el hosting donde estoy no me permite usar las llamdas a sistema de SQL), y ese código que me preguntas, lo que hace es obtener uno a uno los nombres de las BD.
Como veras es un string separados por comas, pues las líneas de código que me has preguntado, te va devolviendo una a una las BD.
Cada vez que llamo a ese código me devuelve la siguiente, ya que veras, que tiene otras variables, como cont, etc...

----------------------

Entonces, mi idea era tener un trigger en esta BD principal con el código que puse en el primer mensaje, y ya aparecieron los problemas.



Espero haberme explicado bien!!

Gracias!
  #11 (permalink)  
Antiguo 01/10/2013, 08:02
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: TRigger. Set @var en consulta.

TEnía la sopecha de que se trataba de lago así, pero era un poquitin confuso de sintaxis.
Ahora bien, por lo que estoy viendo, sería conveniente hacer en realidad dos cosas: Un EVENT, para que se realice esa verificación en forma automática y cada cierto tiempo, y un SP invocado por el EVENT, para que realice la tarea.
De todos modos, también existe la posibilidad de hacer un esquema maestro/esclavo, para que la replica de datos se administre en forma automática, pero eso implicaría que las bases sean absolutamente idénticas, es decir, que las otras serían espejos de la primera.
¿Es posible esto último?
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #12 (permalink)  
Antiguo 01/10/2013, 08:11
 
Fecha de Ingreso: julio-2010
Mensajes: 134
Antigüedad: 13 años, 9 meses
Puntos: 0
Respuesta: TRigger. Set @var en consulta.

Cita:
Iniciado por gnzsoloyo Ver Mensaje
TEnía la sopecha de que se trataba de lago así, pero era un poquitin confuso de sintaxis.
Ahora bien, por lo que estoy viendo, sería conveniente hacer en realidad dos cosas: Un EVENT, para que se realice esa verificación en forma automática y cada cierto tiempo, y un SP invocado por el EVENT, para que realice la tarea.
De todos modos, también existe la posibilidad de hacer un esquema maestro/esclavo, para que la replica de datos se administre en forma automática, pero eso implicaría que las bases sean absolutamente idénticas, es decir, que las otras serían espejos de la primera.
¿Es posible esto último?
No, no son espejos. Si es verdad que tienen las mismas tablas y campos, pero no van a tener el mismo contenido.


Entonces, solo queda la primera opción?
No recuerdo lo que era un EVENT en SQL!!!
Pero por lo que has escrito, deduzco que algún tipo de método que se ejecuta cada X min, segundos, o algo asi? Y este llamaría al SP??

.... Crees que esto seria buena solución?
Necesito que las actualización se hagan casa instantánea... o en 1, 2, 5 segundos como mucho.

Edito: Si, ya recuerdo lo que son los EVent, es tal y como decía, digamos un programador para que lance procedimientos, etc..
El caos es que esto, aun q se pueda lanzar cada X segundos, no veo una solución eficiente, no? Es decir, el trigger que estaba haciendo era un trigger que raramente se iba a ejecutar, pero que era necesario que se hiciera la propagación de forma rápida en el momento del update.

Sin embargo, tal y como lo entiendo yo ahora, este vent, estaría comprobando cada X segundos si hay cambios.... y no lo veo eficiente.

Última edición por daicon; 01/10/2013 a las 08:22
  #13 (permalink)  
Antiguo 01/10/2013, 10:27
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: TRigger. Set @var en consulta.

Pues visto y considerando que la cosa se te complica, y para no afectar la funcionalidad de la base, vamos a intentarlo de una forma simple.
partamos que si estás harcodeando el nombre de las bases, y siendo innecesario no sólo cambiar de base, sino también que ni siquiera tiene sentido iterar, podemos intentarlo mas o menos así:
Código MySQL:
Ver original
  1.     SET @cont = 0;
  2.     IF NEW.Jname != OLD.Jname THEN
  3.         IF (SELECT COUNT(*) FROM aux.j25_users WHERE name = OLD.Jname)= 1 THEN
  4.             UPDATE aux.j25_users SET `NAME` = NEW.Jname WHERE `NAME = OLD.Jname;
  5.            SET @cont = @cont + 1;
  6.        END IF;
  7.        IF (SELECT COUNT(*) FROM prugeok.j25_users WHERE name = OLD.Jname)= 1 THEN
  8.            UPDATE prugeok.j25_users SET `NAME` = NEW.Jname WHERE `NAME = OLD.Jname;
  9.             SET @cont = @cont + 1;
  10.         END IF;
  11.         IF (SELECT COUNT(*) FROM pruebas.j25_users WHERE name = OLD.Jname)= 1 THEN
  12.             UPDATE pruebas.j25_users SET `NAME` = NEW.Jname WHERE `NAME = OLD.Jname;
  13.            SET @cont = @cont + 1;
  14.    END IF;
  15. END
A mi entender, al hacer esa iteración te estás complicando mucho.

Incluso, si quieres saber cuál o cuales bases se actualizaron, podemos hacer esto:
Código MySQL:
Ver original
  1.     SET @cont = 0;
  2.     IF NEW.Jname != OLD.Jname THEN
  3.         IF (SELECT COUNT(*) FROM aux.j25_users WHERE name = OLD.Jname)= 1 THEN
  4.             UPDATE aux.j25_users SET `NAME` = NEW.Jname WHERE `NAME = OLD.Jname;
  5.            SET @cont = @cont + 1;
  6.        END IF;
  7.        IF (SELECT COUNT(*) FROM prugeok.j25_users WHERE name = OLD.Jname)= 1 THEN
  8.            UPDATE prugeok.j25_users SET `NAME` = NEW.Jname WHERE `NAME = OLD.Jname;
  9.             SET @cont = @cont + 3;
  10.         END IF;
  11.         IF (SELECT COUNT(*) FROM pruebas.j25_users WHERE name = OLD.Jname)= 1 THEN
  12.             UPDATE pruebas.j25_users SET `NAME` = NEW.Jname WHERE `NAME = OLD.Jname;
  13.            SET @cont = @cont + 5;
  14.    END IF;
  15. END
Esto sería lo devuelto por @cont:
Cita:
- 0: ninguna.
- 1: sólo la primera.
- 3: sólo la segunda.
- 4: la primera y la segunda.
- 5: sólo la tercera.
- 6 la primera y la tercera.
- 8: la segunda y la tercera.
- 9: Todas.
__________________
¿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; 01/10/2013 a las 10:35
  #14 (permalink)  
Antiguo 01/10/2013, 10:34
 
Fecha de Ingreso: julio-2010
Mensajes: 134
Antigüedad: 13 años, 9 meses
Puntos: 0
Respuesta: TRigger. Set @var en consulta.

Cita:
Iniciado por gnzsoloyo Ver Mensaje
Pues visto y considerando que la cosa se te complica, y para no afectar la funcionalidad de la base, vamos a intentarlo de una forma simple.
partamos que si estás harcodeando el nombre de las bases, y siendo innecesario no sólo cambiar de base, sino también que ni siquiera tiene sentido iterar, podemos intentarlo mas o menos así:
Código MySQL:
Ver original
  1.     SET @cont = 0;
  2.     IF NEW.Jname != OLD.Jname THEN
  3.         IF (SELECT COUNT(*) FROM aux.j25_users WHERE name = OLD.Jname)= 1 THEN
  4.             UPDATE aux.j25_users SET `NAME` = NEW.Jname WHERE `NAME = OLD.Jname;
  5.            SET @cont = @cont + 1;
  6.        END IF;
  7.        IF (SELECT COUNT(*) FROM prugeok.j25_users WHERE name = OLD.Jname)= 1 THEN
  8.            UPDATE prugeok.j25_users SET `NAME` = NEW.Jname WHERE `NAME = OLD.Jname;
  9.             SET @cont = @cont + 1;
  10.         END IF;
  11.         IF (SELECT COUNT(*) FROM pruebas.j25_users WHERE name = OLD.Jname)= 1 THEN
  12.             UPDATE pruebas.j25_users SET `NAME` = NEW.Jname WHERE `NAME = OLD.Jname;
  13.            SET @cont = @cont + 1;
  14.    END IF;
  15. END
A mi entender, al hacer esa iteración te estás complicando mucho.
Mmm O_o.... valeee. xD
Si que es una solución, y tengo que reconocer que no entiendo ni como NO se me ha pasado por la cabeza.

Pero si que le veo un inconveniente, y haber que me dices tu.
No solo van a ser 3 BD, van a ser mas.... como unas 15-20. ¿No es un poco..... poco elegante?

Pero vaya, que aparte de que me recomiendes otra cosa, es lo que voy a añadir por ahora.
  #15 (permalink)  
Antiguo 01/10/2013, 10:38
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: TRigger. Set @var en consulta.

Cita:
como unas 15-20. ¿No es un poco..... poco elegante?
La elegancia puede ser sacrificada en aras de la precisión.
Lo que en todo caso tienes es un problema de diseño, porque si tienes una tabla que se replica entre 20 bases distintas, entonces lo que tienes que hacer es separar ese subesquema en una base distinta, a donde todas las otras bases consulten ese dato.
Ya no es un problema de triggers o procedures. Es un tema de diseño de sistemas.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #16 (permalink)  
Antiguo 01/10/2013, 10:44
 
Fecha de Ingreso: julio-2010
Mensajes: 134
Antigüedad: 13 años, 9 meses
Puntos: 0
Respuesta: TRigger. Set @var en consulta.

Cita:
Iniciado por gnzsoloyo Ver Mensaje
La elegancia puede ser sacrificada en aras de la precisión.
Lo que en todo caso tienes es un problema de diseño, porque si tienes una tabla que se replica entre 20 bases distintas, entonces lo que tienes que hacer es separar ese subesquema en una base distinta, a donde todas las otras bases consulten ese dato.
Ya no es un problema de triggers o procedures. Es un tema de diseño de sistemas.
Vale vale, lo veo correcto y cierto.
De hecho yo mismo llevo pensando que va haber un problema de diseño.

Para que veas un poco de que se trata:
Es una web en Joomla, y queremos sincronizar en la medida de lo posibles algunos campos entre un subdominio y otro. Vaya hacer esto es joomla es un CAOS.
Pero estamos preparando esa BD principal, para que algún dia, cuando tengamos medio hacer la web a medida y tener los usuarios bien ordenados.

Pero que si, tienes razón en cuanto a que el problema ya es de diseño en si.

Una ultima cosa:
Por que pones entre comillas simples el campo name? Y por que lo has puesto en mayúscula. Alguna cosa técnica? Creo que las comillas eran por que si no los espacios no lo coge, cierto? Pero en este caso?

Por otra parte, has dejado la variable cont. ¿Por algo en concreto? o simplemente para que tenga el numero de registros cambiados?

Nada mas, y muchísimas gracias!!!
  #17 (permalink)  
Antiguo 01/10/2013, 11: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: TRigger. Set @var en consulta.

Cita:
Por que pones entre comillas simples el campo name? Y por que lo has puesto en mayúscula. Alguna cosa técnica? Creo que las comillas eran por que si no los espacios no lo coge, cierto? Pero en este caso?
No son "comillas simples", las cuales en realidad no existen sino que son serían los apóstrofos ('), sino acentos agudos (`).
Los acentos agudos se usan en MySQL (y otros DBMS) cuando debes usar nombres de objetos que contienen palabras reservadas (caso NAME), o bien caracteres ilícitos en ellos (signos +, - y cosas así), que por razones de necesidad no pueden ser normalizados.
Esos signos permiten usar ese tipo de cosas sin generar un error de sintaxis que luego no podrás diagnosticar adecuadamente porque no parecerá existir.
Algunas palabras reservadas se aceptan por compatibilidad, pero es mejor acostumbrarse a nunca usaras.
En cuanto a las mayúsculas, es un arma de doble filo: Si usas Windows, no tendrás problemas. Pero si estás usando un servidor basado en Unix (Linux, por ejemplo), tendrás problemas, porque el sistema operativo en ese caso diferencia entre mayúsculas y minúsculas.
En este último caso, tablas llamadas usuarios, uSuArios, Usuarios, y USUARIOS, se toman como tablas distintas.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #18 (permalink)  
Antiguo 01/10/2013, 11:52
 
Fecha de Ingreso: julio-2010
Mensajes: 134
Antigüedad: 13 años, 9 meses
Puntos: 0
Respuesta: TRigger. Set @var en consulta.

Cita:
Iniciado por gnzsoloyo Ver Mensaje
No son "comillas simples", las cuales en realidad no existen sino que son serían los apóstrofos ('), sino acentos agudos (`).
Los acentos agudos se usan en MySQL (y otros DBMS) cuando debes usar nombres de objetos que contienen palabras reservadas (caso NAME), o bien caracteres ilícitos en ellos (signos +, - y cosas así), que por razones de necesidad no pueden ser normalizados.
Esos signos permiten usar ese tipo de cosas sin generar un error de sintaxis que luego no podrás diagnosticar adecuadamente porque no parecerá existir.
Algunas palabras reservadas se aceptan por compatibilidad, pero es mejor acostumbrarse a nunca usaras.
En cuanto a las mayúsculas, es un arma de doble filo: Si usas Windows, no tendrás problemas. Pero si estás usando un servidor basado en Unix (Linux, por ejemplo), tendrás problemas, porque el sistema operativo en ese caso diferencia entre mayúsculas y minúsculas.
En este último caso, tablas llamadas usuarios, uSuArios, Usuarios, y USUARIOS, se toman como tablas distintas.
Vale, lo tendre muy en cuenta, algunas cosas las conocía, pero otras no!

Bueno, ahora te voy a contar una cosa que me esta pasando, que te vas a reir... y no se si tiene solución.....

Todo iba muy bien con la solución que me habias dicho hasta que he empezado a hacer pruebas reales, y me he dado cuenta del pedazo de FAIL.

Como te comente antes,
Cada BD, tiene en algunas tablas un trigger que lanza un update a la BD Principal.
Y esa a su vez lanza el trigger que hemos estado discutiendo para propagar la información a las otras BD.

¿Qué ocurre? Pues que entra en un bucle
Estas otras bd, detectan que se ha actualizado, y lanzan nuevamente el trigger para la BD principal. Menos mal que Mysql lo detecta, y me manda este error:
Can't update table 'UsuNal' in stored function/trigger because it is already used by statement which invoked this stored function/trigger

El problema es que aparece el error en la web .... joder, que cagada....
Hay forma de solucionar esto?

Ya estaba CASI solucionado!!!!!!!
  #19 (permalink)  
Antiguo 01/10/2013, 12:01
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: TRigger. Set @var en consulta.



Bueno, te has topado con uno de los problemas que precisamente debe evitarse....
No. No hay una forma de saltearse el problema. Lo único que puedes hacer es:
1) No propagar los triggers en todas las tablas. Sólo una debe hacer la tarea, y si hay otras que deban hacer lo mismo, no deben ejecutarse al mismo tiempo...
2) Ese tipo de balanceo requiere una tabla de logs, para verificar los cambios que se aplicarán, a fin de que ninguna ejecute un cambio ya realizado. En otras palabras, en alguna parte debe haber una tabla donde se pueda verificar que un cambio ya se impactó en las otras bases.

Infortunadamente, en ese escenario, la única solución práctica es el EVENT (ver manual de referencia), y su correspondiente SP. Si lo intentas por trigger en ese contexto, se producirá un desastre.
Creo que en ese caso lo mejor es que implementes la base concentradora de datos primarios.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #20 (permalink)  
Antiguo 01/10/2013, 12:17
 
Fecha de Ingreso: julio-2010
Mensajes: 134
Antigüedad: 13 años, 9 meses
Puntos: 0
Respuesta: TRigger. Set @var en consulta.

Cita:
Iniciado por gnzsoloyo Ver Mensaje


Bueno, te has topado con uno de los problemas que precisamente debe evitarse....
No. No hay una forma de saltearse el problema. Lo único que puedes hacer es:
1) No propagar los triggers en todas las tablas. Sólo una debe hacer la tarea, y si hay otras que deban hacer lo mismo, no deben ejecutarse al mismo tiempo...
2) Ese tipo de balanceo requiere una tabla de logs, para verificar los cambios que se aplicarán, a fin de que ninguna ejecute un cambio ya realizado. En otras palabras, en alguna parte debe haber una tabla donde se pueda verificar que un cambio ya se impactó en las otras bases.

Infortunadamente, en ese escenario, la única solución práctica es el EVENT (ver manual de referencia), y su correspondiente SP. Si lo intentas por trigger en ese contexto, se producirá un desastre.
Creo que en ese caso lo mejor es que implementes la base concentradora de datos primarios.
Joer.... pues la llevo buena...

Sobre el punto 1).
No puedo hacer eso, piensa que un usuario puede entrar en un subdominio, cambiar hay sus datos. Entonces necesito enviarlos a la BD principal, y luego propagarlos por las demás lo mas rápidamente posible, por si cambiaria de subdominio.

Sobre el punto 2).
Usar el Event, no sirve como solución, a no ser que su periodo sea de 1-3 segundos.
Pero eso podría afectar mucho al rendimiento? Estar comprobando cada 1-3 segundos que se ha cambiado algo en la BD principal?
  #21 (permalink)  
Antiguo 01/10/2013, 12:31
 
Fecha de Ingreso: julio-2010
Mensajes: 134
Antigüedad: 13 años, 9 meses
Puntos: 0
Respuesta: TRigger. Set @var en consulta.

Vamos ...a ver, espera... Hay algo que no entiendo, y creo que no debería de haber ese problema:

Mira el trigger que debo de poner en todas las BD:

Código:
After update

BEGIN
IF NEW.name != OLD.name THEN
UPDATE principal.UsuNa SET Jname = NEW.name WHERE Jusername = NEW.username;
END IF;
END
Y ahora el código de BD Principal que será la que propague:

Código:
BEGIN

    SET @cont = 0;
    IF NEW.Jname != OLD.Jname THEN
    
        IF (SELECT COUNT(*) FROM otra.j25_users WHERE username = OLD.Jusername AND name != NEW.Jname)= 1 THEN 
            UPDATE otra.j25_users SET NAME = NEW.Jname WHERE username = OLD.Jusername;
            SET @cont = @cont + 1;
        END IF;
        
        IF (SELECT COUNT(*) FROM pruebas.j25_users WHERE username = OLD.Jusername AND name != NEW.Jname)= 1 THEN 
            UPDATE pruebas.j25_users SET NAME = NEW.Jname WHERE username = OLD.Jusername;
            SET @cont = @cont + 1;
        END IF;
        
        IF (SELECT COUNT(*) FROM prugeok.j25_users WHERE username = OLD.Jusername AND name != NEW.Jname)= 1 THEN 
            UPDATE prugeok.j25_users SET NAME = NEW.Jname WHERE username = OLD.Jusername;
            SET @cont = @cont + 1;
        END IF;
        
    END IF;
 
END
Cuando El primer triger se ejecute, lanzara el update a la BD principal.
Este comprobara en el primer IF si ha sido cambiado el campo que necesitamos, si es asi, lanzara a las otras BD el update.
Cuando llegue a la nueva BD a ser propagada, esta se actualizará, y volverá a lanzar el update a la BD principal. PEEEERO, no entraría en el IF del segundo trigger, ya que los campos no son DIFERENTE. Por lo que no entraría en un BUCLE!!!!!

Es esto correcto?

Si estoy en lo cierto - ¿Qué esta pasando?
  #22 (permalink)  
Antiguo 01/10/2013, 12:58
 
Fecha de Ingreso: julio-2010
Mensajes: 134
Antigüedad: 13 años, 9 meses
Puntos: 0
Respuesta: TRigger. Set @var en consulta.

Buah, me respondo a mi mismo, que creo que he encontrado la solución, y es importante por si alguien en el futuro le hace falta:
Mira lo que he añadido a los trigger de las BD, es decir a los primeros trigger:

Código:


IF (NEW.name != OLD.name) && (SELECT COUNT(*) FROM nacional.UsuNacional WHERE Jname = NEW.name)= 0 THEN
UPDATE nacional.UsuNacional SET Jname = NEW.name WHERE Jusername = NEW.username;
END IF;
jijiji xD, ahora con esa condición comprueba antes de hacer el update si en la BD principal ya se hizo la actualización !!!

Bueno, por dios, espero que ya no de mas problemas, y esto de verdad se quede solucionado.


Solo te puedo agradecer nuevamente tu ayuda! De verdad! muchas gracias, es un placer poder tener en este foro a gente tan atenta y con conocimientos!!!

Etiquetas: campo, lanzar, select, set, sql, tabla, trigger, var
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 01:48.