Sostituzione trigger FOR INSERT con una Stored Procedure

di il
1 risposte

Sostituzione trigger FOR INSERT con una Stored Procedure

Buonasera a tutti,

sono nuovo nel forum ed ho un problema su un db sqlserver di terze parti che ho risolto fino a poco fa utilizzano un trigger su una tabella ma dopo l'ultimo aggiornamento purtroppo il trigger non funziona più e fino a quando non lo disabilito non mi consente di scaricare i nuovi dati aggiornati.

Il mio problema è il seguente:

Ho una tabella APP_TIMBRATURE_GEO che viene alimentata in automatico mediante un APP per smartphone con questo trigger

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE TRIGGER [dbo].[TRG_INS_APP_TIMBRATURE_GEO] ON [dbo].[APP_TIMBRATURE_GEO] FOR INSERT AS
BEGIN
SET NOCOUNT ON;
DECLARE   @BADGE VARCHAR(10)
DECLARE   @CAUSALE VARCHAR(20)
DECLARE   @VERSO VARCHAR(1)
DECLARE   @DATA VARCHAR(20)
DECLARE   @INDIRIZZO VARCHAR(30)
SELECT    @BADGE = (SELECT TOP 1 CODICE FROM BADGE WHERE IDUTILIZZATORE = (SELECT IDDIP FROM INSERTED)),
        @CAUSALE = (SELECT CAUSALE FROM INSERTED),
        @VERSO = (SELECT VERSO FROM INSERTED),
        @DATA=(SELECT CONVERT(varchar, timestampgps, 105)+' '+CONVERT(varchar, timestampgps, 108) FROM INSERTED),
        @INDIRIZZO = (SELECT TOP 1 INDIRIZZO_TERMSTD FROM TERMGEO_TERMSTD WHERE ID_TERMGEO=(SELECT IDTERMINALEGEO FROM INSERTED));
    BEGIN
    
       INSERT INTO TEMPTRANSAZ(BADGE, CAUSALE, VERSO, DATA, IDTERMINALE, TIPO) values 
       (@BADGE, @CAUSALE, @VERSO, @DATA, @INDIRIZZO, 'C');
         INSERT INTO TEMPTRANSAZCDC(BADGE, CAUSALE, VERSO, DATA, IDTERMINALE, TIPO) values 
       (@BADGE, @CAUSALE, @VERSO, @DATA, @INDIRIZZO, 'C');
    END
    
END

riuscivo a spostare i nuovi record nella tabella TEMPTRANSAZ che a sua volta fa delle operazioni per spostare nella tabella giusta i nuovi record. Dopo l'aggiornamento degli applicativi il trigger mi genera un errore ottimistico di concorrenza. L'ho segnalato al produttore del software e mi ha detto che i trigger non si può più utilizzare ed è necessario creare una stored procedure da richiamare ogni x minuti per fare la stessa cosa del trigger.

Ho provato a creare una nuova procedura che spostasse in una tabella d'appoggio TEMP_APP_TIMBRATURE_GEO e su quella nuova tabella applicare il suddetto trigger ma continua a non funzionare.

Ho pensato di creare una procedura che prendesse il valore massimo di LOGID della tabella TEMP_APP_TIMBRATURE_GEO, tabella d'appoggio identica all'originale, e copiasse tutti i record dalla tabella originale APP_TIMBRATURE_GEO che avessero un LOGID maggiore del valore massimo rilevato ed in fase di inserimento eseguisse il trigger sopra riportato per spostare le timbrature in TEMPTRANSAZ e sono arrivato fino a questo punto 

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[TRAVASO_APP_TIMBRATURE_GEO]
AS
BEGIN
   -- Dichiaro la variabile
   DECLARE @TEMP_LOGIDVALMAX INT; -- Valore ultimo LOGID di TEMP_APP_TIMBRATURE_GEO inserito
    DECLARE @APP_TIMB_GEO_LOGIDVALMAX INT; -- Valore ultimo di LOGID di APP_TIMBRATURE_GEO
   -- SET NOCOUNT ON added to prevent extra result sets from
   -- interfering with SELECT statements.
   SET NOCOUNT ON
   -- Insert statements for procedure here
   SELECT @TEMP_LOGIDVALMAX = max(LOGID) from TEMP_APP_TIMBRATURE_GEO; -- Seleziono il valore LOGID max della tabella di destinazione TEMP_APP_TIMBRATURE_GEO
    SELECT @APP_TIMB_GEO_LOGIDVALMAX = max(LOGID) from APP_TIMBRATURE_GEO; -- Seleziono il valore LOGID max della tabella di destinazione APP_TIMBRATURE_GEO
    WHILE @TEMP_LOGIDVALMAX < @APP_TIMB_GEO_LOGIDVALMAX
BEGIN
   SET @TEMP_LOGIDVALMAX = @TEMP_LOGIDVALMAX + 1;
    BEGIN
SET NOCOUNT ON;
DECLARE   @BADGE VARCHAR(10)
DECLARE   @CAUSALE VARCHAR(20)
DECLARE   @VERSO VARCHAR(1)
DECLARE   @DATA VARCHAR(20)
DECLARE   @INDIRIZZO VARCHAR(30)
SELECT    @BADGE = (SELECT TOP 1 CODICE FROM BADGE WHERE IDUTILIZZATORE = (SELECT IDDIP FROM INSERTED)),
        @CAUSALE = (SELECT CAUSALE FROM INSERTED),
        @VERSO = (SELECT VERSO FROM INSERTED),
        @DATA=(SELECT CONVERT(varchar, timestampgps, 105)+' '+CONVERT(varchar, timestampgps, 108) FROM INSERTED),
        @INDIRIZZO = (SELECT TOP 1 INDIRIZZO_TERMSTD FROM TERMGEO_TERMSTD WHERE ID_TERMGEO=(SELECT IDTERMINALEGEO FROM INSERTED));
    BEGIN
    
       INSERT INTO TEMPTRANSAZ(BADGE, CAUSALE, VERSO, DATA, IDTERMINALE, TIPO) values 
       (@BADGE, @CAUSALE, @VERSO, @DATA, @INDIRIZZO, 'C');
         INSERT INTO TEMPTRANSAZCDC(BADGE, CAUSALE, VERSO, DATA, IDTERMINALE, TIPO) values 
       (@BADGE, @CAUSALE, @VERSO, @DATA, @INDIRIZZO, 'C');
    END
END;
    --SELECT @LOGIDVALMAX;
    INSERT INTO TEMP_APP_TIMBRATURE_GEO 
        SELECT * FROM APP_TIMBRATURE_GEO 
            WHERE APP_TIMBRATURE_GEO.LOGID > @TEMP_LOGIDVALMAX;
END

ma non so cosa scrivere al posto di FROM INSERTED per dire alla procedura che questa operazione la deve eseguire per ogni nuovo record che sposta da una tabella ad un'altra.

Se per potermi dare supporto necessitate di altro fatemi sapere che provvedo ad integrare con ciò che manca.

Grazie mille a chiunque possa darmi supporto.

1 Risposte

  • Re: Sostituzione trigger FOR INSERT con una Stored Procedure

    Salve,

    tendenzialmente, “inserted” va sostituito con la tabella base del gestionale, APP_TIMBRATURE_GEO..

    MA… come, a mio parere,  per tanti versi hai sbagliato a fare un trigger “mono riga”, ancora di piu' ora, dove dovrai alimentare ogni n minuti dalla “coda” di APP_TIMBRATURE_GEO, non puoi usare “codice mono-riga”…

    quindi, correttamente, otterrai il max della tua tabella, ed estrarrai per inserire nella tua tab, tutte le righe della tabella originale con ID superiore al tuo max…

    trivialmente,

    SELECT @TEMP_LOGIDVALMAX = max(LOGID) from TEMP_APP_TIMBRATURE_GEO;
    INSERT TEMP_APP_TIMBRATURE_GEO
        SELECT 
            -- tutte le colonne che richiedano una lookup
            (SELECT TOP 1 CODICE FROM BADGE WHERE IDUTILIZZATORE = t.IDDIP)
            
            -- normali colonna da trasporre..
            , t.CAUSALE 
            , t.VERSO 
            
            -- cos'e' sta schifezza ?? :D :D
            --. @DATA=(SELECT CONVERT(varchar, timestampgps, 105)+' '+CONVERT(varchar, timestampgps, 108) FROM INSERTED),
            -- una DATA e' una DATA, e va usato il tipo DATETIME
            -- !
            , t.timestampgps
            
            -- tabella di estrazione
            FROM APP_TIMBRATURE_GEO t        
            -- filtri...
            WHERE t.LOGID > @TEMP_LOGIDVALMAX;

    personalmente discuto un attimo anche sulle tue selezioni di lookup, tipo, e per le date, si usa il tipo DATETIME, PUNTO! :D
    non ti inventare cose strane, che poi si fanno danni :D

    (SELECT TOP 1 CODICE FROM BADGE WHERE IDUTILIZZATORE = t.IDDIP)

    che mi danno un'idea di scarsa normalizzazione della base dati, in quanto la cardinalita' dovrebbe essere 1, e quindi dovresti poter risolvere la proiezione con una JOIN e non con una subquery, ma tant'e'…

    poi, dovrai trovare il modo di eseguire “ogni tanto” la tua stored procedure…

    21/10/2024 - gaemas ha scritto:


    il trigger mi genera un errore ottimistico di concorrenza.

    per curiosita', che eccezione viene sollevata?

    salutoni romagnoli
    – 
    Andrea

Devi accedere o registrarti per scrivere nel forum
1 risposte