Compartir a través de


O2SS0343: no se admite la instrucción FORALL con la cláusula SAVE EXCEPTION (error)

En este artículo se describe por qué SQL Server Migration Assistant (SSMA) para Oracle no admite la SAVE EXCEPTIONS cláusula en la FORALL instrucción .

Fondo

El control de excepciones es una construcción o mecanismo de lenguaje de programación diseñado para controlar la aparición de excepciones, condiciones especiales que cambian el flujo normal de ejecución del programa. En Oracle, la FORALL instrucción le permite ejecutar varias instrucciones DML de forma eficaz y solo puede repetir una sola instrucción DML, a diferencia de un bucle de uso FOR general. SAVE EXCEPTIONS la cláusula hace que el FORALL bucle continúe incluso si se produce un error en algunas operaciones DML.

El modelo de excepciones de Oracle difiere de SQL Server tanto en la generación de excepciones como en el control de excepciones. Es preferible usar el modelo de excepciones de SQL Server como parte de la migración de código PL/SQL de Oracle.

Cada vez que se FORALL usa la instrucción con SAVE EXCEPTIONS la cláusula , SSMA no la admite y genera un mensaje de error.

Ejemplo

En el ejemplo siguiente, se usa una FORALL instrucción con SAVE EXCEPTIONS cláusula .

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;

Al intentar convertir el código anterior en SSMA, genera el siguiente mensaje de error:

O2SS0343: no se admite la instrucción FORALL con la cláusula SAVE EXCEPTIONS.

Posibles soluciones

Una posible corrección consiste en usar el bloque try y catch para controlar las excepciones en T-SQL mediante ERROR_NUMBER funciones y ERROR_MESSAGE en lugar de las SQLCODE funciones de Oracle y SQLERRM .

Actualice el código de SQL Server de la manera siguiente:

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 sin excepción especificada solo se puede colocar en el controlador de excepciones.