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

Echadme una mano con triggers, estoy aprendiendo

Estas en el tema de Echadme una mano con triggers, estoy aprendiendo en el foro de Oracle en Foros del Web. Pues a ver si alguno de vosotros me echa una mano con esto. Tengo 2 tablas, y se trata de hacer un trigger que si ...
  #1 (permalink)  
Antiguo 09/03/2010, 10:42
Avatar de manurodri189  
Fecha de Ingreso: octubre-2006
Ubicación: Toledo
Mensajes: 76
Antigüedad: 13 años
Puntos: 1
Echadme una mano con triggers, estoy aprendiendo

Pues a ver si alguno de vosotros me echa una mano con esto.

Tengo 2 tablas, y se trata de hacer un trigger que si se actualiza una, tenga que hacer un registro en otra, con la hora de modificación, el valor anterior y el nuevo, y poco más.

Pero he hecho el trigger, y me dice errores de compilación, osea que está mal. Me vuelvo loco con esto, y tiene pinta de ser chorrada, pero no doy con la tecla.

Hasta ahora he hecho esto, pero vamos que parece que no funciona el trigger.

Código:
CREATE TABLE Cuenta (nro_cuenta varchar(10),
balance integer,
PRIMARY KEY(nro_cuenta));
 
CREATE TABLE Transaccion(nro_cuenta varchar(10),
hora_mod date,
id_cliente varchar(10),
ant_balance integer,
act_balance integer,
PRIMARY KEY(nro_cuenta,hora_mod));
 
CREATE OR REPLACE TRIGGER actualizar
AFTER UPDATE ON Cuenta
BEGIN
    INSERT INTO Transaccion
    (hora_mod, ant_balance, act_balance)
    VALUES(SYSDATE, OLD.balance, NEW.balance)
END actualizar;
Salu2
  #2 (permalink)  
Antiguo 09/03/2010, 12:08
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 10 años, 8 meses
Puntos: 360
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Si en la tabla transaccion lleva un primary key, por defecto es not null y es necesario incluirlo en cualquier inserciòn.

Con respecto al trigger faltan algunos detalles... como el for each row

Código SQL:
Ver original
  1. SQL> CREATE OR REPLACE TRIGGER actualizar
  2. AFTER UPDATE ON Cuenta
  3. FOR each ROW WHEN (NEW.balance <> 999)
  4. BEGIN
  5. INSERT INTO Transaccion (nro_cuenta,hora_mod, ant_balance, act_balance) VALUES(:OLD.nro_cuenta,SYSDATE, :OLD.balance, :NEW.balance);
  6. END actualizar;
  7. /  2    3    4    5    6    7  
  8.  
  9. Disparador creado.
  10.  
  11. SQL> SELECT *FROM cuenta;
  12.  
  13. NRO_CUENTA    BALANCE
  14. ---------- ----------
  15. 1254120            20
  16.  
  17. SQL> SELECT *FROM transaccion;
  18.  
  19. ninguna fila seleccionada
  20.  
  21. SQL> UPDATE cuenta SET balance=25;
  22.  
  23. 1 fila actualizada.
  24.  
  25. SQL> SELECT *FROM transaccion;
  26.  
  27. NRO_CUENTA HORA_MOD ID_CLIENTE ANT_BALANCE ACT_BALANCE
  28. ---------- -------- ---------- ----------- -----------
  29. 1254120    28/07/09                     20          25

saludos
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #3 (permalink)  
Antiguo 10/03/2010, 02:46
Avatar de manurodri189  
Fecha de Ingreso: octubre-2006
Ubicación: Toledo
Mensajes: 76
Antigüedad: 13 años
Puntos: 1
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Tengo unas dudillas con respecto al codigo que me pasaste, en primer lugar esta sentencia:

(new.balance <> 999) que significa exactamente? que el nuevo balance sea diferente de 999? porque? y otra cosa el when es obligatorio?

y otra cosa, porque el : delante de NEW y OLD, y en esa sentencia no? muchas gracias tío.

Si me surgen más dudillas te puedo preguntar?

Salu2

Última edición por manurodri189; 10/03/2010 a las 02:55
  #4 (permalink)  
Antiguo 10/03/2010, 06:09
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 10 años, 8 meses
Puntos: 360
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Cita:
Tengo unas dudillas con respecto al codigo que me pasaste, en primer lugar esta sentencia:

(new.balance <> 999) que significa exactamente? que el nuevo balance sea diferente de 999? porque? y otra cosa el when es obligatorio?
creo que esto puedes probarlo tu mismo.
Si el trigger se crea con errores puedes digitar en consola SHOW ERRORS; para ver en que parte se generan.

Cita:
y otra cosa, porque el : delante de NEW y OLD, y en esa sentencia no? muchas gracias tío.
Sino estoy mal, el : en una variable indica asignación, pero para efectos de comparación no es necesaria.


saludos
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #5 (permalink)  
Antiguo 10/03/2010, 09:57
 
Fecha de Ingreso: junio-2007
Mensajes: 891
Antigüedad: 12 años, 4 meses
Puntos: 43
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Cita:
Iniciado por huesos52 Ver Mensaje

Sino estoy mal, el : en una variable indica asignación, pero para efectos de comparación no es necesaria.


saludos
Compi huesos, te confundes. La asignacion es esta :=

VAR_CODIGO := 98;

y los dos puntos tienen que ir tanto en el old como en el new

:NEW.SALARIO := :OLD.SALARIO * 10;
  #6 (permalink)  
Antiguo 10/03/2010, 10:00
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 10 años, 8 meses
Puntos: 360
Respuesta: Echadme una mano con triggers, estoy aprendiendo


manurodri189 ahí tienes tu respuesta.


Saludos
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #7 (permalink)  
Antiguo 15/03/2010, 02:56
Avatar de manurodri189  
Fecha de Ingreso: octubre-2006
Ubicación: Toledo
Mensajes: 76
Antigüedad: 13 años
Puntos: 1
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Muchas gracias, ya entendí lo del when y lo de los :.

Ahora intento lo siguiente:

Código SQL:
Ver original
  1. CREATE TABLE distancias(ruta VARCHAR(10),
  2. distancia_k INTEGER,
  3. distancia_m INTEGER,
  4. PRIMARY KEY(ruta));
  5.  
  6. Tabla creada.
  7.  
  8.  
  9. CREATE OR REPLACE TRIGGER up_km
  10. AFTER UPDATE ON distancias ON distancia_k
  11. FOR each ROW
  12. BEGIN
  13. UPDATE transaccion SET distancia_m=:NEW.distancia_k*0.621371;
  14. END up_km;
  15. /

Este trigger lo que hace es si se actualiza la distancia en km automaticamente lo pone en millas. Pero no se como acceder en esta linea al altributo de la tabla:

Código SQL:
Ver original
  1. AFTER UPDATE ON distancias ON distancia_k

Se supone que si inserto una nueva fila con km o millas, tiene que actualizar el otro atributo, eso si que no se por donde cogerlo. Muchas gracias.

Salu2
  #8 (permalink)  
Antiguo 15/03/2010, 04:26
Avatar de manurodri189  
Fecha de Ingreso: octubre-2006
Ubicación: Toledo
Mensajes: 76
Antigüedad: 13 años
Puntos: 1
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Bueno, he leido un tutorial que me he bajado muy chulo, y he hecho lo siguiente:

Código SQL:
Ver original
  1. CREATE OR REPLACE TRIGGER up_km
  2. AFTER UPDATE OF distancia_k, distancia_m ON distancias
  3. FOR each ROW
  4. BEGIN
  5. IF UPDATING ('distancia_k') THEN UPDATE distancias SET distancia_m=:NEW.distancia_k*0.621371;
  6. ELSIF UPDATING ('distancia_m') THEN UPDATE distancias SET distancia_k=:NEW.distancia_m*1.609344;
  7. END IF;
  8. END up_km;

Pero al hacer un set, da problemas de tablas mutantes, ahi si que no tengo ni idea de como solucionarlo.

Salu2
  #9 (permalink)  
Antiguo 15/03/2010, 06:53
 
Fecha de Ingreso: junio-2007
Mensajes: 891
Antigüedad: 12 años, 4 meses
Puntos: 43
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Las tablas mutantes en algunos casos tienen solucion, pero antes hay algo que no veo.

¿ haces un update sin where ?

THEN UPDATE distancias SET distancia_m=:NEW.distancia_k*0.621371;
THEN UPDATE distancias SET distancia_k=:NEW.distancia_m*1.609344;
  #10 (permalink)  
Antiguo 15/03/2010, 07:18
Avatar de manurodri189  
Fecha de Ingreso: octubre-2006
Ubicación: Toledo
Mensajes: 76
Antigüedad: 13 años
Puntos: 1
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Pues si, no? se supone que lo que quiero hacer es modificar la misma fila que me llegó, y solo tengo una, porque si pusiera el where como distingo la fila?

Salu2
  #11 (permalink)  
Antiguo 15/03/2010, 07:44
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 10 años, 8 meses
Puntos: 360
Respuesta: Echadme una mano con triggers, estoy aprendiendo

manurodri189

Con ese update vas a modificar todas las filas de tu tabla.

debes poner el where para distinguir la ruta.
Ademas, puedes hacerlo en una misma sentencia update.

Código SQL:
Ver original
  1. UPDATE distancias
  2. SET
  3. distancia_m=:NEW.distancia_k*0.621371,
  4. distancia_k=:NEW.distancia_m*1.609344
  5. WHERE ruta=:OLD.ruta;
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #12 (permalink)  
Antiguo 15/03/2010, 09:29
Avatar de manurodri189  
Fecha de Ingreso: octubre-2006
Ubicación: Toledo
Mensajes: 76
Antigüedad: 13 años
Puntos: 1
Respuesta: Echadme una mano con triggers, estoy aprendiendo

No podría ponerlo en la misma sentencia no? osea, si quiero actualizar los km, entonces se debe cambiar solo las millas, y viceversa, si me viene un parametro null en las millas o km eso no iria, que no?

Salu2
  #13 (permalink)  
Antiguo 15/03/2010, 13:17
 
Fecha de Ingreso: junio-2007
Mensajes: 891
Antigüedad: 12 años, 4 meses
Puntos: 43
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Cita:
Iniciado por huesos52 Ver Mensaje
manurodri189

Con ese update vas a modificar todas las filas de tu tabla.

debes poner el where para distinguir la ruta.
Ademas, puedes hacerlo en una misma sentencia update.

Código SQL:
Ver original
  1. UPDATE distancias
  2. SET
  3. distancia_m=:NEW.distancia_k*0.621371,
  4. distancia_k=:NEW.distancia_m*1.609344
  5. WHERE ruta=:OLD.ruta;
Compi, ese update me dá que no funcionaria. Si no estoy equivocado ese trigger estaría saltando de manera infinita o daría error por tabla mutante.

Creo que lo correcto sería algo parecido a esto:

if UPDATING distancia_k THEN
:new.distancia_m=:NEW.distancia_k*0.621371;
ELSIF UPDATING distancia_m THEN
:new.distancia_k=:NEW.distancia_m*1.609344;
end if;

Todo es probar.

Ya nos dirás.
  #14 (permalink)  
Antiguo 15/03/2010, 13:23
Avatar de manurodri189  
Fecha de Ingreso: octubre-2006
Ubicación: Toledo
Mensajes: 76
Antigüedad: 13 años
Puntos: 1
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Pero así es como yo lo tenia, y da problemas de tablas mutantes.

Salu2
  #15 (permalink)  
Antiguo 15/03/2010, 14:28
 
Fecha de Ingreso: junio-2007
Mensajes: 891
Antigüedad: 12 años, 4 meses
Puntos: 43
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Cita:
Iniciado por manurodri189 Ver Mensaje
Pero así es como yo lo tenia, y da problemas de tablas mutantes.

Salu2
Ahora me doy cuenta de que es posible ya que o bien actualizas un campo o bien el otro.

Mmmmmmmmmmm, mala solucion...........

Tengo una idea ¿ como funcionaria un AFTER UPDATE para un campo y un BEFORE UPDATE para el otro con un AUTONOMOUS TRANSACTION en cada uno ?, pero le doy una pensada a ver si se me ocurre algo mas decente y lo comentamos, ahora me voy a cenar que la parienta me va a poner la almohada en la bañera.........

Mañana seguimos.
  #16 (permalink)  
Antiguo 15/03/2010, 16:32
Avatar de manurodri189  
Fecha de Ingreso: octubre-2006
Ubicación: Toledo
Mensajes: 76
Antigüedad: 13 años
Puntos: 1
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Eso de AUTONOMOUS TRANSACTION no se ni lo que es xDDD, voy a investigar a ver que sale.

Salu2
  #17 (permalink)  
Antiguo 16/03/2010, 05:13
 
Fecha de Ingreso: junio-2007
Mensajes: 891
Antigüedad: 12 años, 4 meses
Puntos: 43
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Hoy tengo un dia muy feo en el curro, a ver si a ultima hora le puedo dar una vuelta a este tema.
  #18 (permalink)  
Antiguo 16/03/2010, 06:45
Avatar de manurodri189  
Fecha de Ingreso: octubre-2006
Ubicación: Toledo
Mensajes: 76
Antigüedad: 13 años
Puntos: 1
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Cita:
Iniciado por jc3000 Ver Mensaje
Hoy tengo un dia muy feo en el curro, a ver si a ultima hora le puedo dar una vuelta a este tema.
No te preocupes tio, y gracias por todo.

Salu2
  #19 (permalink)  
Antiguo 16/03/2010, 13:40
 
Fecha de Ingreso: junio-2007
Mensajes: 891
Antigüedad: 12 años, 4 meses
Puntos: 43
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Cita:
Iniciado por manurodri189 Ver Mensaje
No te preocupes tio, y gracias por todo.

Salu2
Pues no, no he podido, a ver si mañana estoy mas tranquilo.

Te informo pa que sepas que sigo este tema, me parece un reto.......
  #20 (permalink)  
Antiguo 16/03/2010, 14:40
Avatar de manurodri189  
Fecha de Ingreso: octubre-2006
Ubicación: Toledo
Mensajes: 76
Antigüedad: 13 años
Puntos: 1
Respuesta: Echadme una mano con triggers, estoy aprendiendo

De verdad que no te tienes por que preocupar eh. Pero vamos si te parece un reto entonces me callo, pero si no, puedes dejarlo tranquilamente.

Salu2
  #21 (permalink)  
Antiguo 17/03/2010, 04:26
 
Fecha de Ingreso: junio-2007
Mensajes: 891
Antigüedad: 12 años, 4 meses
Puntos: 43
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Si los dos campos no se actualizen a la vez ( no he probado esa casuistica ) a lo mejor te valdría esto:

Cita:
SQL*Plus: Release 8.0.5.0.0 - Production on Mié Mar 17 11:23:32 2010

(c) Copyright 1999 Oracle Corporation. All rights reserved.


Conectado a:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> CREATE TABLE distancias (ruta varchar(10),
2 distancia_k integer,
3 distancia_m integer )
4 /

Tabla creada.

SQL> insert into distancias
2 values
3 ('1',2,3)
4 /

1 fila creada.

SQL>
SQL>
SQL> commit
2 /

Validación terminada.

SQL>
SQL> insert into distancias
2 values
3 ('2',4,5)
4 /

1 fila creada.

SQL>
SQL>
SQL> commit
2 /

Validación terminada.

SQL> CREATE OR REPLACE TRIGGER up_km
2 before UPDATE Of distancia_k,distancia_m on distancias
3 FOR each row
4 begin
5 if :new.distancia_k <> :old.distancia_k THEN
6 :new.distancia_m := :NEW.distancia_k* 2;
7 elsif :new.distancia_m <> :old.distancia_m THEN
8 :new.distancia_k := :NEW.distancia_m* 4;
9 end if;
10 end;
11 /

Disparador creado.

SQL> select * from distancias
2 ;

RUTA DISTANCIA_K DISTANCIA_M
---------- ----------- -----------
1 2 3
2 4 5

SQL> update distancias
2 set distancia_k = 6
3 where ruta = '1';

1 fila actualizada.

SQL> commit;

Validación terminada.

SQL> select * from distancias;

RUTA DISTANCIA_K DISTANCIA_M
---------- ----------- -----------
1 6 12
2 4 5

SQL> drop table distancias purge;

Tabla borrada.

SQL>
  #22 (permalink)  
Antiguo 17/03/2010, 05:04
Avatar de manurodri189  
Fecha de Ingreso: octubre-2006
Ubicación: Toledo
Mensajes: 76
Antigüedad: 13 años
Puntos: 1
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Muchas gracias tio, pues seguramente si me valga, gracias por todo.

Salu2
  #23 (permalink)  
Antiguo 27/07/2010, 13:12
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 10 años, 8 meses
Puntos: 360
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Acabo de tener un problema con tablas mutantes en el uso de unos triggers y recordé este tema. Me ayudó bastante.

Considerando que he ganado un poco de habilidad en el manejo de PL (hace unos cuantos meses no tenía idea de que estaban hablando ) empecé a mirar detalladamente el problema y noté que la primera solución que dió jc3000 era la correcta y no era necesario dar tantas vueltas (Por cierto, muy ingeniosas)

Retomando el ejemplo de jc3000
Código SQL:
Ver original
  1. SQL> CREATE TABLE distancias (ruta VARCHAR(10),
  2. distancia_k INTEGER,
  3. distancia_m INTEGER )
  4. /
  5.  
  6. INSERT INTO distancias
  7. VALUES
  8. ('1',2,3)
  9. /
  10.  
  11. INSERT INTO distancias
  12. VALUES
  13. ('2',4,5)
  14. /
  15. commit;  2    3    4
  16. Tabla creada.
  17.  
  18. SQL> SQL>   2    3    4
  19. 1 fila creada.
  20.  
  21. SQL> SQL>   2    3    4
  22. 1 fila creada.
  23.  
  24. SQL> CREATE OR REPLACE TRIGGER up_km
  25.   2  BEFORE UPDATE OF distancia_k,distancia_m ON distancias
  26.   3  FOR each ROW
  27.   4  BEGIN
  28.   5  IF UPDATING ('distancia_k') THEN
  29.   6  :NEW.distancia_m := :NEW.distancia_k*2;
  30.   7  ELSIF UPDATING ('distancia_m') THEN
  31.   8  :NEW.distancia_k := :NEW.distancia_m*4;
  32.   9  END IF;
  33.  10  END;
  34.  11  /
  35.  
  36. Disparador Creado.
  37.  
  38. SQL> SELECT * FROM distancias;
  39.  
  40. RUTA       DISTANCIA_K DISTANCIA_M
  41. ---------- ----------- -----------
  42. 1                    2           3
  43. 2                    4           5
  44.  
  45. SQL> UPDATE distancias
  46. SET distancia_k = 6
  47. WHERE ruta = '1';  2    3
  48.  
  49. 1 fila actualizada.
  50.  
  51. SQL> SELECT * FROM distancias;
  52.  
  53. RUTA       DISTANCIA_K DISTANCIA_M
  54. ---------- ----------- -----------
  55. 1                    6          12
  56. 2                    4           5

Creo que el problema de manurodri189 era que en vez de asignar los valores a las variables :NEW lo hacía pero en la ejecución de una sentencia update de la misma tabla que ejecuta el trigger (Por ello el error de tablas mutantes) y no como inicialmente se lo recomendaba jc3000.

Por cierto... me ha gustado mucho el tema de AUTONOMOUS TRANSACTION que de seguro me va a ser muy util para un proyecto que tengo.

Gracias por información tan valiosa jc3000
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #24 (permalink)  
Antiguo 29/07/2010, 04:57
 
Fecha de Ingreso: junio-2007
Mensajes: 891
Antigüedad: 12 años, 4 meses
Puntos: 43
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Cita:
Iniciado por huesos52 Ver Mensaje

Por cierto... me ha gustado mucho el tema de AUTONOMOUS TRANSACTION que de seguro me va a ser muy util para un proyecto que tengo.
Que tal Huesos ?

Me alegro de haber aportado algo.

Respecto a lo de " AUTONOMOUS TRANSACTION ", lee esto : MUCHO OJO CON ELLO, mal manejado es peligroso.

Como no lo tengas todo, muy, muy controlado puedes dejar en la BBDD inconsistencia de datos.

Cita:
Iniciado por huesos52 Ver Mensaje

Gracias por información tan valiosa jc3000
De nada tio, con peña como tu, da gusto venir por aquí.
  #25 (permalink)  
Antiguo 29/07/2010, 06:32
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 10 años, 8 meses
Puntos: 360
Respuesta: Echadme una mano con triggers, estoy aprendiendo

Cita:
Respecto a lo de " AUTONOMOUS TRANSACTION ", lee esto : MUCHO OJO CON ELLO, mal manejado es peligroso.

Como no lo tengas todo, muy, muy controlado puedes dejar en la BBDD inconsistencia de datos.
Lo tendré muy en cuenta.
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #26 (permalink)  
Antiguo 22/09/2010, 10:51
 
Fecha de Ingreso: septiembre-2010
Ubicación: Quito - Ecuador
Mensajes: 2
Antigüedad: 9 años, 1 mes
Puntos: 0
De acuerdo Respuesta: Echadme una mano con triggers, estoy aprendiendo

Gracias a todos los que participaron de este post me sirvio mucho en lo actualmente estoy desarrollando.

Espero pronto también colaborar en algo.

Saludos a todos.

Etiquetas: mano, trigger
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

SíEste tema le ha gustado a 1 personas




La zona horaria es GMT -6. Ahora son las 04:51.