Freigeben über


O2SS0343: FORALL-Anweisung mit SAVE EXCEPTION-Klausel wird nicht unterstützt (Fehler)

In diesem Artikel wird beschrieben, warum der SQL Server-Migrations-Assistent (SSMA) für Oracle die SAVE EXCEPTIONS Klausel in der FORALL Anweisung nicht unterstützt.

Hintergrund

Die Ausnahmebehandlung ist ein Programmiersprachenkonstrukt oder ein Mechanismus, der das Auftreten von Ausnahmen, spezielle Bedingungen, die den normalen Programmablauf ändern, behandeln soll. In Oracle FORALL können Sie mehrere DML-Anweisungen effizient ausführen und nur eine einzelne DML-Anweisung FOR wiederholen, im Gegensatz zu einer allgemeinen Schleife. SAVE EXCEPTIONS klausel bewirkt, dass die FORALL Schleife fortgesetzt wird, auch wenn einige DML-Vorgänge fehlschlagen.

Das Oracle-Ausnahmemodell unterscheidet sich von SQL Server sowohl bei der Ausnahmeaufhebung als auch bei der Ausnahmebehandlung. Es ist vorzuziehen, das SQL Server-Ausnahmenmodell als Teil der Oracle PL/SQL-Codemigration zu verwenden.

Wenn eine FORALL Anweisung mit SAVE EXCEPTIONS Klauseln verwendet wird, unterstützt SSMA sie nicht und generiert eine Fehlermeldung.

Beispiel

Im folgenden Beispiel verwenden Sie eine FORALL Anweisung mit SAVE EXCEPTIONS Klausel.

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;

Wenn Sie versuchen, den vorherigen Code in SSMA zu konvertieren, wird die folgende Fehlermeldung generiert:

O2SS0343: FORALL-Anweisung mit SAVE EXCEPTIONS-Klausel wird nicht unterstützt.

Mögliche Abhilfen

Eine mögliche Problembehebung besteht darin, den Try and Catch-Block zu verwenden, um die Ausnahmen in T-SQL mithilfe ERROR_NUMBER und ERROR_MESSAGE Funktionen anstelle der SQLCODE Oracle-Funktionen SQLERRM zu behandeln.

Aktualisieren Sie den SQL Server-Code wie folgt:

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 ohne Ausnahme kann nur im Ausnahmehandler platziert werden.