In quali condizioni non si chiamerà un sybase?
-
28-10-2019 - |
Domanda
Ho un paio di trigger in un database Sybase ASE che viene sparato su aggiornamenti a due tabelle: docs e trans.
I trigger sono definiti come mostrato qui:
Per i documenti:
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
Per 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
Sembra che il comportamento di questi trigger sia diverso, a seconda di come vengono effettuati gli aggiornamenti a quelle tabelle.
In un caso, queste tabelle vengono aggiornate tramite due procedure memorizzate (insert_docs_sp e insert_trans_sp). Quando ciò accade, ogni trigger viene sparato una volta (una volta per i documenti, uno per trans) e tutto funziona come previsto.
In un altro caso, queste tabelle vengono aggiornate all'interno di una transazione Sybase con due aggiornamenti del database. Qui, il primo aggiornamento viene eseguito tramite in linea SQL nell'applicazione chiamante (che spara il trigger trans.) Il secondo aggiornamento viene eseguito tramite una procedura memorizzata - Insert_docs_sp, lo stesso dell'altro caso - che non spara un trigger.
Forse c'è qualcosa su come vengono gestite le transazioni che non capisco?
Soluzione 2
Ho trovato la risposta: è nell'ordine di esecuzione. Pensavo che uno dei trigger non fosse stato licenziato - in questo caso il trigger index_change_trans - ma in realtà lo era. Non ho visto i risultati, tuttavia, perché questo grilletto si basa sulle voci nella tabella dei documenti.
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)
Quindi, nei casi in cui la tabella trans è stata aggiornata prima della tabella Docs, l'esecuzione del trigger trans non mostrerebbe un aggiornamento nella tabella Docid_Sync - poiché a questo punto non c'erano voci nella tabella Docs con il valore transnum appropriato. In questi casi, la tabella DOCID_SYNC ha solo una voce, il risultato del trigger DOCS.
In altri casi, la tabella Docs viene aggiornata per prima e quindi la tabella trans. In questi casi, la tabella Docid_Sync ha due voci: una come risultato del trigger Docs e un'altra come risultato del trigger trans.
Altri suggerimenti
In entrambi i trigger, il trigger viene inserito solo nella tabella docid_sync se alcune colonne vengono aggiornate. Sei sicuro che la procedura memorizzata stia aggiornando una delle colonne nel trigger? Anche i trigger non sono chiamati se si tratta di un aggiornamento ricorsivo da una chiamata di innesco, ma non sembra essere il caso qui.
L'altra possibilità è se la transazione chiamante disabilita il trigger con il comando Imposta. Inizierei a garantire che la procedura memorizzata stia aggiornando una delle colonne nei controlli del trigger.
Un'altra domanda: la stessa riga viene aggiornata due volte, nella procedura SQL e memorizzata in linea nel caso di errore o stanno aggiornando due righe diverse?