none
Trigger Update con condiciones IF RRS feed

  • Pregunta

  • Buenas tardes, aquí nuevamente con dudas con los triggers.

    Estoy intentando hacer nuevamente un trigger, pero que en este se ejecuten 2 funciones si las condiciones se cumplen.

    Estoy intentándolo realizar de la siguiente forma:

    Create trigger FACTBIMBO
       ON FACTURAS
       AFTER UPDATE 
       AS
       IF UPDATE(ESTATUS)
       IF EXISTS (
       SELECT D.NOFACTURA,D.ESTATUS
       FROM FACTURAS D
       INNER JOIN RUTAF_FAC D1 ON (D.NOFACTURA=D1.FACTURA)
       INNER JOIN RUTAF D2 ON (D1.NORUTA=D2.NORUTA)
       WHERE D.NOFACTURA LIKE 'REMB%' AND D.ESTATUS='Entregada' AND D2.ESTATUS='Nueva')
       BEGIN
    	UPDATE FACTURAS SET ESTATUS = 'Programada' 
    	FROM  FACTURAS
    		
    	IF EXISTS (
    	SELECT D.NOFACTURA,D.ESTATUS
    	FROM FACTURAS D
    	INNER JOIN RUTAF_FAC D1 ON (D.NOFACTURA=D1.FACTURA)
    	INNER JOIN RUTAF D2 ON (D1.NORUTA=D2.NORUTA)
    	WHERE D.NOFACTURA LIKE 'REMB%' AND D.ESTATUS='Programada' AND (D2.ESTATUS='Entregada' OR D2.ESTATUS='Cerrada'))
    	UPDATE FACTURAS SET ESTATUS = 'Entregada'
    	FROM  FACTURAS
    
       END

    La idea de este trigger es la siguiente:

    Tengo un documento (Factura) de la siguiente forma resultado de la siguiente consulta:

    	SELECT D.NOFACTURA,D.ESTATUS ESTATUS_FACTURA,D2.DESCRIPCION,D2.ESTATUS ESTATUS_RUTA
    	FROM FACTURAS D
    	INNER JOIN RUTAF_FAC D1 ON (D.NOFACTURA=D1.FACTURA)
    	INNER JOIN RUTAF D2 ON (D1.NORUTA=D2.NORUTA)
    	WHERE D.NOFACTURA LIKE 'REMB%' AND D.ESTATUS='Entregada' AND D2.ESTATUS='Nueva'
    	ORDER BY D.FECHAFACTURA ASC

    Registro:

    NOFACTURA	ESTATUS_FACTURA	DESCRIPCION	                ESTATUS_RUTA
    REMB-1942	Entregada	Ruta Local. Salida Local.	Nueva

    La idea es que si Estatus_Ruta es Nueva y Estatus_Factura es Entregada, cambie el Estatus_Factura a Programada

    Pero si el Estatus_Ruta es Entregada o Cerrada y Estatus_Factura es Programada, cambie el Estatus_Factura a Entregada

    Honestamente no se si se pueda realizar con la lógica que estoy planteando, o si definitivamente estoy más que perdido con lo que intento realizar jejejeje.

    Espero puedan guiarme un poco amigos.

    De antemano muchas gracias por todo y disculpen tantas molestias; pero bien dice el dicho:

    "Prefiero ser un tonto que pregunta y no serlo para siempre".

    Saludos.


    • Editado Alejandro 0991 martes, 13 de abril de 2021 17:39 Faltó condición en la explicación
    martes, 13 de abril de 2021 17:20

Respuestas

  • Hola Alejandro 0991:

    Esto es lo mismo que tú has puesto, pero más correcto.

    ALTER trigger FACTBIMBO
       ON RUTAF
       AFTER UPDATE 
       AS
       BEGIN
    	UPDATE D SET ESTATUS = 
    			CASE
    			--CUANDO EL ESTATUS DE LA TABLA RUTAF ES NUEVA CAMBIE EL ESTATUS DE LA FACTURA REMB A PROGRAMADA
    			WHEN D2.ESTATUS='Nueva' THEN 'Programada'
    			--CUANDO EL ESTATUS DE LA FACTURA REMB ES PROGRAMADA Y EL ESTATUS DE LA RUTAF ES ENTREGADA, CAMBIE EL ESTATUS DE LA FACTURA REMB A ENTREGADA
    			WHEN D.ESTATUS='Programada' AND D2.ESTATUS='Entregada' THEN 'Entregada'
    			--CUANDO EL ESTATUS LA RUTAF ES CERRADA, DEJE EL ESTATUS DE LA FACTURA REMB A ENTREGADA
    			WHEN D2.ESTATUS='Cerrada' THEN 'Entregada'
    			ELSE D.ESTATUS
    			END
    	FROM  FACTURAS D 
    	LEFT JOIN RUTAF_FAC D1 ON (D.NOFACTURA=D1.FACTURA)
    	LEFT JOIN INSERTED D2 ON (D1.NORUTA=D2.NORUTA)
    	WHERE LEFT(D.NOFACTURA,4) = 'REMB'; 
       END

    Aún me sigue rechinando los oídos, el uso de LEFT JOIN en un trigger de la tabla RutaF.

    Si las facturas a cambiar el estado, tienen que tener una ruta, porque es lo que hacemos, en función de ella, debería de ser INNER JOIN.

    Pero salvo eso, lo demás esta ok.

    • Marcado como respuesta Alejandro 0991 viernes, 16 de abril de 2021 16:05
    viernes, 16 de abril de 2021 4:48
  • Que hay Javi Fernández F ¿cómo estás?

    Pues al fin logré realizar ahora sí lo que necesitaba. Edité el código que me dejaste y te comento los cambios que realicé para llegar al 'producto final' :)

    Primero antes que todo, agregué la condición if udpate al trigger:

       BEGIN
    	SET NOCOUNT ON
         IF UPDATE(DESCRIPCION) OR UPDATE(NOFACTURAS) OR UPDATE(ESTATUS)
       BEGIN

    Y cambiando los LEFT JOIN por INNER JOIN como me lo comentabas, quedando de la siguiente forma:

    ALTER trigger FACTBIMBO
       ON RUTAF
       After update
       AS
       BEGIN
    	SET NOCOUNT ON
         IF UPDATE(DESCRIPCION) OR UPDATE(NOFACTURAS) OR UPDATE(ESTATUS)
       BEGIN
    	UPDATE D SET ESTATUS = 
    			CASE
    			--CUANDO EL ESTATUS DE LA TABLA RUTAF ES NUEVA CAMBIE EL ESTATUS DE LA FACTURA REMB A PROGRAMADA
    			WHEN D2.ESTATUS='Nueva' THEN 'Programada'
    			--CUANDO EL ESTATUS DE LA FACTURA REMB ES PROGRAMADA Y EL ESTATUS DE LA RUTAF ES ENTREGADA, CAMBIE EL ESTATUS DE LA FACTURA REMB A ENTREGADA
    			WHEN D.ESTATUS='Programada' AND D2.ESTATUS='Entregada' THEN 'Entregada'
    			--CUANDO EL ESTATUS LA RUTAF ES CERRADA, DEJE EL ESTATUS DE LA FACTURA REMB A ENTREGADA
    			WHEN D2.ESTATUS='Cerrada' THEN 'Entregada'
    			ELSE D.ESTATUS
    			END
    	FROM  FACTURAS D 
    	INNER JOIN RUTAF_FAC D1 ON (D.NOFACTURA=D1.FACTURA)
    	INNER JOIN INSERTED D2 ON (D1.NORUTA=D2.NORUTA)
    	WHERE LEFT(D.NOFACTURA,4) = 'REMB'; 
       END
       END

    Y ahora sí, cuando el usuario edita la Ruta creada en RutaF, ya sea agregando nuevas facturas, cambiando la descripción o incluso cerrando la Ruta (dándola por concluida) el código funciona correctamente :D

    Ya realicé pruebas tanto de crear una Ruta desde cero ingresando las Facturas cualquiera y no bota error (anteriormente me marcaba error al darle en guardar) y también realicé las pruebas en las Rutas con Facturas REMB, estas se generan en automático (por el tipo de Factura), edité la Ruta que contiene dichas Facturas y listo, ahora sí me cambia el estatus de la Factura REMB como lo quería :D

    En verdad muchísimas gracias por tu enorme ayuda Javi :) y sobretodo por tenerme tanta paciencia y explicarme en qué la regaba, qué omitía o qué me faltaba por agregar; muchísimas gracias en verdad.

    Saludos.


    viernes, 16 de abril de 2021 16:01

Todas las respuestas

  • Hola Alejandro 0991:

    Estás liando un poco la madeja. Si la pregunta es si se puede hacer, la respuesta es SI.

    Pero vamos a darle la vuelta a la lógica.

    ¿Porqué?  update(status)

    Esa condición que está muy bien, solo se cumple si en algún registro de la tabla facturas se realiza una update del campo status. Si actualiza cualquier otra columna, no se cumple.

    Partiendo de que sea o no lo que requieres, un if, es completamente válido, y no rompe la lógica de conjuntos.

    Seguimos.

    El segundo if, no tiene sentido, que busques un d.noFactura like ....algo en un trigger. 

     Voy a imaginar, que tú trigger, solo quiere cambiar las facturas que se han "updatado", que tengan una columna NOFACTURA que empieza por REMB y si es el caso, entonces en función del estado al que va quieres ponerle otro, o en función de otra causística.

    Lo que tienes que implementar es utilizar inserted, porque es quien tiene los registros de Factura que están modificándose, en la sentencia update o merge que quiere commitearse.

    Por tanto ese exist no es necesario.

    Sería un UPDATE t SET ESTATUS = case when inserted.Estatus = 'Programada' and rutaF.col='otracosa' then 'resultado1'

    when inserted.Estatus='Entregada' and rutaF.colx='algo' and otraTabla.col = 'otraCosa' then 'resultado2' end

    From inserted i inner join facturas t on i.colPrimaryKey = t.colPrimarykey

    join rutaF....join ruta_Fac 

    El case te determinará lo que quieres establecer, en función de lo que tiene inserted.estatus o de lo que tenía deleted.estatus, que son los subconjuntos con los que trabajas en el trigger.

    Con Inserted y/o deleted te aseguras de que solo se hacen cosas para los registros que tiene esa instrucción de update/merge que está en ejecución.

    La sentencia update, no es más que una sentencia de selección, con un formato especial, que obtiene una serie de registros. Haz que la sentencia llegue a ser lo que necesitas, y luego el valor condicionalo con el case.

    Trigger after update

    https://javifer2.wordpress.com/2020/04/15/trigger-que-es-como-se-hace-y-como-funciona-after-for-update/


    martes, 13 de abril de 2021 19:47
  • Solo una pequeña cosa que añadir: Ojo, no vaya a ser que tengas habilitada la opción de "triggers recursivos". Si está activada, y dentro del trigger "after update on Facturas" haces un update de Facturas, se volverá a disparar el trigger una y otra vez (hasta que dé un error al llegar al límite de 20 anidaciones).

    Afortunadamente, esta opción está desactivada por defecto, pero debes dejar bien documentado que no se debe activar, por si acaso en el futuro se instala tu programa en algún sitio donde se plantee activar los triggers recursivos por algún otro motivo (ejemplo: actualizaciones de una tabla recursiva tipo "árbol").

    martes, 13 de abril de 2021 20:27
  • Que hay Javi Fernández F ¿cómo estás? Espero y bien.

    Así es, me explico un poco mejor para ver si con esto se puede dar con lo que intento realizar (que si está algo revoltoso para ser honesto).

    Como primer instancia hay relaciones de las siguientes tablas:

    • Facturas: tabla en la que quiero actualizar el Estatus de la Factura, pero solamente de aquellas que comiencen con REMB.
    • RutaF: tabla de los proyecto en donde van todas las facturas, aquí tengo el Nombre de la Ruta y  Estatus de la misma.
    • RutaF_Fac: es el desglose de todas las facturas que van dentro de la RutaF.

    Partiendo de esto, la idea es hacer lo siguiente:

    • Si la factura REMB está agregada en una RutaF misma que su estatus (de la ruta) es Nueva, el Estatus de la Factura REMB se cambie de Entregada a Programada
    • Si el Estatus de la RutaF es Entregada o Cerrada, el Estatus de la Factura REMB se cambie de Programada a Entregada
    ¿Porqué?  update(status)

    Ammm... quise pensar que era eso por la cuestión de que pensé que era un Trigger Update, ¿o lo tengo que generar con un trigger after insert?

    Aquí es donde me perdí un poco.

    Sería un UPDATE t SET ESTATUS = case when inserted.Estatus = 'Programada' and rutaF.col='otracosa' then 'resultado1'
    
    when inserted.Estatus='Entregada' and rutaF.colx='algo' and otraTabla.col = 'otraCosa' then 'resultado2' end
    
    From inserted i inner join facturas t on i.colPrimaryKey = t.colPrimarykey
    
    join rutaF....join ruta_Fac 

    Intenté realizarlo de la siguiente forma:

    CREATE TRIGGER FACTBIMBO
       ON [dbo].[FACTURAS]
       AFTER UPDATE 
       AS
       IF UPDATE(ESTATUS)
       BEGIN
    	UPDATE FACTURAS SET ESTATUS = 
    	CASE
    	WHEN I.ESTATUS='Entregada' THEN 'Programada'
    	WHEN (I.ESTATUS='Entregada' OR I.ESTATUS='Programada') AND D2.ESTATUS='Cancelada' THEN 'Programada'
    	WHEN (I.ESTATUS='Entregada') AND (D2.ESTATUS='Entregada' OR D2.ESTATUS='Cerrada') THEN 'Entregada'
    	WHEN (I.ESTATUS='Programada') AND (D2.ESTATUS='Entregada' OR D2.ESTATUS='Cerrada') THEN 'Entregada' 
    	WHEN (I.ESTATUS='Programada') AND (D2.ESTATUS='Nueva') THEN 'Programada'
    	END
    	FROM  INSERTED I
    	INNER JOIN FACTURAS D ON (I.NOFACTURA=D.NOFACTURA)
    	INNER JOIN RUTAF_FAC D1 ON (D.NOFACTURA=D1.FACTURA)
    	INNER JOIN RUTAF D2 ON (D1.NORUTA=D2.NORUTA)
    	WHERE d.NOFACTURA LIKE 'REMB%'
       END

    Pero el Estatus de la Factura REMB no me lo cambia :/

    Honestamente creo que va a ser algo como la vez pasada, algo sencillo que está frente a mi pero que solo es acomodarlo.

    De antemano muchas gracias por todo Javi y a todos.

    saludos.

    martes, 13 de abril de 2021 23:01
  • Hola Alejandro 0991:

    Este trigger, ya tiene mejor pinta. Puede no hacer lo esperado, pero es más "interesante".

    Creo que lo primero es que comprendas los triggers del todo para llegar a buen puerto.

    El trigger After Insert on dbo.Facturas, sólo se produce una vez (salvo si utilizas merge, que lo dispara más veces, pero esto es otra guerra), la primera que insertes un registro en dbo.Facturas. En este trigger, se tiene el valor de los registros que se están insertando a través de la pseudotabla inserted

    El trigger After Update on dbo.Facturas, se puede producir muchas veces, tantas veces como haya una sentencia Update sobre la tabla dbo.Facturas. Por tanto 10 sentencias update = 10 veces se dispara el trigger. En éste, están las pseudotablas inserted y deleted. Las mismas contienen la información, que esta siendo cambiada (inserted), y la información que contenía el registro, justo hasta este momento (delete).

    La función Update(Estatus) devuelve true, si hay una sentencia Update que está modificando el valor de la columna estatus. Ahora bien, puesto en un if, solo aplica a la última row (o la primera o a la que le apetezca, pero solo a 1), que contenga inserted. En tu caso debería de ser no en un if, sino en el where o en el case, eso como quieras implementarlo.

    Porque puedo hacer una update de x filas, y en algunas modificar el estado y en otras no. Siempre hay que pensar en que pueden ser múltiples filas afectadas.

    Ejemplo

    Drop table if exists dbo.funcUpdate; 
    -- Creamos una tabla con 3 columnas
    Create table dbo.funcUpdate (id tinyint, estatus char(1), col2 tinyint)
    go
    -- Insertamos datos.
    Insert into dbo.funcUpdate(id, estatus, col2)
    values
    (1,'a',1),
    (2,'b',1),
    (3,'c',1),
    (4,'d',1);
    go
    -- Trigger after update
    Create trigger dbo.UpdateFuncUpdate on dbo.funcUpdate
    After update
    as
    	If (UPDATE(estatus))-- solo tiene que hacer esto si se modifica la columna estatus.
    	begin
    		update f
    			set estatus = 'z'
    		From dbo.funcUpdate f join inserted i on f.id = i.id;
    	End
    Go
    Update f
    	Set f.estatus = case when id = 1 OR id=3 then 'g'
    					else estatus 
    					end,
    		f.col2 = 2
    	from dbo.funcUpdate f; 
    go

    La pregunta es. ¿Y ahora que tendrá la tabla?, Update(estatus) es true o no.

    Y se los ha fundido todos. 

    Es un ejemplo un poco absurdo y sin mucho sentido, de algo que no se debe de hacer. Piensa siempre que te llegan en los triggers 1 millón de filas. Y que lo tienes que hacer de una sola tacada. Si utilizas ese enfoque, seguro que encuentras la solución, porque siempre la hay.

    Fin ejemplo

    • Si la factura REMB está agregada en una RutaF misma que su estatus (de la ruta) es Nueva, el Estatus de la Factura REMB se cambie de Entregada a Programada

    La primera pregunta es.......pero ¿qué desencadenara el trigger, una modificación de un registro de dbo.Factura? o una modificación de dbo.RutaF, o una inserción de dbo.RutaF

    Supongamos que si, que por ejemplo se modifica al cambiar la ruta alguna columna de dbo.Factura, porque cambia el Estatus, o cualquier otra cosa.

    ALTER TRIGGER FACTBIMBO
       ON [dbo].[FACTURAS]
       AFTER UPDATE 
       AS
       
    	UPDATE FACTURAS SET ESTATUS = 
    		CASE
    			WHEN (I.ESTATUS='Entregada' OR I.ESTATUS='Programada') AND D2.ESTATUS='Cancelada' THEN 'Programada'
    			WHEN I.ESTATUS='Programada' AND (D2.ESTATUS='Entregada' OR D2.ESTATUS='Cerrada') THEN 'Entregada' 
    			ELSE I.ESTATUS
    		END
    	FROM  INSERTED I
    		INNER JOIN FACTURAS D ON (I.NOFACTURA=D.NOFACTURA)
    		INNER JOIN RUTAF_FAC D1 ON (D.NOFACTURA=D1.FACTURA)
    		INNER JOIN RUTAF D2 ON (D1.NORUTA=D2.NORUTA)
    	WHERE LEFT(i.NOFACTURA,4) = 'REMB';
       

    Ligeros cambios.

    Ya evalúas estatus en el case, por tanto te sobra, y si en el caso quisieras que solo se cambiase si fuera por un cambio de estado entonces el UPDATE(I.ESTATUS), podría ir como una condición más del case, o una restricción más en el Where.

    No tiene sentido evaluar una condición si vas a llevar la columna al mismo destino al que va. When algo then i.Estatus tiene que ir a algo diferente a lo que va ahora.

    LEFT(I.ESTATUS,4) es más eficiente que LIKE

    Usa siempre las funciones sobre el conjunto inserted y no sobre Facturas, porque aunque el plan de ejecución seguro que es el mismo, ya que el motor es muy "listo", si aplicas una función sobre un conjunto que tiene pocas filas, penalizará menos que si lo haces sobre un conjunto que tiene tropecientos millones.

    Espero te acerque un poco más a tú objetivo.


    miércoles, 14 de abril de 2021 5:05
  • Excelente :)
    miércoles, 14 de abril de 2021 8:57
  • Gracias
    miércoles, 14 de abril de 2021 8:57
  • Gracias
    miércoles, 14 de abril de 2021 8:58
  • Que hay Javi Fernández F ¿cómo estás? Espero y bien.

    Te comento lo que hice.

    Bueno, pues tras estar analizando y revisando una y otra y otra vez, me di cuenta que estaba haciendo mal las cosas. Me explico:

    Quien hace la actualización como tal es la tabla RutaF, que es la única tabla que se actualiza en el proceso cliente. El proceso vendría siendo el siguiente: Genero la Factura REMB -> ésta se ingresa en un proyecto en la tabla RutaF -> RutaF es la que cambia su estatus de Nueva a Entregada, de Entregada a Cerrada o Cancelada. Ésta tabla en sí es la que nos debería de hacer el cambio del estatus a la tabla Facturas.

    Ante este argumento, me puse a reescribir el código de la siguiente forma:

       ALTER trigger FACTBIMBO
       ON RUTAF
       AFTER UPDATE 
       AS
       BEGIN
    	UPDATE FACTURAS SET ESTATUS = 
    	CASE
    	WHEN D.ESTATUS='Entregada' OR (D2.ESTATUS='Cancelada') THEN 'Programada'
    	WHEN (D2.ESTATUS='Entregada' OR D2.ESTATUS='Cerrada') THEN 'Entregada'
    	ELSE D.ESTATUS
    	END
    	FROM  FACTURAS D 
    	LEFT JOIN RUTAF_FAC D1 ON (D.NOFACTURA=D1.FACTURA)
    	LEFT JOIN RUTAF D2 ON (D1.NORUTA=D2.NORUTA)
    	WHERE LEFT(D.NOFACTURA,4) = 'REMB'
       END

    Y de esta forma sí me cumple las siguientes condiciones:

    • Si la Factura REMB está en estatus Entregada o si el Estatus de la RutaF está Cancelada cambie el Estatus a Programada
    • Si la RutaF está en estatus Entregada cambie el Estatus de la Factura REMB a Entregada

    El detalle es que no me cumple el OR del segundo WHEN, si el Estatus de la RutaF es Cerrada cambia el Estatus de la Factura REMB a Entregada, toma el primer WHEN y la deja en Programada.

    Intenté poner un WHEN más de la siguiente forma:

    	WHEN D.ESTATUS='Entregada' AND D2.ESTATUS='Cerrada' THEN 'Entregada'

    Pero no me dio resultados. Es aquí el último punto donde me atoré ahora sí.

    Pero ahí voy entendiendo más, poco a poco la cuestión de los triggers, es ver qué tabla va a efectuar la acción (ya sea de insert, update o delete) y referente en saber eso, qué acción quieres hacer y dónde.

    Muchas gracias en verdad por toda la ayuda Javi.

    Saludos.

    miércoles, 14 de abril de 2021 16:14
  • Hola Alejandro 0991:

    Veo cositas no del todo bien cerradas.

    ¿Dónde esta inserted?

    Tener un trigger, y no recoger los conjuntos inserted o deleted, implica que estás actualizando todos los registros todas las veces, y eso nunca es un buen objetivo.

    No trabajes con RutaF, trabaja con inserted.

    Update FActuras set..... From Facturas D

    Si estás usando un alias, la forma correcta es:

    "Update D set ..... From Facturas  D" o también "Update D set .... From Facturas as D"

    Y todas las columnas que mencionas, como bien haces, usan el alias "D"

    El case no te funciona porque no puede ser un Or.

    Dice When D.Estatus = 'Entregada' O ...... cualquier otra cosa, ya que si D.Estatus = 'Entregada' el resultado siempre va a ser 'Programada'

    Debería de ser un And 

    When (D.Estatus = 'Entregada' And D2.Estatus = 'Cancelada') Then .....

    When (D.Estatus='Entregada' And D2.Estatus = 'Cerrada') Then .....

    Por tanto solo si se cumplen las dos condiciones se cambia el estado. (Condicion1 and Condicion2)


    miércoles, 14 de abril de 2021 19:40
  • Que hay Javi Fernández F ¿cómo estas?

    Disculpa que apenas responda, pero el día de ayer ya no logré volver acá por el trabajo.

    Bueno te comento lo que realicé, al parecer logré dar con el clavo, bueno, al menos en las pruebas que he estado haciendo sí me realiza los cambios que necesito.

    ALTER trigger FACTBIMBO
       ON RUTAF
       AFTER UPDATE 
       AS
       BEGIN
    	UPDATE FACTURAS SET ESTATUS = 
    	CASE
    	--CUANDO EL ESTATUS DE LA TABLA RUTAF ES NUEVA CAMBIE EL ESTATUS DE LA FACTURA REMB A PROGRAMADA
    	WHEN D2.ESTATUS='Nueva' THEN 'Programada'
    	--CUANDO EL ESTATUS DE LA FACTURA REMB ES PROGRAMADA Y EL ESTATUS DE LA RUTAF ES ENTREGADA, CAMBIE EL ESTATUS DE LA FACTURA REMB A ENTREGADA
    	WHEN D.ESTATUS='Programada' AND D2.ESTATUS='Entregada' THEN 'Entregada'
    	--CUANDO EL ESTATUS LA RUTAF ES CERRADA, DEJE EL ESTATUS DE LA FACTURA REMB A ENTREGADA
    	WHEN D2.ESTATUS='Cerrada' THEN 'Entregada'
    	ELSE D.ESTATUS
    	END
    	FROM  FACTURAS D 
    	LEFT JOIN RUTAF_FAC D1 ON (D.NOFACTURA=D1.FACTURA)
    	LEFT JOIN RUTAF D2 ON (D1.NORUTA=D2.NORUTA)
    	INNER JOIN INSERTED I ON (I.NORUTA=D2.NORUTA)
    	WHERE LEFT(D.NOFACTURA,4) = 'REMB' AND (I.NORUTA=D2.NORUTA)
       END

    Ignoro si lo estoy haciendo bien, pero al momento no me ha brincado algún error o problema; igual seguiré haciendo pruebas antes de implementarlo en la DB buena, todo cambio lo realizo primero en una de capacitación y si la función o cambio realizado se ejecuta correctamente, lo implemento en la buena jejeje.

    De antemano muchas gracias en verdad por toda tu ayuda y sobretodo la paciencia; se que ya te he sacado más de 1 cana y más en esta pregunta jejeje, una disculpa. Pero en verdad he aprendido muchísimo, tanto procedimiento como lógica con todas tus ayudas y la de los compañeros de la comunidad.

    Saludos.

    jueves, 15 de abril de 2021 18:58
  • Hola Alejandro 0991:

    Esto es lo mismo que tú has puesto, pero más correcto.

    ALTER trigger FACTBIMBO
       ON RUTAF
       AFTER UPDATE 
       AS
       BEGIN
    	UPDATE D SET ESTATUS = 
    			CASE
    			--CUANDO EL ESTATUS DE LA TABLA RUTAF ES NUEVA CAMBIE EL ESTATUS DE LA FACTURA REMB A PROGRAMADA
    			WHEN D2.ESTATUS='Nueva' THEN 'Programada'
    			--CUANDO EL ESTATUS DE LA FACTURA REMB ES PROGRAMADA Y EL ESTATUS DE LA RUTAF ES ENTREGADA, CAMBIE EL ESTATUS DE LA FACTURA REMB A ENTREGADA
    			WHEN D.ESTATUS='Programada' AND D2.ESTATUS='Entregada' THEN 'Entregada'
    			--CUANDO EL ESTATUS LA RUTAF ES CERRADA, DEJE EL ESTATUS DE LA FACTURA REMB A ENTREGADA
    			WHEN D2.ESTATUS='Cerrada' THEN 'Entregada'
    			ELSE D.ESTATUS
    			END
    	FROM  FACTURAS D 
    	LEFT JOIN RUTAF_FAC D1 ON (D.NOFACTURA=D1.FACTURA)
    	LEFT JOIN INSERTED D2 ON (D1.NORUTA=D2.NORUTA)
    	WHERE LEFT(D.NOFACTURA,4) = 'REMB'; 
       END

    Aún me sigue rechinando los oídos, el uso de LEFT JOIN en un trigger de la tabla RutaF.

    Si las facturas a cambiar el estado, tienen que tener una ruta, porque es lo que hacemos, en función de ella, debería de ser INNER JOIN.

    Pero salvo eso, lo demás esta ok.

    • Marcado como respuesta Alejandro 0991 viernes, 16 de abril de 2021 16:05
    viernes, 16 de abril de 2021 4:48
  • Que hay Javi Fernández F ¿cómo estás?

    Pues al fin logré realizar ahora sí lo que necesitaba. Edité el código que me dejaste y te comento los cambios que realicé para llegar al 'producto final' :)

    Primero antes que todo, agregué la condición if udpate al trigger:

       BEGIN
    	SET NOCOUNT ON
         IF UPDATE(DESCRIPCION) OR UPDATE(NOFACTURAS) OR UPDATE(ESTATUS)
       BEGIN

    Y cambiando los LEFT JOIN por INNER JOIN como me lo comentabas, quedando de la siguiente forma:

    ALTER trigger FACTBIMBO
       ON RUTAF
       After update
       AS
       BEGIN
    	SET NOCOUNT ON
         IF UPDATE(DESCRIPCION) OR UPDATE(NOFACTURAS) OR UPDATE(ESTATUS)
       BEGIN
    	UPDATE D SET ESTATUS = 
    			CASE
    			--CUANDO EL ESTATUS DE LA TABLA RUTAF ES NUEVA CAMBIE EL ESTATUS DE LA FACTURA REMB A PROGRAMADA
    			WHEN D2.ESTATUS='Nueva' THEN 'Programada'
    			--CUANDO EL ESTATUS DE LA FACTURA REMB ES PROGRAMADA Y EL ESTATUS DE LA RUTAF ES ENTREGADA, CAMBIE EL ESTATUS DE LA FACTURA REMB A ENTREGADA
    			WHEN D.ESTATUS='Programada' AND D2.ESTATUS='Entregada' THEN 'Entregada'
    			--CUANDO EL ESTATUS LA RUTAF ES CERRADA, DEJE EL ESTATUS DE LA FACTURA REMB A ENTREGADA
    			WHEN D2.ESTATUS='Cerrada' THEN 'Entregada'
    			ELSE D.ESTATUS
    			END
    	FROM  FACTURAS D 
    	INNER JOIN RUTAF_FAC D1 ON (D.NOFACTURA=D1.FACTURA)
    	INNER JOIN INSERTED D2 ON (D1.NORUTA=D2.NORUTA)
    	WHERE LEFT(D.NOFACTURA,4) = 'REMB'; 
       END
       END

    Y ahora sí, cuando el usuario edita la Ruta creada en RutaF, ya sea agregando nuevas facturas, cambiando la descripción o incluso cerrando la Ruta (dándola por concluida) el código funciona correctamente :D

    Ya realicé pruebas tanto de crear una Ruta desde cero ingresando las Facturas cualquiera y no bota error (anteriormente me marcaba error al darle en guardar) y también realicé las pruebas en las Rutas con Facturas REMB, estas se generan en automático (por el tipo de Factura), edité la Ruta que contiene dichas Facturas y listo, ahora sí me cambia el estatus de la Factura REMB como lo quería :D

    En verdad muchísimas gracias por tu enorme ayuda Javi :) y sobretodo por tenerme tanta paciencia y explicarme en qué la regaba, qué omitía o qué me faltaba por agregar; muchísimas gracias en verdad.

    Saludos.


    viernes, 16 de abril de 2021 16:01