Compartir a través de


O2SS0347: no se admite la comparación de expresiones de registro o colección (error)

En este artículo se describen los motivos por los que SQL Server Migration Assistant (SSMA) para Oracle no admite la comparación de variables de registro o recopilación.

Fondo

Una colección es un grupo ordenado de elementos, todo el mismo tipo. Es un concepto general que abarca listas, matrices y otros tipos de datos conocidos. Cada elemento tiene un subíndice único que determina su posición en la colección.

Cada vez que se encuentra un bloque PL/SQL con operador de comparación como = o IN con operandos de colección o registro de tipos, SSMA genera un mensaje de error.

Ejemplo

En el ejemplo siguiente, se comparan dos colecciones mediante el = operador :

DECLARE
    TYPE SIMPLE_COLLECTION IS TABLE OF INTEGER;
    VARCOLL1 SIMPLE_COLLECTION := SIMPLE_COLLECTION(1, 1, 1);
    VARCOLL2 SIMPLE_COLLECTION := SIMPLE_COLLECTION(1, 1, 1);
BEGIN
    IF VARCOLL1 = VARCOLL2 THEN
        DBMS_OUTPUT.PUT_LINE(1);
    ELSE
        DBMS_OUTPUT.PUT_LINE(0);
    END IF;
END;

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

O2SS0347: no se admite la comparación de expresiones de registro o colección

Posibles soluciones

La solución al error anterior es volver a escribir el código en Oracle. A diferencia de Oracle, SQL Server no admite registros o colecciones y sus operaciones asociadas. Por lo tanto, al migrar de Oracle a SQL Server mediante SSMA, debe aplicar transformaciones sustanciales al código PL/SQL.

Este es el código de Oracle reescrito:

DECLARE
    TYPE SIMPLE_COLLECTION IS TABLE OF INTEGER;
    VARCOLL1 SIMPLE_COLLECTION := SIMPLE_COLLECTION(1, 2,3);
    VARCOLL2 SIMPLE_COLLECTION := SIMPLE_COLLECTION(1, 2,3);
    j PLS_INTEGER := 0;
BEGIN
    IF VARCOLL1.count=VARCOLL2.count THEN
        FOR i IN 1..VARCOLL1.count
        LOOP
            IF VARCOLL1(i) = VARCOLL2(i) THEN
                j:=1;
            ELSE
                j:=0;
                DBMS_OUTPUT.PUT_LINE(0);
                EXIT;
            END IF;
        END LOOP;

        IF j = 1 THEN
            DBMS_OUTPUT.PUT_LINE(1);
        END IF;
    ELSE
        DBMS_OUTPUT.PUT_LINE(0);
    END IF;
END;

Esto se traduce al siguiente código de Transact-SQL mediante SSMA:

BEGIN
    DECLARE
        @CollectionIndexInt$TYPE varchar(max) = ' TABLE OF INT'

    DECLARE
        @VARCOLL1 dbo.CollectionIndexInt =
            dbo.CollectionIndexInt::[Null]
                .SetType(@CollectionIndexInt$TYPE)
                .AddInt(1)
                .AddInt(2)
                .AddInt(3),

        @VARCOLL2 dbo.CollectionIndexInt =
            dbo.CollectionIndexInt::[Null]
                .SetType(@CollectionIndexInt$TYPE)
                .AddInt(1)
                .AddInt(2)
                .AddInt(3),

        @j int = 0

    IF @VARCOLL1.Count = @VARCOLL2.Count
    BEGIN
        BEGIN
            DECLARE
                @i int

            SET @i = 1

            DECLARE
               @loop$bound int

            SET @loop$bound = @VARCOLL1.Count

            WHILE @i <= @loop$bound
            BEGIN
                IF @VARCOLL1.GetInt(@i) = @VARCOLL2.GetInt(@i)
                    SET @j = 1
                ELSE
                BEGIN
                    SET @j = 0
                    PRINT 0
                    BREAK
                END

                SET @i = @i + 1
            END
        END

        IF @j = 1
            PRINT 1
    END
    ELSE
        PRINT 0
END