O2SS0343: l'istruzione FORALL con clausola SAVE EXCEPTION non è supportata (Errore)

Questo articolo descrive perché SQL Server Migration Assistant (SSMA) per Oracle non supporta la SAVE EXCEPTIONS clausola nell'istruzione FORALL .

Background

La gestione delle eccezioni è un costrutto o un meccanismo del linguaggio di programmazione progettato per gestire l'occorrenza di eccezioni, condizioni speciali che modificano il normale flusso di esecuzione del programma. In Oracle l'istruzione FORALL consente di eseguire più istruzioni DML in modo molto efficiente e può ripetere solo una singola istruzione DML, a differenza di un FOR ciclo generico. SAVE EXCEPTIONS la clausola fa sì che il FORALL ciclo continui anche se alcune operazioni DML hanno esito negativo.

Il modello di eccezione Oracle differisce da SQL Server sia nella generazione di eccezioni che nella gestione delle eccezioni. È preferibile usare il modello di eccezioni di SQL Server come parte della migrazione del codice ORACLE PL/SQL.

Ogni volta che FORALL l'istruzione usata con SAVE EXCEPTIONS la clausola , SSMA non la supporta e genera un messaggio di errore.

Esempio

Si consideri l'esempio seguente che usa un'istruzione FORALL con SAVE EXCEPTIONS clausola .

CREATE TABLE DIVISION_RESULT_Exception (RESULT NUMBER);
/

DECLARE
    TYPE NUMLIST IS TABLE OF NUMBER;
    NUM_TAB NUMLIST := NUMLIST(1000, 0, 100, 0, 10);
    ERRORS NUMBER;
    DML_ERRORS EXCEPTION;
    PRAGMA EXCEPTION_INIT(DML_ERRORS, -24381);
BEGIN
    FORALL i IN NUM_TAB.FIRST..NUM_TAB.LAST
    SAVE EXCEPTIONS
        INSERT INTO DIVISION_RESULT_Exception
        VALUES(1000 / NUM_TAB(i));
EXCEPTION
    WHEN DML_ERRORS THEN
        ERRORS := SQL%BULK_EXCEPTIONS.COUNT;
        DBMS_OUTPUT.PUT_LINE('Number of errors is ' || ERRORS);

        FOR i IN 1..ERRORS LOOP
            DBMS_OUTPUT.PUT_LINE('SQLCODE: ' || SQL%BULK_EXCEPTIONS(i).ERROR_INDEX);
            DBMS_OUTPUT.PUT_LINE('SQLERRM: ' ||SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
        END LOOP;
END;

Quando si tenta di convertire il codice precedente in SSMA, viene generato il messaggio di errore seguente:

O2SS0343: l'istruzione FORALL con clausola SAVE EXCEPTIONS non è supportata

Possibili rimedi

Una possibile correzione consiste nell'usare il blocco try e catch per gestire le eccezioni in T-SQL usando ERROR_NUMBER funzioni e anziché le SQLCODE funzioni Oracle e SQLERRMERROR_MESSAGE . Per questo motivo, è necessario aggiornare il codice di SQL Server come indicato di seguito:

BEGIN
    /* Declaration and initialization of table of input values */
    DECLARE
        @CollectionIndexInt$TYPE varchar(max) = ' TABLE OF DOUBLE'

    DECLARE
        @NUM_TAB dbo.CollectionIndexInt =
            dbo.CollectionIndexInt::[Null]
                .SetType(@CollectionIndexInt$TYPE)
                .AddDouble(1000)
                .AddDouble(0)
                .AddDouble(100)
                .AddDouble(0)
                .AddDouble(10)

    /* Declaration and initialization of other variables */
    DECLARE
        @ERRORS int,
        @DML_ERRORS$exception nvarchar(1000)

    SET @DML_ERRORS$exception = N'ORA-24381%'

    /* Declaration and initialization of temporary variables */
    DECLARE
        @i int

    SET @i = 1

    /* Running the loop for all the input values*/
    WHILE @i <= @NUM_TAB.Count
    BEGIN
        /* Performing the required operation in Try block */
        BEGIN TRY
            INSERT dbo.DIVISION_RESULT_EXCEPTION(RESULT)
            VALUES (1000 / @NUM_TAB.GetDouble(@i))
        END TRY

        /* Catch block to handle exception generated in Try block */
        BEGIN CATCH
            SET @Errors = @Errors + 1;
            PRINT ('SQL error is ' + CONVERT(varchar(20), ERROR_NUMBER()) +
                ':' + CONVERT(varchar(100), ERROR_MESSAGE()))

            PRINT (CONVERT(Varchar(30), ERROR_NUMBER()))
        END CATCH;

        /* Incrementing the loop variable */
        SET @i = @i + 1
    END
END
  • O2SS0282: RAISE senza eccezione specificata può essere inserito solo nel gestore eccezioni