Pregunta

Tengo un par de desencadenantes en una base de datos SYBASE ASE que se disparan a las actualizaciones de dos tablas: Docs y Trans.

Los desencadenantes se definen como se muestra aquí:

Para los documentos:

 CREATE TRIGGER dbo.Index_Change_Docs
 ON dbo.docs
 FOR INSERT,UPDATE AS

 IF UPDATE(DOCTYPE) OR UPDATE(BATCH_NO) OR UPDATE(SCANDATE) OR           
 UPDATE(PERIOD_START_DATE) OR UPDATE(PERIOD_END_DATE) 
 OR UPDATE(DISPATCH_ID) OR UPDATE(DISPATCH_NAME) OR UPDATE(CHECKNUM) OR    
 UPDATE(CHECKAMT)
 BEGIN
    INSERT INTO 
    DOCID_SYNC (IS_DOC_ID, CRTN_DT, SYNC_STATUS_CDE) 
    SELECT Inserted.DOCID, GETDATE(), "N" FROM Inserted

 END

Para trans:

 CREATE TRIGGER dbo.Index_Change_Trans
 ON dbo.Trans
 FOR INSERT,UPDATE AS

 IF UPDATE(TRANSNUM) OR UPDATE(CONTRACT) OR UPDATE(FRANCHISE) OR UPDATE(SSN) OR      
 UPDATE(STATE_CODE) OR UPDATE(TRANSTYPE)
OR UPDATE(AGENCYNUM) OR UPDATE(LOCKBOXBATCHNUM) OR UPDATE(PRODUCTCODE) 
 BEGIN

    INSERT INTO 
    DOCID_SYNC (IS_DOC_ID, CRTN_DT, SYNC_STATUS_CDE)
    SELECT DOCID, GETDATE(), "N" FROM DOCS
    WHERE Transnum = (SELECT Inserted.TransNum from Inserted)
 END

Parece que el comportamiento de estos desencadenantes es diferente, dependiendo de cómo se realicen las actualizaciones de esas tablas.

En un caso, estas tablas se actualizan a través de dos procedimientos almacenados (insert_docs_sp e insert_trans_sp). Cuando esto sucede, cada gatillo se dispara una vez (una vez para documentos, uno para trans) y todo funciona como se esperaba.

En otro caso, estas tablas se actualizan dentro de una transacción SYBASE con dos actualizaciones de la base de datos. Aquí, la primera actualización se realiza a través de SQL en línea en la aplicación de llamadas (que dispara el disparador trans). La segunda actualización se realiza a través de un procedimiento almacenado: insert_docs_sp, lo mismo que en el otro caso, que no dispara un disparador.

¿Quizás hay algo sobre cómo se manejan las transacciones que no entiendo?

¿Fue útil?

Solución 2

Encontré la respuesta: está en el orden de ejecución. Pensé que uno de los desencadenantes no estaba siendo disparado, en este caso el desencadenante index_change_trans, pero de hecho lo fue. Sin embargo, no vi los resultados, porque este desencadenante depende de las entradas en la tabla Docs.

INSERT INTO 
DOCID_SYNC (IS_DOC_ID, CRTN_DT, SYNC_STATUS_CDE)
SELECT DOCID, GETDATE(), "N" FROM DOCS
WHERE Transnum = (SELECT Inserted.TransNum from Inserted)

Entonces, en los casos en que la tabla trans se actualizó antes de la tabla DOCS, la ejecución del disparador trans no mostraría una actualización en la tabla DOCID_SYNC, ya que en este punto no había entradas en la tabla DOCS con el valor de transnum apropiado. En estos casos, la tabla DOCID_SYNC solo tiene una entrada, el resultado del activador DOCS.

En otros casos, la tabla DOCS se actualiza primero y luego la tabla trans. En estos casos, la tabla DOCID_SYNC tiene dos entradas, una como resultado del activador DOCS, y otra como resultado del disparador trans.

Otros consejos

En ambos desencadenantes, el disparador solo se está insertando en la tabla DOCID_SYNC si se actualizan ciertas columnas. ¿Está seguro de que el procedimiento almacenado está actualizando una de las columnas en el disparador? Los desencadenantes tampoco se llaman si es una actualización recursiva de una llamada de activación, pero ese no parece ser el caso aquí.

La otra posibilidad es si la transacción de llamadas deshabilitó el disparador con el comando desencadenante de desencadenantes. Comenzaría a garantizar que el procedimiento almacenado esté actualizando una de las columnas en las verificaciones de activación.

Otra pregunta: se actualiza la misma fila dos veces, en el SQL en línea y el procedimiento almacenado en su caso de error, o están actualizando dos filas diferentes?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top