Ir al contenido


Foto

Duda con trigger


  • Por favor identifícate para responder
5 respuestas en este tema

#1 santiago14

santiago14

    Advanced Member

  • Miembros
  • PipPipPip
  • 334 mensajes
  • LocationCerrillos - Salta - Argentina

Escrito 16 agosto 2014 - 10:42

Buenas, les comento.

Tengo una tabla: Lotes

nro_lote:integer; (PK)
dimension:double precision;
estado_lote:varchar(50)


Un trigger sobre la tabla

CREATE trigger asociar_lote_cliente for lotes
active before update position 0
AS

begin
  /* Solamente podemos asociar un cliente con un lote que esté DISPONIBLE */
  if (new.estado_lote = 'OCUPADO' and old.estado_lote = 'OCUPADO') then
  begin
    exception lote_no_disponible;
   
  end
end


Si queremos asociar un lote con un cliente, el mismo debe estar DISPONIBLE.
Hasta aquí todo bien, el trigger solamente me va a dejar pasar si el lote está disponible.

Resulta que ahora, por otra parte del software, se quiere modificar la dimensión del lote (que está en m2). Claramente eso no tiene nada que ver con el estado del lote.
Hago:

Update lotes set dimension = 350
Where nro_lote = 12


Al hacer esto, el trigger de mas arriba cancela la operación indicándome que el lote no está disponible.
El trigger se ejecuta "before", y en el update no estoy enviado ningún valor para el campo "estado_lote", por lo cual debería dejar que se haga la actualización sin problemas.
Lo que veo es que new y old tienen el mismo valor, sino no habría forma de que el if me de verdadero.
Esto es lo que me confunde... o yo estoy mal con esto o cambiaron las reglas de los triggers sin avisar. Se supone, que en este caso, el valor para new.estado_lote debería ser NULL o algo parecido pues no se actúa sobre él en el Update... Bah, no se.
Uso Firebird 2.5 y Delphi XE5.

Que alguien aclare please....

Gracias.
  • 0

#2 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 832 mensajes
  • LocationMisiones, Argentina

Escrito 16 agosto 2014 - 01:12

NEW.Nombre_campo y OLD.Nombre_campo son respectivamente el valor que se intenta ingresar al campo Nombre_Campo y el valor que se encuentra almacenado. Preguntar por NEW.Nombre_Campo = OLD_Nombre_Campo creo que sería algo como decir, no modifico en nada con la operación que estoy realizando.
Yo creo que deberías preguntar solo por si Estado_lote es 'OCUPADO' o no (Quizá OLD.Estado_Lote), eso es todo. Pero si OLD.Dimension <> NEW.Dimension la excepción no se lleve a cabo.
No sé si me explico bien, pero creo que la pregunta debería incluir al estado de Dimension y así evitar que la excpeción se lleve a cabo cuando no sea necesario.

Saludos.

  • 0

#3 santiago14

santiago14

    Advanced Member

  • Miembros
  • PipPipPip
  • 334 mensajes
  • LocationCerrillos - Salta - Argentina

Escrito 16 agosto 2014 - 01:35

He cambiado el trigger a lo siguiente:


CREATE trigger asociar_lote_cliente for lotes
active before update position 0
AS
--declare variable estado_lote varchar(50);
begin
  /* Solamente podemos asociar un cliente con un lote que esté DISPONIBLE */
  if (new.estado_lote = 'OCUPADO') then
  begin
    exception lote_no_disponible;
   
  end
end


Cuando hago

UPDATE lotes SET dimension = 350
WHERE nro_lote = 12


El trigger sigue impidiendo que actualice la dimensión.
Claramente no le estoy enviando nada en new.estado_lote, sin embargo, entiende que new.estado_lote = 'OCUPADO' cuando no es así.

Saludos. Esto es medio raro... ¿no?


  • 0

#4 santiago14

santiago14

    Advanced Member

  • Miembros
  • PipPipPip
  • 334 mensajes
  • LocationCerrillos - Salta - Argentina

Escrito 16 agosto 2014 - 01:42

Para echar un poco mas de luz, un lote puede asignarse a un cliente cuando:
El viejo estado es DISPONIBLE. Obviamente esto se aplica cuando estoy tratando de actualizar ese campo en particular.
Pero resulta que también es factible actualizar otros, independientemente del estado (caso de la dimensión) Podría estar OCUPADO o DISPONIBLE e igual actualizar su  dimensión.
He aquí mi dilema. No quiere hacerlo con el trigger expresado de esa forma.

Lo que no me queda claro es porque el Update envía un valor para new.estado_lote cuando ese campo no está participando. Lo lógico, creo yo, sería que new.estado_lote = null (para este caso particular) bah.. no se.

  • 0

#5 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 16 agosto 2014 - 01:46

He cambiado el trigger a lo siguiente:


CREATE trigger asociar_lote_cliente for lotes
active before update position 0
AS
--declare variable estado_lote varchar(50);
begin
  /* Solamente podemos asociar un cliente con un lote que esté DISPONIBLE */
  if (new.estado_lote = 'OCUPADO') then
  begin
    exception lote_no_disponible;
   
  end
end


Cuando hago

UPDATE lotes SET dimension = 350
WHERE nro_lote = 12


El trigger sigue impidiendo que actualice la dimensión.
Claramente no le estoy enviando nada en new.estado_lote, sin embargo, entiende que new.estado_lote = 'OCUPADO' cuando no es así.

Saludos. Esto es medio raro... ¿no?



Eso no es raro, es lo que le estás diciendo que haga, que siempre que esté ocupado lance la excepción, lo que deberías es incluir el campo que asigna al cliente en el trigger, suponiendo que el lote se asigna al cliente por el ID del cliente,  sería algo así:


begin
  /* Solamente podemos asociar un cliente con un lote que esté DISPONIBLE */
  if ((new.estado_lote = 'OCUPADO') AND
  (NEW.ID_CLIENTE <> OLD.ID_CLIENTE)) then
  begin
    exception lote_no_disponible;
   
  end
end


Saludos.


  • 0

#6 santiago14

santiago14

    Advanced Member

  • Miembros
  • PipPipPip
  • 334 mensajes
  • LocationCerrillos - Salta - Argentina

Escrito 16 agosto 2014 - 03:10

Gracias Wilson, por ahí venía la mano.
No recordaba algunos conceptos básicos de los Triggers....

Gracias de nuevo.

Santiago.
  • 0




IP.Board spam blocked by CleanTalk.