Controllo errore in una funzione.

di il
3 risposte

Controllo errore in una funzione.

Spero che gli esperti mi sollevino dal cercare una soluzione che a una prima occhiata non ho trovato. Ho una funzione che, in dipendenza dei valori d'ingresso, va in errore. Purtroppo mi va in errore su una select che restituisce qualche centinaio di migliaia di record, e non so su quale. La select non viene eseguita, e ADO mi restituisce il seguente errore: "Datetime function: datetime field overflow (#1441) "

Vorrei trappare l'errore, ma non ho esperienza con i vari Error Handling. La funzione è questa (ho tolto il blocco centrale)

FUNCTION `NewRvDt`(PubDt DATE,GbDt DATE,VerM TINYINT,VerH TINYINT,DtType TINYINT,DtToday DATE) RETURNS date
BEGIN
  -- DtType =0 start period, =1 end period, =2 end period today
  DECLARE bytNumMesi TINYINT DEFAULT 0;
  DECLARE bytMeseIni TINYINT DEFAULT 0;
  DECLARE dtmIni DATE DEFAULT NULL;
  DECLARE dtmReturn DATE DEFAULT NULL;
  
  --- parecchio codice tolto
  
  --- parecchio codice tolto 
  
  -- da data iniziale ottiene data finale se richiesta
  If DtType = 1 Then		-- data finale periodo
    Set dtmReturn = Date_Add(Date_Add(dtmReturn, INTERVAL bytNumMesi MONTH),INTERVAL -1 DAY);
  ElseIf DtType = 2 Then	-- data finale a oggi
    Set dtmReturn = Date_Add(Date_Add(dtmReturn, INTERVAL bytNumMesi MONTH),INTERVAL -1 DAY);
    While DateFM(Date_Add(dtmReturn, interval bytNumMesi month))<=DtToday do
      Set dtmReturn = DateFM(Date_Add(dtmReturn, interval bytNumMesi month));
    End While;
  End If;

  RETURN dtmReturn;
END

Come faccio a restituire un valore opportuno se c'è un errore?

3 Risposte

  • Re: Controllo errore in una funzione.

    Prova a dare un occhio  : https://mysqlcode.com/error-handling-mysql-store-procedure/

    Se ritieni che il problema sia dato da qualche Date_Add, se provi a descrivere cosa vuoi ottenere magari esistono delle formule diverse.

    Noto nel tuo codice che usi sempre la stessa variabile (dtmReturn) che inizializzi a null : la funzione Date_Add in presenza di null nel campo data restituisce null ...

    Nel codice compare anche la funzione DateFM della quale non si sa nulla ...

  • Re: Controllo errore in una funzione.

    Grazie, mi sembra un buon tutorial, domani lo guardo.

    La funzione DateFM è una mia funzione che restituisce il fine mese di una data in ingresso.

    La funzione serve per calcolare quali sono le date di inizio e fine periodo del prossimo rendiconto di vendita. Si parla di libri, che normalmente vengono rendicontati, con relativo calcolo di royalties, una o due volte all'anno.

    A questo punto, giusto per la cronaca, ti posto tutta la funzione, che è poi la trasposizione di una in basic

    FUNCTION `NewRvDt`(PubDt DATE,GbDt DATE,VerM TINYINT,VerH TINYINT,DtType TINYINT,DtToday DATE) RETURNS date
       DETERMINISTIC
    BEGIN
    -- DtType =0 start period, =1 end period, =2 end period today
     DECLARE bytNumMesi TINYINT DEFAULT 0;
     DECLARE bytMeseIni TINYINT DEFAULT 0;
     DECLARE dtmIni DATE DEFAULT NULL;
     DECLARE dtmReturn DATE DEFAULT NULL;
     
     if isnull(PubDt) and isnull(GbDt) then
       set dtmReturn = Null;
       return dtmReturn;
     End If;
    
     set VerM = ifnull(VerM,1);
     set VerH = ifnull(VerH,1);
     -- imposta data iniziale periodo
     SET dtmIni=date_add(ifnull(GbDt, PubDt), INTERVAL 1 DAY);
     -- imposta numero mesi periodicità
     SET bytNumMesi = VerH;
     If bytNumMesi<= 0 Or bytNumMesi > 12 Then
       set bytNumMesi=1;
     End If;
     set bytNumMesi= 12 / bytNumMesi;
     
     -- imposta mese iniziale periodo
     set bytMeseIni=VerM;
     If bytMeseIni<=0 Or bytMeseIni>12 Then
       set bytMeseIni=1;
     End If;
     -- crea data sicuramente futura
     set dtmReturn = DateYMD(Year(dtmIni) + 2, bytMeseIni, 1);
     -- sottrae numero mesi fino a renderla minore o uguale a dtmIni
     While dtmReturn > dtmIni do
       set dtmReturn = Date_Add(dtmReturn, INTERVAL -bytNumMesi MONTH);
     End While;
     
     -- da data iniziale ottiene data finale se richiesta
     If DtType = 1 Then        -- data finale periodo
       Set dtmReturn = Date_Add(Date_Add(dtmReturn, INTERVAL bytNumMesi MONTH),INTERVAL -1 DAY);
     ElseIf DtType = 2 Then    -- data finale a oggi
       Set dtmReturn = Date_Add(Date_Add(dtmReturn, INTERVAL bytNumMesi MONTH),INTERVAL -1 DAY);
       While DateFM(Date_Add(dtmReturn, interval bytNumMesi month))<=DtToday do
         Set dtmReturn = DateFM(Date_Add(dtmReturn, interval bytNumMesi month));
       End While;
     End If;
     RETURN dtmReturn;
    END
  • Re: Controllo errore in una funzione.

    04/12/2024 - max.riservo ha scritto:

    Prova a dare un occhio  : https://mysqlcode.com/error-handling-mysql-store-procedure/

    Se ritieni che il problema sia dato da qualche Date_Add, se provi a descrivere cosa vuoi ottenere magari esistono delle formule diverse.

    Noto nel tuo codice che usi sempre la stessa variabile (dtmReturn) che inizializzi a null : la funzione Date_Add in presenza di null nel campo data restituisce null ...

    Nel codice compare anche la funzione DateFM della quale non si sa nulla ...

    Ti ringrazio tantissimo, il tutorial che mi hai indicato è molto chiaro, mi sono bastati 10 minuti per risolvere il problema, beccando anche il record che lo creava. Ecco qui la routine con il gestore di errore semplicissimo che serve al mio scopo. Come vedi lascio la variabile di ritorno a NULL in caso dell'errore 1441 (ma potrei farlo per tutti) . Per individuare i record che mi danno problemi basta che tolga il commento alla riga che setta la variabile di ritorno alla mia data di nascita. Tramite quel preciso valore che non è tra i possibili li becco. In questo caso era solo uno tra 54mila. Anche DateYMD è una mia funzione, che restituisce una data a partire da anno, mese, giorno. Magari c'è già, non lo so.

    FUNCTION `NewRvDt`(PubDt DATE,GbDt DATE,VerM TINYINT,VerH TINYINT,DtType TINYINT,DtToday DATE) RETURNS date
       DETERMINISTIC
    BEGIN
    -- DtType =0 start period, =1 end period, =2 end period today
     DECLARE bytNumMesi TINYINT DEFAULT 0;
     DECLARE bytMeseIni TINYINT DEFAULT 0;
     DECLARE dtmIni DATE DEFAULT NULL;
     DECLARE dtmReturn DATE DEFAULT NULL;
     
     DECLARE EXIT HANDLER FOR 1441
     BEGIN
    -- set dtmReturn=DateYMD(1954, 6, 13);
       RETURN dtmReturn;
     END;
    
     if isnull(PubDt) and isnull(GbDt) then
       return dtmReturn;
     End If;
    
     set VerM = ifnull(VerM,1);
     set VerH = ifnull(VerH,1);
     -- imposta data iniziale periodo
     SET dtmIni=date_add(ifnull(GbDt, PubDt), INTERVAL 1 DAY);
     -- imposta numero mesi periodicità
     SET bytNumMesi = VerH;
     If bytNumMesi<= 0 Or bytNumMesi > 12 Then
       set bytNumMesi=1;
     End If;
     set bytNumMesi= 12 / bytNumMesi;
     
     -- imposta mese iniziale periodo
     set bytMeseIni=VerM;
     If bytMeseIni<=0 Or bytMeseIni>12 Then
       set bytMeseIni=1;
     End If;
     -- crea data sicuramente futura
     set dtmReturn = DateYMD(Year(dtmIni) + 2, bytMeseIni, 1);
     -- sottrae numero mesi fino a renderla minore o uguale a dtmIni
     While dtmReturn > dtmIni do
       set dtmReturn = Date_Add(dtmReturn, INTERVAL -bytNumMesi MONTH);
     End While;
     
     -- da data iniziale ottiene data finale se richiesta
     If DtType = 1 Then        -- data finale periodo
       Set dtmReturn = Date_Add(Date_Add(dtmReturn, INTERVAL bytNumMesi MONTH),INTERVAL -1 DAY);
     ElseIf DtType = 2 Then    -- data finale a oggi
       Set dtmReturn = Date_Add(Date_Add(dtmReturn, INTERVAL bytNumMesi MONTH),INTERVAL -1 DAY);
       While DateFM(Date_Add(dtmReturn, interval bytNumMesi month))<=DtToday do
         Set dtmReturn = DateFM(Date_Add(dtmReturn, interval bytNumMesi month));
       End While;
     End If;
     RETURN dtmReturn;
    END  
Devi accedere o registrarti per scrivere nel forum
3 risposte