SnowConvert AI - Oracle - COLLECTIONS AND RECORDS

Référence de traduction pour convertir COLLECTIONS et RECORDS Oracle vers Snowflake Scripting

Avertissement

Les informations de cette section, en cours de modification, sont sujettes à modification.

Description générale

PL/SQL vous permet de définir deux types de données composites : collection et enregistrement, où composite est un type de données qui stocke des valeurs ayant des composants internes.

Dans une collection, les composants internes ont toujours le même type de données et sont appelés éléments.

Dans un enregistrement, les composants internes peuvent avoir différents types de données et sont appelés champs. (Référence linguistique Oracle PL/SQL COLLECTIONS AND RECORDS)

Note

Veuillez tenir compte de la référence de traduction d’instruction CREATE TYPE, car certaines solutions de contournement peuvent se chevaucher et peuvent être fonctionnelles dans les deux scénarios.

Limitations

Snowflake ne prend pas en charge les types de données définis par l’utilisateur, ce qui inclut les Collections et Enregistrements PL, selon la documentation en ligne Types de données non pris en charge, mais il supporte les types de données semi-structurées, qui peuvent être utilisés pour imiter à la fois la structure de type hiérarchie de l’enregistrement et la structure d’élément des types de collection définis par l’utilisateur. C’est pourquoi il existe plusieurs types de fonctions pour lesquelles il n’existe pas de solution de contournement.

Voici les fonctions pour lesquelles la solution de contournement NO est proposée :

La taille de la variable ne peut pas dépasser 16MB

Snowflake définit la taille maximale de VARIANT, OBJECT et ARRAY sur 16MBs. Cela signifie que si un enregistrement, une collection ou tout élément de l’un ou l’autre dépasse cette taille, une erreur d’exécution se produit.

La capacité de Varray ne peut pas être limitée

Les varrays d’Oracle offrent la capacité de limiter le nombre d’éléments qu’ils contiennent. Ceci n’est pas pris en charge par Snowflake.

Solution de contournement proposée

À propos de la définition des types d’enregistrement

La solution de contournement proposée consiste à utiliser un type de données semi-structurées « OBJECT » pour imiter le type de données d’Oracle.

À propos de la définition des types de collection

Il existe deux solutions différentes qui dépendent du type de collection à migrer :

  • Il est proposé de transformer les tableaux associatifs en un type de données semi-structurées « OBJECT ».

  • Il est proposé de transformer les Varrays et les Tableaux de tables imbriquées en un type de données semi-structurées « ARRAY ».

Prise en charge SnowConvert AI actuelle

Le tableau suivant présente un résumé de la prise en charge actuelle par l’outil SnowConvert AI. Veuillez tenir compte du fait que les traductions peuvent ne pas être finales et que des tâches supplémentaire peuvent être nécessaire.

Sous-fonctionnalité

Statut actuel de reconnaissance

Statut actuel de la traduction

Solutions de contournement connues

Définitions de type d’enregistrement

Reconnu.

Non traduit.

Oui.

Définitions de type Array (tableau) associatif

Non reconnu.

Non traduit.

Oui.

Définitions de type Array (tableau)

Reconnu.

Non traduit.

Oui.

Définitions de type Array (tableau) de tables imbriquées

Reconnu.

Non traduit.

Oui.

Problèmes connus

1. Associate Arrays are considered a Nested Table

Actuellement, SnowConvert AI ne fait pas la différence entre un tableau associatif et une table imbriquée, ce qui signifie qu’ils sont mélangés dans les mêmes comptages d’évaluation.

Définition du type de tableau associatif

Il s’agit d’une référence de traduction pour convertir la déclaration Array (tableau) associatif Oracle vers Snowflake.

Avertissement

Les informations de cette section, en cours de modification, sont sujettes à modification.

Note

Certaines parties du code de sortie sont omises pour des raisons de clarté.

Description

Un tableau associatif (anciennement appelé table PL/SQL ou table index-by) est un ensemble de paires clé-valeur. Chaque clé est un index unique, utilisé pour l’emplacement de la valeur associée avec la syntaxe variable_name(index).

Le type de données de l”index peut être un type de chaîne (VARCHAR2, VARCHAR, STRING ou LONG) ou PLS_INTEGER. Les index sont stockés par ordre de tri, et non par ordre de création. Pour les types de chaînes, l’ordre de tri est déterminé par les paramètres d’initialisation NLS_SORT et NLS_COMP.

(Référence linguistique Oracle PL/SQL ASSOCIATIVE ARRAYS)

Avertissement

À ne pas confondre avec la définition du type Type de définition PL/SQL NESTED TABLE.

Pour la traduction, la définition du type est remplacée par un OBJECT Type de données semi-structurées et son utilisation est modifiée en conséquence pour toutes les opérations.

Pour définir un type de tableau associatif, la syntaxe est la suivante :

type_definition := TYPE IS TABLE OF datatype INDEX BY indexing_datatype;

indexing_datatype := { PLS_INTEGER
                     | BINARY_INTEGER
                     | string_datatype
                     }
Copy

Pour déclarer une variable de ce type :

variable_name collection_type;

Copy

Modèles d’échantillons de sources

Tableau associatif indexé Varchar

Oracle
CREATE OR REPLACE PROCEDURE associative_array
IS
    TYPE associate_array_typ IS TABLE OF INTEGER
        INDEX BY VARCHAR2(50);
        
    associate_array associate_array_typ := associate_array_typ();
    associate_index VARCHAR2(50);
BEGIN
    associate_array('abc') := 1;
    associate_array('bca') := 2;
    associate_array('def') := 3;
    
    DBMS_OUTPUT.PUT_LINE(associate_array('abc'));
    associate_array('abc') := 4;
    --THROWS 'NO DATA FOUND'
    --DBMS_OUTPUT.PUT_LINE(associate_array('no exists'));
    
    DBMS_OUTPUT.PUT_LINE(associate_array.COUNT);
    
    associate_index := associate_array.FIRST;
    WHILE associate_index IS NOT NULL
    LOOP
        DBMS_OUTPUT.PUT_LINE(associate_array(associate_index));
        associate_index := associate_array.NEXT(associate_index);
    END LOOP;
END;

CALL associative_array();
Copy
Résultat

DBMS OUTPUT

1

3

4

2

3

Snowflake

Veuillez noter le paramètre « true » dans le OBJECT_INSERT. Ainsi, l’élément est mis à jour s’il est déjà présent dans le tableau.

CREATE OR REPLACE PROCEDURE PUBLIC.associative_array ()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
   DECLARE
      associate_array OBJECT := OBJECT_CONSTRUCT();
      associate_index VARCHAR(50);
   BEGIN
      associate_array := OBJECT_INSERT(associate_array, 'abc', 1, true);
      associate_array := OBJECT_INSERT(associate_array, 'bca', 2, true);
      associate_array := OBJECT_INSERT(associate_array, 'def', 3, true);

      CALL DBMS_OUTPUT.PUT_LINE(:associate_array['abc']);
      CALL DBMS_OUTPUT.PUT_LINE(:associate_array['not found']);
      
      associate_array := OBJECT_INSERT(:associate_array, 'abc', 4, true);
    
      CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(OBJECT_KEYS(:associate_array)));
      
      FOR i IN 1 TO ARRAY_SIZE(OBJECT_KEYS(:associate_array))
      LOOP
         associate_index := OBJECT_KEYS(:associate_array)[:i-1];
         CALL DBMS_OUTPUT.PUT_LINE(:associate_array[:associate_index]);
      END LOOP;
   END;
$$;

CALL PUBLIC.associative_array();
SELECT * FROM DBMS_OUTPUT.DBMS_OUTPUT_LOG;
Copy
Résultat

DBMS OUTPUT

1

3

4

2

3

Tableau associatif indexé numériquement

Oracle
CREATE OR REPLACE PROCEDURE numeric_associative_array
IS
    TYPE numeric_associative_array_typ IS TABLE OF INTEGER
        INDEX BY PLS_INTEGER;
        
    associate_array numeric_associativ
    e_array_typ := numeric_associative_array_typ();
    associate_index PLS_INTEGER;
BEGIN
    associate_array(1) := -1;
    associate_array(2) := -2;
    associate_array(3) := -3;
    
    DBMS_OUTPUT.PUT_LINE(associate_array(1));
    associate_array(1) := -4;
    
    DBMS_OUTPUT.PUT_LINE(associate_array.COUNT);
    
    associate_index := associate_array.FIRST;
    WHILE associate_index IS NOT NULL
    LOOP
        DBMS_OUTPUT.PUT_LINE(associate_array(associate_index));
        associate_index := associate_array.NEXT(associate_index);
    END LOOP;
END;

CALL numeric_associative_array();
Copy
Résultat

DBMS OUTPUT

-1

3

-4

-2

-3

Snowflake

Veuillez noter que la valeur numérique est convertie en varchar lorsque l’opération le nécessite. En outre, notez le paramètre « true » dans OBJECT_INSERT. Ainsi, l’élément est mis à jour s’il est déjà présent dans le tableau.

CREATE OR REPLACE PROCEDURE PUBLIC.numeric_associative_array ()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
   DECLARE
      associate_array OBJECT := OBJECT_CONSTRUCT();
      associate_index NUMBER;
   BEGIN
      associate_array := OBJECT_INSERT(associate_array, '1', -1, true);
      associate_array := OBJECT_INSERT(associate_array, '2', -2, true);
      associate_array := OBJECT_INSERT(associate_array, '3', -3, true);

      CALL DBMS_OUTPUT.PUT_LINE(:associate_array['1']);
      
      associate_array := OBJECT_INSERT(:associate_array, '1', -4, true);
    
      CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(OBJECT_KEYS(:associate_array)));
      
      FOR i IN 1 TO ARRAY_SIZE(OBJECT_KEYS(:associate_array))
      LOOP
         associate_index := OBJECT_KEYS(:associate_array)[:i-1];
         CALL DBMS_OUTPUT.PUT_LINE(:associate_array[:associate_index::VARCHAR]);
      END LOOP;
   END;
$$;

CALL PUBLIC.numeric_associative_array();
SELECT * FROM DBMS_OUTPUT.DBMS_OUTPUT_LOG;
Copy
Résultat

DBMS OUTPUT

-1

3

-4

-2

-3

Tableau associatif à éléments numériques indexés par enregistrement

Dans ce cas, le tableau associatif est composé d’une structure d’enregistrement, et cette structure doit être préservée. À cette fin, d’autres opérations sur les insertions ont été ajoutées.

Oracle
CREATE OR REPLACE PROCEDURE record_associative_array
IS
    TYPE record_typ IS RECORD(col1 INTEGER);
    TYPE record_associative_array_typ IS TABLE OF record_typ
        INDEX BY PLS_INTEGER;
        
    associate_array record_associati ve_array_typ := record_associative_array_typ();
    associate_index PLS_INTEGER;
BEGIN
    associate_array(1).col1 := -1;
    associate_array(2).col1 := -2;
    associate_array(3).col1 := -3;
    
    DBMS_OUTPUT.PUT_LINE(associate_array(1).col1);
    associate_array(4).col1 := -4;
    
    DBMS_OUTPUT.PUT_LINE(associate_array.COUNT);
    
    associate_index := associate_array.FIRST;
    WHILE associate_index IS NOT NULL
    LOOP
        DBMS_OUTPUT.PUT_LINE(associate_array(associate_index).col1);
        associate_index := associate_array.NEXT(associate_index);
    END LOOP;
END;
/

CALL record_associative_array();
Copy
Résultat

DBMS OUTPUT

-1

3

-4

-2

-3

Snowflake

Dans ce scénario, l’insertion/mise à jour suppose une création automatique de l’enregistrement dans le tableau associatif, ce qui doit être pris en compte lors de la création de nouveaux enregistrements.

CREATE OR REPLACE PROCEDURE PUBLIC.record_associative_array ()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
   DECLARE
      associate_array OBJECT := OBJECT_CONSTRUCT();
      associate_index NUMBER;
   BEGIN
      associate_array := OBJECT_INSERT(associate_array, '1', OBJECT_INSERT(NVL(associate_array['1'], OBJECT_CONSTRUCT()), 'col1', -1, true), true);
      associate_array := OBJECT_INSERT(associate_array, '2', OBJECT_INSERT(NVL(associate_array['2'], OBJECT_CONSTRUCT()), 'col1', -2, true), true);
      associate_array := OBJECT_INSERT(associate_array, '3', OBJECT_INSERT(NVL(associate_array['3'], OBJECT_CONSTRUCT()), 'col1', -3, true), true);

      CALL DBMS_OUTPUT.PUT_LINE(:associate_array['1']:col1);
      
      associate_array := OBJECT_INSERT(associate_array, '1', OBJECT_INSERT(NVL(associate_array['1'], OBJECT_CONSTRUCT()), 'col1', -4, true), true);
    
      CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(OBJECT_KEYS(:associate_array)));
      
      FOR i IN 1 TO ARRAY_SIZE(OBJECT_KEYS(:associate_array))
      LOOP
         associate_index := OBJECT_KEYS(:associate_array)[:i-1];
         CALL DBMS_OUTPUT.PUT_LINE(:associate_array[:associate_index::VARCHAR]:col1);
      END LOOP;
   END;
$$;

CALL PUBLIC.record_associative_array();
SELECT * FROM DBMS_OUTPUT.DBMS_OUTPUT_LOG;
Copy
Résultat

DBMS OUTPUT

-1

3

-4

-2

-3

Problèmes connus

1. They are currently not being recognized

SnowConvert AI traite ces collections comme des tableaux de tables imbriquées. Il existe une solution pour y remédier.

EWIs connexes

Pas d’EWIs connexes.

Méthodes de collection

Il s’agit d’une référence de traduction pour convertir les méthodes de collection Oracle vers Snowflake.

Avertissement

Les informations de cette section, en cours de modification, sont sujettes à modification.

Note

Certaines parties du code de sortie sont omises pour des raisons de clarté.

Description

Une méthode de collection est un sous-programme PL/SQL - soit une fonction qui renvoie des informations sur une collection, soit une procédure qui opère sur une collection. Les méthodes de collection facilitent l’utilisation des collections et la maintenance de vos applications.

(Référence linguistique Oracle PL/SQL COLLECTION METHODS)

Certaines de ces méthodes peuvent être mappées à des opérations semi-structurées natives de Snowflake. Celles qui ne le peuvent pas ou qui présentent des différences seront mappées à une implémentation d’UDF.

Prise en charge SnowConvert AI actuelle

Le tableau suivant présente un résumé de la prise en charge actuelle par l’outil SnowConvert AI. Veuillez tenir compte du fait que les traductions peuvent ne pas être finales et que des tâches supplémentaire peuvent être nécessaire.

Méthode

Statut actuel de reconnaissance

Statut actuel de la traduction

Mappé vers

DELETE

Non reconnu.

Non traduit.

UDF

TRIM

Non reconnu.

Non traduit.

UDF (à définir)

EXTEND

Non reconnu.

Non traduit.

UDF

EXISTS

Non reconnu.

Non traduit.

ARRAY_CONTAINS

FIRST

Non reconnu.

Non traduit.

UDF

LAST

Non reconnu.

Non traduit.

UDF

COUNT

Non reconnu.

Non traduit.

ARRAY_SIZE

LIMIT

Non reconnu.

Non traduit.

Non pris en charge.

PRIOR

Non reconnu.

Non traduit.

UDF (à définir)

NEXT

Non reconnu.

Non traduit.

UDF (à définir)

Modèles d’échantillons de sources

COUNT

Cette méthode renvoie le nombre d’éléments « non définis » (à ne pas confondre avec les éléments null) dans une collection (les tables imbriquées peuvent devenir clairsemées en laissant ces éléments entre elles). Dans les tableaux associatifs, elle renvoie le nombre de clés du tableau.

Oracle
CREATE OR REPLACE PROCEDURE collection_count
IS
    TYPE varray_typ IS VARRAY(5) OF INTEGER;
    TYPE nt_typ IS TABLE OF INTEGER;
    TYPE aa_typ IS TABLE OF INTEGER INDEX BY VARCHAR2(20);
    
    associative_array aa_typ := aa_typ('abc'=>1, 'bca'=>1);
    varray_variable varray_typ := varray_typ(1, 2, 3);
    nt_variable nt_typ := nt_typ(1, 2, 3, 4);
BEGIN
    DBMS_OUTPUT.PUT_LINE(associative_array.COUNT);
    DBMS_OUTPUT.PUT_LINE(varray_variable.COUNT);
    DBMS_OUTPUT.PUT_LINE(nt_variable.COUNT);
END;

CALL collection_count();
Copy
Résultat

DBMS OUTPUT

2

3

4

Snowflake

L’équivalent du Snowflake est la méthode ARRAY_SIZE.

CREATE OR REPLACE PROCEDURE PUBLIC.collection_count()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
    associative_array OBJECT := OBJECT_CONSTRUCT('abc', 1, 'bca', 1);
    varray_variable ARRAY := ARRAY_CONSTRUCT(1, 2, 3);
    nt_variable ARRAY := ARRAY_CONSTRUCT(1, 2, 3, 4);
BEGIN
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(OBJECT_KEYS(:associative_array)));
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(:varray_variable));
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(:nt_variable));
END;
$$;

CALL PUBLIC.collection_count();
SELECT * FROM DBMS_OUTPUT.DBMS_OUTPUT_LOG;
Copy
Résultat

DBMS OUTPUT

2

3

4

EXISTS

Cette méthode renvoie un résultat positif si l’élément donné est contenu dans la collection. Dans les tableaux associatifs, il teste si la clé est contenue.

Oracle
CREATE OR REPLACE PROCEDURE collection_exists
IS
    TYPE nt_typ IS TABLE OF INTEGER;
    TYPE aa_typ IS TABLE OF INTEGER INDEX BY VARCHAR2(20);
    
    associative_array aa_typ := aa_typ('abc'=>1, 'bca'=>1);
    nt_variable nt_typ := nt_typ(1, 2, 3, 4);
BEGIN
    IF associative_array.EXISTS('abc')
    THEN DBMS_OUTPUT.PUT_LINE('Found');
    END IF;
    
    IF NOT associative_array.EXISTS('not found')
    THEN DBMS_OUTPUT.PUT_LINE('Not found');
    END IF;
    
    IF nt_variable.EXISTS(1)
    THEN DBMS_OUTPUT.PUT_LINE('Found');
    END IF;
    
    IF NOT nt_variable.EXISTS(5)
    THEN DBMS_OUTPUT.PUT_LINE('Not found');
    END IF;
END;
/

CALL collection_exists();
Copy
Résultat

DBMS OUTPUT

2

3

4

Snowflake

L’équivalent du Snowflake est la méthode ARRAY_CONTAINS. Notez que, lors de l’utilisation d’éléments Varchar, il est nécessaire d’effectuer une conversion vers Variant.

CREATE OR REPLACE PROCEDURE PUBLIC.collection_exists()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
    associative_array OBJECT := OBJECT_CONSTRUCT('abc', 1, 'bca', 1);
    nt_variable ARRAY := ARRAY_CONSTRUCT(1, 2, 3, 4);
BEGIN
    IF (ARRAY_CONTAINS('abc'::VARIANT, OBJECT_KEYS(associative_array)))
    THEN CALL DBMS_OUTPUT.PUT_LINE('Found');
    END IF;
    
    IF (NOT ARRAY_CONTAINS('not found'::VARIANT, OBJECT_KEYS(associative_array)))
    THEN CALL DBMS_OUTPUT.PUT_LINE('Not found');
    END IF;
    
    IF (ARRAY_CONTAINS(1, nt_variable))
    THEN CALL DBMS_OUTPUT.PUT_LINE('Found');
    END IF;
    
    IF (NOT ARRAY_CONTAINS(5, nt_variable))
    THEN CALL DBMS_OUTPUT.PUT_LINE('Not found');
    END IF;
END;
$$;

CALL PUBLIC.collection_exists();
SELECT * FROM DBMS_OUTPUT.DBMS_OUTPUT_LOG;
Copy
Résultat

DBMS OUTPUT

2

3

4

FIRST/LAST

Ces deux méthodes renvoient respectivement le premier et le dernier élément de la collection. Si la collection est vide, elle renvoie null. Cette opération est mappée à une UDF, qui sera ajoutée dans les révisions ultérieures.

Oracle
CREATE OR REPLACE PROCEDURE collection_first_last
IS
    TYPE nt_typ IS TABLE OF INTEGER;
    TYPE aa_typ IS TABLE OF INTEGER INDEX BY VARCHAR2(20);
    
    associative_array aa_typ := aa_typ('abc'=>1, 'bca'=>1);
    nt_variable nt_typ := nt_typ();
BEGIN
    DBMS_OUTPUT.PUT_LINE(associative_array.FIRST);
    DBMS_OUTPUT.PUT_LINE(associative_array.LAST);
    
    DBMS_OUTPUT.PUT_LINE(nt_variable.FIRST);
    DBMS_OUTPUT.PUT_LINE(nt_variable.LAST);
    nt_variable := nt_typ(1, 2, 3, 4);
    DBMS_OUTPUT.PUT_LINE(nt_variable.FIRST);
    DBMS_OUTPUT.PUT_LINE(nt_variable.LAST);
END;
/

CALL collection_first_last();
Copy
Résultat

DBMS OUTPUT

abc

bca

–Ces espaces vides sont dus au fait qu’ils correspondent à null

1

4

Snowflake
CREATE OR REPLACE PROCEDURE PUBLIC.collection_first_last()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
    associative_array OBJECT := OBJECT_CONSTRUCT('abc', 1, 'bca', 1);
    nt_variable ARRAY := ARRAY_CONSTRUCT();
BEGIN
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_FIRST(:associative_array));
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_LAST(:associative_array));
    
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_FIRST(:nt_variable));
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_LAST(:nt_variable));
    nt_variable := ARRAY_CONSTRUCT(1, 2, 3, 4);
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_FIRST(:nt_variable));
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_LAST(:nt_variable));
END;
$$;

CALL PUBLIC.collection_first_last();
SELECT * FROM DBMS_OUTPUT.DBMS_OUTPUT_LOG;
Copy
UDFs
CREATE OR REPLACE FUNCTION ARRAY_FIRST(array_variable VARIANT)
RETURNS VARIANT
LANGUAGE SQL
AS
$$
    IFF (IS_OBJECT(array_variable),
        ARRAY_FIRST(OBJECT_KEYS(array_variable)),
        IFF (ARRAY_SIZE(array_variable) = 0, null, array_variable[0]))
$$;

CREATE OR REPLACE FUNCTION ARRAY_LAST(array_variable VARIANT)
RETURNS VARIANT
LANGUAGE SQL
AS
$$
    IFF (IS_OBJECT(array_variable),
        ARRAY_LAST(OBJECT_KEYS(array_variable)),
        IFF (ARRAY_SIZE(array_variable) = 0, null, array_variable[ARRAY_SIZE(array_variable)-1]))
$$;
Copy
Résultat

DBMS OUTPUT

abc

bca

–Ces espaces vides sont dus au fait qu’ils correspondent à null

1

4

DELETE

Cette méthode permet de supprimer des éléments d’une collection. Il existe trois variantes possibles :

  • .DELETE supprime tous les éléments.

  • .DELETE(n) supprime l’élément dont l’index correspond à « n ».

  • .DELETE(n, m) supprime les index de « n » à « m ».

Note

Dans Oracle, l’utilisation de cette opération sur des tables imbriquées entraîne l’apparition d’éléments « non définis » à l’intérieur de ces tables en raison de leur faible densité.

Avertissement

Veuillez noter que les deuxième et troisième versions ne s’appliquent pas aux Varrays.

Oracle

Par souci de simplicité, cet échantillon ne vérifie que le nombre d’éléments, mais il peut être modifié pour afficher le contenu de chaque collection.

CREATE OR REPLACE PROCEDURE collection_delete
IS
    TYPE varray_typ IS VARRAY(5) OF INTEGER;
    TYPE nt_typ IS TABLE OF INTEGER;
    TYPE aa_typ IS TABLE OF INTEGER INDEX BY VARCHAR2(20);
    
    associative_array1 aa_typ := aa_typ('abc'=>1, 'def'=>2, 'ghi'=>3, 'jkl'=>4);
    associative_array2 aa_typ := aa_typ('abc'=>1, 'def'=>2, 'ghi'=>3, 'jkl'=>4);
    associative_array3 aa_typ := aa_typ('abc'=>1, 'def'=>2, 'ghi'=>3, 'jkl'=>4);
    
    varray_variable1 varray_typ := varray_typ(1, 2, 3, 4);
    
    nt_variable1 nt_typ := nt_typ(1, 2, 3, 4);
    nt_variable2 nt_typ := nt_typ(1, 2, 3, 4);
    nt_variable3 nt_typ := nt_typ(1, 2, 3, 4);
BEGIN
    varray_variable1.DELETE;--delete everything
    
    nt_variable1.DELETE;--delete everything
    nt_variable2.DELETE(2);--delete second position
    nt_variable3.DELETE(2, 3);--delete range
    
    associative_array1.DELETE;--delete everything
    associative_array2.DELETE('def');--delete second position
    associative_array3.DELETE('def', 'jkl');--delete range
    
    DBMS_OUTPUT.PUT_LINE(varray_variable1.COUNT);
    DBMS_OUTPUT.PUT_LINE(nt_variable1.COUNT);
    DBMS_OUTPUT.PUT_LINE(nt_variable2.COUNT);
    DBMS_OUTPUT.PUT_LINE(nt_variable3.COUNT);
    
    DBMS_OUTPUT.PUT_LINE(associative_array1.COUNT);
    DBMS_OUTPUT.PUT_LINE(associative_array2.COUNT);
    DBMS_OUTPUT.PUT_LINE(associative_array3.COUNT);
END;
/

CALL collection_delete();
Copy
Résultat

DBMS OUTPUT

0

0

3

2

0

3

1

Snowflake

Snowflake ne prend pas en charge les suppressions à partir d’un ARRAY existant et pour cette raison, la seule solution proposée est de reconstruire un nouveau ARRAY en fonction des paramètres d’origine de DELETE.

Note

Notez qu’une UDF a été ajoutée pour mettre en œuvre la fonctionnalité de mise à jour de l’élément.

Cette UDF sera ajoutée dans les révisions ultérieures.

CREATE OR REPLACE PROCEDURE PUBLIC.collection_delete()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
    associative_array1 OBJECT := OBJECT_CONSTRUCT('abc'=>1, 'def'=>2, 'ghi'=>3, 'jkl'=>4);
    associative_array2 OBJECT := OBJECT_CONSTRUCT('abc'=>1, 'def'=>2, 'ghi'=>3, 'jkl'=>4);
    associative_array3 OBJECT := OBJECT_CONSTRUCT('abc'=>1, 'def'=>2, 'ghi'=>3, 'jkl'=>4);
    
    varray_variable1 ARRAY := ARRAY_CONSTRUCT(1, 2, 3, 4);
    
    nt_variable1 ARRAY := ARRAY_CONSTRUCT(1, 2, 3, 4);
    nt_variable2 ARRAY := ARRAY_CONSTRUCT(1, 2, 3, 4);
    nt_variable3 ARRAY := ARRAY_CONSTRUCT(1, 2, 3, 4);
BEGIN
    varray_variable1 := ARRAY_CONSTRUCT();--delete everything
    
    nt_variable1 := ARRAY_CONSTRUCT();--delete everything
    nt_variable2 := ARRAY_DELETE_UDF(nt_variable2, 2);--delete second position
    nt_variable3 := ARRAY_DELETE_UDF(nt_variable3, 2, 3);--delete range
    
    associative_array1 := OBJECT_CONSTRUCT();--delete everything
    associative_array2 := ASSOCIATIVE_ARRAY_DELETE_UDF('def');--delete second position
    associative_array3 := ASSOCIATIVE_ARRAY_DELETE_UDF('def', 'jkl');--delete range
    
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(varray_variable1));
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(nt_variable1);
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(nt_variable2);
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(nt_variable3);
    
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(associative_array1));
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(associative_array2));
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(associative_array3));
END;
$$;

CALL PUBLIC.collection_first_last();
SELECT * FROM DBMS_OUTPUT.DBMS_OUTPUT_LOG;
Copy
Résultat

DBMS OUTPUT

0

0

3

2

0

3

1

EXTEND

Cette méthode est utilisée pour ajouter de nouveaux éléments à une table imbriquée ou à un Varray. Il existe trois variantes possibles :

  • .EXTEND insère un élément null.

  • .EXTEND(n) insère « n » éléments nulls.

  • .EXTEND(n, i) insère « n » copies de l’élément situé à « i ».

Oracle
CREATE OR REPLACE PROCEDURE collection_extend
IS 
    TYPE varray_typ IS VARRAY(5) OF INTEGER;
    TYPE nt_typ IS TABLE OF INTEGER;
    
    nt_variable1 nt_typ := nt_typ(1, 2, 3, 4);
    varray_variable1 varray_typ := varray_typ(1, 2, 3);
    varray_variable2 varray_typ := varray_typ(1, 2, 3);
BEGIN
    nt_variable1.EXTEND;
    varray_variable1.EXTEND(2);
    varray_variable2.EXTEND(2, 1);
    
    DBMS_OUTPUT.PUT_LINE(nt_variable1.COUNT);
    DBMS_OUTPUT.PUT_LINE(varray_variable1.COUNT);
    DBMS_OUTPUT.PUT_LINE(varray_variable2.COUNT);
END;
/

CALL collection_extend();
Copy
Résultat

DBMS OUTPUT

5

5

5

Snowflake

Note

Notez qu’une UDF a été ajoutée pour mettre en œuvre la fonctionnalité de mise à jour de l’élément.

Cette UDF sera ajoutée dans les révisions ultérieures.

CREATE OR REPLACE PROCEDURE PUBLIC.collection_first_last()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
    nt_variable1 ARRAY := ARRAY_CONSTRUCT(1, 2, 3, 4);
    varray_variable1 ARRAY := ARRAY_CONSTRUCT(1, 2, 3);
    varray_variable2 ARRAY := ARRAY_CONSTRUCT(1, 2, 3);
BEGIN
    nt_variable1 := ARRAY_EXTEND_UDF(nt_variable);
    varray_variable1 := ARRAY_EXTEND_UDF(varray_variable1, 2);
    varray_variable2 := ARRAY_EXTEND_UDF(varray_variable2, 2, 1);
    
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(nt_variable1);
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(varray_variable1));
    CALL DBMS_OUTPUT.PUT_LINE(ARRAY_SIZE(varray_variable2));
END;
$$;

CALL PUBLIC.collection_first_last();
SELECT * FROM DBMS_OUTPUT.DBMS_OUTPUT_LOG;
Copy
Résultat

DBMS OUTPUT

5

5

5

TRIM

Cette méthode est utilisée pour supprimer les derniers éléments d’une table imbriquée ou d’un Varray. Il existe deux variantes possibles :

  • .TRIM supprime le dernier élément.

  • .TRIM(n) supprime les « n » derniers éléments.

Note

Cette fonctionnalité peut être mise en œuvre à l’aide de ARRAY_SLICE

Oracle
CREATE OR REPLACE PROCEDURE collection_trim
IS 
    TYPE varray_typ IS VARRAY(5) OF INTEGER;
    TYPE nt_typ IS TABLE OF INTEGER;
    
    varray_variable1 varray_typ := varray_typ(1, 2, 3);
    nt_variable1 nt_typ := nt_typ(1, 2, 3, 4);
BEGIN
    varray_variable1.TRIM;
    nt_variable1.TRIM(2);
    
    DBMS_OUTPUT.PUT_LINE(nt_variable1.COUNT);
    DBMS_OUTPUT.PUT_LINE(varray_variable1.COUNT);
END;
/

CALL collection_trim();
Copy
Résultat
DBMS OUTPUT
-----------
2
2

Copy

LIMIT

Cette méthode renvoie la limite maximale d’un Varray.

Danger

Cette méthode n’est pas prise en charge par Snowflake.

Oracle
CREATE OR REPLACE PROCEDURE collection_limit
IS 
    TYPE varray_typ1 IS VARRAY(5) OF INTEGER;
    TYPE varray_typ2 IS VARRAY(6) OF INTEGER;
    
    varray_variable1 varray_typ1 := varray_typ1(1, 2, 3);
    varray_variable2 varray_typ2 := varray_typ2(1, 2, 3, 4);
BEGIN
    DBMS_OUTPUT.PUT_LINE(varray_variable1.LIMIT);
    DBMS_OUTPUT.PUT_LINE(varray_variable2.LIMIT);
END;
/

CALL collection_limit();
Copy
Résultat

DBMS OUTPUT

5

6

PRIOR/NEXT

Cette méthode renvoie l’index précédent/suivant, compte tenu d’un index. S’il n’y a pas d’antécédent/suivant, il renvoie null. Il est le plus souvent utilisé pour parcourir une collection.

Oracle
CREATE OR REPLACE PROCEDURE collection_prior_next
IS 
    TYPE varray_typ1 IS VARRAY(5) OF INTEGER;
    TYPE aa_typ IS TABLE OF INTEGER INDEX BY VARCHAR2(20);
    
    varray_variable1 varray_typ1 := varray_typ1(-1, -2, -3);
    associative_array1 aa_typ := aa_typ('abc'=>1, 'def'=>2, 'ghi'=>3, 'jkl'=>4);
BEGIN
    DBMS_OUTPUT.PUT_LINE(varray_variable1.PRIOR(1));
    DBMS_OUTPUT.PUT_LINE(varray_variable1.PRIOR(2));
    DBMS_OUTPUT.PUT_LINE(varray_variable1.NEXT(2));
    DBMS_OUTPUT.PUT_LINE(varray_variable1.NEXT(3));
    
    DBMS_OUTPUT.PUT_LINE(associative_array1.PRIOR('abc'));
    DBMS_OUTPUT.PUT_LINE(associative_array1.PRIOR('def'));
    DBMS_OUTPUT.PUT_LINE(associative_array1.NEXT('ghi'));
    DBMS_OUTPUT.PUT_LINE(associative_array1.NEXT('jkl'));
    DBMS_OUTPUT.PUT_LINE(associative_array1.PRIOR('not found'));
END;
/

CALL collection_prior_next();
Copy
Résultat

DBMS OUTPUT

– Les espaces vides sont dus aux résultats nuls

1

3

abc

jkl

jkl

Problèmes connus

1. Limit method is not supported in Snowflake

Snowflake ne prend pas en charge les varrays à espace limité. C’est pourquoi cette méthode n’est pas prise en charge.

EWIs connexes

Pas d’EWIs connexes.

Définition du type de tableau de tables imbriquées

Il s’agit d’une référence de traduction pour convertir la déclaration de tableau de tables imbriquées d’Oracle vers Snowflake

Avertissement

Les informations de cette section, en cours de modification, sont sujettes à modification.

Note

Cette section concerne la version PL/SQL des tableaux de tables imbriquées, pour la version autonome, voir Définition du type de table imbriquée.

Note

Certaines parties du code de sortie sont omises pour des raisons de clarté.

Description

Dans la base de données, une table imbriquée est un type de colonne qui stocke un nombre indéterminé de lignes sans ordre particulier.

Lorsque vous récupérez une valeur de table imbriquée de la base de données dans une variable de table imbriquée PL/SQL, PL/SQL donne aux lignes des index consécutifs, en commençant par 1. Grâce à ces index, vous pouvez accéder aux différentes lignes de la variable de la table imbriquée. La syntaxe est la suivante : variable_name(index). Les index et l’ordre des lignes d’une table imbriquée peuvent ne pas rester stables lorsque vous stockez et récupérez la table imbriquée dans la base de données.

(Référence linguistique Oracle PL/SQL NESTED TABLES)

Pour la traduction, la définition du type est remplacée par un ARRAY type de données semi-structurées et son utilisation est modifiée en conséquence pour toutes les opérations. Veuillez noter que la traduction pour les tables imbriquées et les varrays est la même.

Pour définir un type de tableau de tables imbriquées, la syntaxe est la suivante :

type_definition := TYPE IS TABLE OF datatype;

Copy

Pour déclarer une variable de ce type :

variable_name collection_type;

Copy

Modèles d’échantillons de sources

Définitions des tableaux de tables imbriquées

Ceci illustre comment créer différents tableaux de tables imbriquées et comment migrer les définitions des variables.

Oracle
CREATE OR REPLACE PROCEDURE nested_table_procedure
IS
    TYPE nested_table_array_typ IS TABLE OF INTEGER;
    TYPE nested_table_array_typ2 IS TABLE OF DATE;
    
    nested_table_array nested_table_array_typ;
    nested_table_array2 nested_table_array_typ2;
BEGIN
    NULL;
END;
Copy
Snowflake
CREATE OR REPLACE PROCEDURE nested_table_procedure()
RETURNS INTEGER
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
    -- NO LONGER NEEDED
    /*
    TYPE associative_array_typ IS TABLE OF INTEGER INDEX BY VARCHAR2(30);
    TYPE associative_array_typ2 IS TABLE OF INTEGER INDEX BY PLS_INTEGER;
    */
    
    associative_array ARRAY;
    associative_array2 ARRAY;
BEGIN
    NULL;
END;
$$;
Copy

Itération des tables imbriquées

Oracle
CREATE OR REPLACE PROCEDURE nested_table_iteration
IS
    TYPE nested_table_typ IS TABLE OF INTEGER;
    nested_table_variable nested_table_typ := nested_table_typ (10, 20, 30);
BEGIN
    FOR i IN 1..nested_table_variable.COUNT
    LOOP
        DBMS_OUTPUT.PUT_LINE(nested_table_variable(i));
    END LOOP;
    
    nested_table_variable (1) := 40;
    
    FOR i IN 1..nested_table_variable.COUNT
    LOOP
        DBMS_OUTPUT.PUT_LINE(nested_table_variable(i));
    END LOOP;
END;
/

CALL nested_table_iteration();
Copy
Résultat

DBMS OUTPUT

10

20

30

40

20

30

Snowflake

Note

Notez qu’une UDF a été ajoutée pour mettre en œuvre la fonctionnalité de mise à jour de l’élément.

Cette UDF sera ajoutée dans les révisions ultérieures.

CREATE OR REPLACE PROCEDURE PUBLIC.nested_table_iteration()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
DECLARE
    nested_table_variable ARRAY := ARRAY_CONSTRUCT(10, 20, 30);
BEGIN
    FOR i IN 1 TO ARRAY_SIZE(nested_table_variable)
    LOOP
        CALL DBMS_OUTPUT.PUT_LINE(:nested_table_variable[:i-1]);
    END LOOP;

    nested_table_variable:= INSERT_REPLACE_COLLECTION_ELEMENT_UDF(nested_table_variable, 1, 40);
    
    FOR i IN 1 TO ARRAY_SIZE(nested_table_variable)
    LOOP
        CALL DBMS_OUTPUT.PUT_LINE(:nested_table_variable[:i-1]);
    END LOOP;
END;
$$;

CALL PUBLIC.nested_table_iteration();
SELECT * FROM DBMS_OUTPUT.DBMS_OUTPUT_LOG;
Copy
UDF
CREATE OR REPLACE FUNCTION PUBLIC.INSERT_REPLACE_COLLECTION_ELEMENT_UDF(varray ARRAY, position INTEGER, newValue VARIANT)
RETURNS ARRAY
LANGUAGE SQL
AS
$$
    ARRAY_CAT(
        ARRAY_APPEND(ARRAY_SLICE(varray, 0, (position)-1), newValue),
        ARRAY_SLICE(varray, position, ARRAY_SIZE(varray)))
$$;
Copy
Résultat

DBMS OUTPUT

10

20

30

40

20

30

Problèmes connus

1. They are currently not being converted

SnowConvert AI ne prend pas en charge la traduction de ces éléments.

2. Indexing needs to be modified

Les index d’Oracle commencent à 1, sur Snowflake ils commenceront à 0.

EWIs connexes

Pas d’EWIs connexes.

Définition du type d’enregistrement

Il s’agit d’une référence de traduction pour convertir la déclaration de l’enregistrement Oracle vers Snowflake

Avertissement

Les informations de cette section, en cours de modification, sont sujettes à modification.

Note

Certaines parties du code de sortie sont omises pour des raisons de clarté.

Description

Une variable d’enregistrement est une variable composite dont les composants internes, appelés champs, peuvent avoir différents types de données. La valeur d’une variable d’enregistrement et les valeurs de ses champs peuvent changer.

Vous faites référence à une variable d’enregistrement entière par son nom. Vous faites référence à un champ de l’enregistrement avec la syntaxe suivante : record.field.

Vous pouvez créer une variable d’enregistrement de l’une ou l’autre de ces manières :

  • Définissez un type d’enregistrement, puis déclarez une variable de ce type.

  • Utilisez %ROWTYPE pour déclarer une variable d’enregistrement qui représente une ligne complète ou partielle d’une table de base de données ou d’une vue.

  • Utilisez %TYPE pour déclarer une variable d’enregistrement du même type qu’une variable d’enregistrement déclarée précédemment.

(Référence linguistique Oracle PL/SQL RECORD VARIABLES)

Pour la traduction, la définition du type est remplacée par un OBJECT Type de données semi-structurées et son utilisation est modifiée en conséquence pour toutes les opérations.

Pour définir un type d’enregistrement, la syntaxe est la suivante :

type_definition := TYPE IS RECORD ( field_definition [, field_definition...] );

field_definition := field_name datatype [ { [NOT NULL default ] | default } ]

default := [ { := | DEFAULT } expression]

Copy

Pour déclarer une variable de ce type :

variable_name { record_type
              | rowtype_attribute
              | record_variable%TYPE
              };

Copy

Modèles d’échantillons de sources

Note

Certaines parties du code de sortie sont omises pour des raisons de clarté.

Initialisation et affectation des enregistrements

Cet échantillon tente d’insérer deux nouvelles lignes à l’aide d’une variable d’enregistrement qui est réaffectée à mi-procédure.

Oracle
CREATE TABLE record_table(col1 FLOAT, col2 INTEGER);

CREATE OR REPLACE PROCEDURE record_procedure
IS
    TYPE record_typ IS RECORD(col1 INTEGER, col2 FLOAT);
    record_variable record_typ := record_typ(1, 1.5);--initialization
BEGIN
    INSERT INTO record_table(col1, col2)
        VALUES (record_variable.col2, record_variable.col1);--usage
        
    --reassignment of properties
    record_variable.col1 := 2;
    record_variable.col2 := 2.5;
    
    INSERT INTO record_table(col1, col2)
        VALUES (record_variable.col2, record_variable.col1);--usage
END;

CALL record_procedure();
SELECT * FROM record_table;
Copy
Résultat

COL1

COL2

1,5

1

2.5

2

Snowflake

Remarquez que les réaffectations sont remplacées par une clause OBJECT_INSERT qui se met à jour si la colonne existe déjà, et que la clause VALUES est remplacée par une clause SELECT.

CREATE OR REPLACE TABLE record_table (col1 FLOAT,
    col2 INTEGER)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE PROCEDURE record_procedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        !!!RESOLVE EWI!!! /*** SSC-EWI-0056 - CUSTOM TYPES ARE NOT SUPPORTED IN SNOWFLAKE BUT REFERENCES TO THIS CUSTOM TYPE WERE CHANGED TO OBJECT ***/!!!
        TYPE record_typ IS RECORD(col1 INTEGER, col2 FLOAT);
        record_variable OBJECT !!!RESOLVE EWI!!! /*** SSC-EWI-0036 - record_typ DATA TYPE CONVERTED TO OBJECT ***/!!! := OBJECT_CONSTRUCT('COL1', 1, 'COL2', 1.5);--initialization

    BEGIN
        INSERT INTO record_table(col1, col2)
        SELECT
            :record_variable:COL2,
            :record_variable:COL1;--usage

        --reassignment of properties
        record_variable := OBJECT_INSERT(record_variable, 'COL1', 2, true);
        record_variable := OBJECT_INSERT(record_variable, 'COL2', 2.5, true);

        INSERT INTO record_table(col1, col2)
        SELECT
            :record_variable:COL2,
            :record_variable:COL1;--usage

    END;
$$;

CALL record_procedure();

SELECT * FROM
    record_table;
Copy
Résultat

COL1

COL2

1,5

1

2.5

2

Enregistrement %ROWTYPE et enregistrement des valeurs

Comme ce sont les opérations qui définissent la structure, ces définitions peuvent être remplacées par un type de données OBJECT, mais les valeurs de l’enregistrement doivent être décomposées, car l’insertion de l’enregistrement « tel quel » n’est pas prise en charge.

Oracle
CREATE TABLE record_table(col1 INTEGER, col2 VARCHAR2(50), col3 DATE);
CREATE OR REPLACE PROCEDURE insert_record
IS
    record_variable record_table%ROWTYPE;
BEGIN
    record_variable.col1 := 1;
    record_variable.col2 := 'Hello';
    record_variable.col3 := DATE '2020-12-25';
    
    INSERT INTO record_table VALUES record_variable;
END;

CALL insert_record();
SELECT * FROM record_table;
Copy
Résultat

COL1

COL2

COL3

1

« Hello »

25-DEC-20

Snowflake

Notez enfin que la variable OBJECT doit être initialisée pour que les informations puissent y être ajoutées.

CREATE OR REPLACE TABLE record_table (col1 INTEGER,
    col2 VARCHAR(50),
    col3 TIMESTAMP /*** SSC-FDM-OR0042 - DATE TYPE COLUMN HAS A DIFFERENT BEHAVIOR IN SNOWFLAKE. ***/
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE PROCEDURE insert_record ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        record_variable OBJECT !!!RESOLVE EWI!!! /*** SSC-EWI-0036 - ROWTYPE DATA TYPE CONVERTED TO OBJECT ***/!!! := OBJECT_CONSTRUCT();
    BEGIN
        record_variable := OBJECT_INSERT(record_variable, 'COL1', 1, true);
        record_variable := OBJECT_INSERT(record_variable, 'COL2', 'Hello', true);
        record_variable := OBJECT_INSERT(record_variable, 'COL3', DATE '2020-12-25', true);
        INSERT INTO record_table
        SELECT
            :record_variable:COL1,
            :record_variable:COL2,
            :record_variable:COL3;
    END;
$$;

CALL insert_record();

SELECT * FROM
    record_table;
Copy
Résultat

COL1

COL2

COL3

1

« Hello »

25-DEC-20

Récupération des données dans un enregistrement

Oracle
CREATE TABLE record_table(col1 INTEGER, col2 VARCHAR2(50), col3 DATE);
INSERT INTO record_table(col1, col2 , col3)
    VALUES (1, 'Hello', DATE '2020-12-25');

CREATE OR REPLACE PROCEDURE load_cursor_record
IS
    CURSOR record_cursor IS
        SELECT *
        FROM record_table;
        
    record_variable record_cursor%ROWTYPE;
BEGIN
    OPEN record_cursor;
    LOOP
        FETCH record_cursor INTO record_variable;
        EXIT WHEN record_cursor%NOTFOUND;
        
        DBMS_OUTPUT.PUT_LINE(record_variable.col1);
        DBMS_OUTPUT.PUT_LINE(record_variable.col2);
        DBMS_OUTPUT.PUT_LINE(record_variable.col3);
    END LOOP;
    CLOSE record_cursor;
END;

CALL load_cursor_record();
Copy
Résultat

DBMS OUTPUT

1

Bonjour

25-DEC-20

Snowflake

Veuillez noter l’ajout de OBJECT_CONSTRUCT dans la définition du curseur, qui permet d’extraire une instruction OBJECT, qui peut ensuite être utilisée pour migrer de manière transparente l’instruction FETCH.

CREATE OR REPLACE TABLE record_table (col1 INTEGER,
    col2 VARCHAR(50),
    col3 TIMESTAMP /*** SSC-FDM-OR0042 - DATE TYPE COLUMN HAS A DIFFERENT BEHAVIOR IN SNOWFLAKE. ***/
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
;

INSERT INTO record_table(col1, col2 , col3)
    VALUES (1, 'Hello', DATE '2020-12-25');

CREATE OR REPLACE PROCEDURE load_cursor_record ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        --** SSC-PRF-0009 - PERFORMANCE REVIEW - CURSOR USAGE **
        record_cursor CURSOR
        FOR
            SELECT
                OBJECT_CONSTRUCT( *) sc_cursor_record
            FROM
                record_table;
    record_variable OBJECT !!!RESOLVE EWI!!! /*** SSC-EWI-0036 - ROWTYPE DATA TYPE CONVERTED TO OBJECT ***/!!! := OBJECT_CONSTRUCT();
    BEGIN
        OPEN record_cursor;
        --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
    LOOP
            --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        FETCH record_cursor INTO
                :record_variable;
        IF (record_variable IS NULL) THEN
                EXIT;
        END IF;
        --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
        CALL DBMS_OUTPUT.PUT_LINE_UDF(:record_variable:COL1);
        --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
        CALL DBMS_OUTPUT.PUT_LINE_UDF(:record_variable:COL2);
        --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
        CALL DBMS_OUTPUT.PUT_LINE_UDF(:record_variable:COL3::DATE);
    END LOOP;
    CLOSE record_cursor;
    END;
$$;

CALL load_cursor_record();
Copy
Résultat

DBMS OUTPUT

1

Bonjour

25-DEC-20

Attribution d’une variable d’enregistrement dans un SELECT INTO

Cette transformation consiste à profiter de la fonction OBJECT_CONTRUCT pour initialiser l’enregistrement en utilisant les colonnes SELECT comme arguments.

Échantillon de code auxiliaire

Oracle
create table sample_table(ID number, NAME varchar2(23));
CREATE TABLE RESULTS (COL1 VARCHAR(20), COL2 VARCHAR(40));
insert into sample_table values(1, 'NAME 1');
insert into sample_table values(2, 'NAME 2');
insert into sample_table values(3, 'NAME 3');
insert into sample_table values(4, 'NAME 4');
Copy
Snowflake
CREATE OR REPLACE TABLE sample_table (ID NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
NAME VARCHAR(23))
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE TABLE RESULTS (COL1 VARCHAR(20),
COL2 VARCHAR(40))
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

insert into sample_table
values(1, 'NAME 1');

insert into sample_table
values(2, 'NAME 2');

insert into sample_table
values(3, 'NAME 3');

insert into sample_table
values(4, 'NAME 4');
Copy
Oracle
CREATE OR REPLACE PROCEDURE sp_sample1 AS
-- Rowtype variable
rowtype_variable sample_table%rowtype;

--Record variable
TYPE record_typ_def IS RECORD(ID number, NAME varchar2(23));
record_variable_def record_typ_def;

-- Auxiliary variable
name_var VARCHAR(20);
BEGIN
   SELECT * INTO rowtype_variable FROM sample_table WHERE ID = 1 FETCH NEXT 1 ROWS ONLY;
   name_var := rowtype_variable.NAME;
   INSERT INTO RESULTS(COL1, COL2) VALUES('SELECT 1', name_var);
  
   SELECT ID, NAME INTO rowtype_variable FROM sample_table WHERE ID = 2 FETCH NEXT 1 ROWS ONLY;
   name_var := rowtype_variable.NAME;
   INSERT INTO RESULTS(COL1, COL2) VALUES('SELECT 2', name_var);
  
   SELECT * INTO record_variable_def FROM sample_table WHERE ID = 3 FETCH NEXT 1 ROWS ONLY;
   name_var := record_variable_def.NAME;
   INSERT INTO RESULTS(COL1, COL2) VALUES('SELECT 3', name_var);
  
   SELECT ID, NAME INTO record_variable_def FROM sample_table WHERE ID = 4 FETCH NEXT 1 ROWS ONLY;
   name_var := record_variable_def.NAME;
   INSERT INTO RESULTS(COL1, COL2) VALUES('SELECT 4', name_var);
END;


call sp_sample1();

SELECT * FROM results;
Copy
Résultat

COL1

COL2

SELECT 1

NAME 1

SELECT 2

NAME 2

SELECT 3

NAME 3

SELECT 4

NAME 4

Snowflake
CREATE OR REPLACE PROCEDURE sp_sample1 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
   DECLARE
      -- Rowtype variable
      rowtype_variable OBJECT !!!RESOLVE EWI!!! /*** SSC-EWI-0036 - ROWTYPE DATA TYPE CONVERTED TO OBJECT ***/!!! := OBJECT_CONSTRUCT();

      --Record variable
      !!!RESOLVE EWI!!! /*** SSC-EWI-0056 - CUSTOM TYPES ARE NOT SUPPORTED IN SNOWFLAKE BUT REFERENCES TO THIS CUSTOM TYPE WERE CHANGED TO OBJECT ***/!!!
      TYPE record_typ_def IS RECORD(ID number, NAME varchar2(23));
      record_variable_def OBJECT !!!RESOLVE EWI!!! /*** SSC-EWI-0036 - record_typ_def DATA TYPE CONVERTED TO OBJECT ***/!!! := OBJECT_CONSTRUCT();

      -- Auxiliary variable
      name_var VARCHAR(20);
   BEGIN
      SELECT
         OBJECT_CONSTRUCT( *) INTO
         :rowtype_variable
      FROM
         sample_table
      WHERE ID = 1
      FETCH NEXT 1 ROWS ONLY;
      name_var := :rowtype_variable:NAME;
      INSERT INTO RESULTS(COL1, COL2) VALUES('SELECT 1', :name_var);

      SELECT
         OBJECT_CONSTRUCT()
      INTO
         :rowtype_variable
      FROM
         sample_table
      WHERE ID = 2
      FETCH NEXT 1 ROWS ONLY;
      name_var := :rowtype_variable:NAME;
      INSERT INTO RESULTS(COL1, COL2) VALUES('SELECT 2', :name_var);

      SELECT
         OBJECT_CONSTRUCT( *) INTO
         :record_variable_def
      FROM
         sample_table
      WHERE ID = 3
      FETCH NEXT 1 ROWS ONLY;
      name_var := :record_variable_def:NAME;
      INSERT INTO RESULTS(COL1, COL2) VALUES('SELECT 3', :name_var);

      SELECT
         OBJECT_CONSTRUCT('ID', ID, 'NAME', NAME) INTO
         :record_variable_def
      FROM
         sample_table
      WHERE ID = 4
      FETCH NEXT 1 ROWS ONLY;
      name_var := :record_variable_def:NAME;
      INSERT INTO RESULTS(COL1, COL2) VALUES('SELECT 4', :name_var);
   END;
$$;

call sp_sample1();

SELECT * FROM
   results;
Copy
Résultat

COL1

COL2

SELECT 1

NAME 1

SELECT 2

NAME 2

SELECT 3

NAME 3

SELECT 4

NAME 4

Problèmes connus

1. The following functionalities are currently not being converted:

  • Récupération de données dans un enregistrement.

  • Enregistrements imbriqués (enregistrements à l’intérieur d’enregistrements).

  • Collections à l’intérieur des enregistrements.

EWIs connexes

  1. SSC-EWI-0036 : Type de données converti en un autre type de données.

  2. SSC-EWI-0056: Le type de création ’Create Type’ n’est pas pris en charge

  3. SSC-FDM-0006: La colonne de type nombre peut ne pas se comporter de la même manière dans Snowflake.

  4. SSC-FDM-OR0042: Le type de date transformé en horodatage a un comportement différent.

  5. SSC-FDM-OR0035: DBMS_OUTPUT.PUTLINE consultez l’implémentation UDF.

  6. SSC-PRF-0003: Fetch à l’intérieur d’une boucle est considéré comme un modèle complexe, cela pourrait dégrader les performances de Snowflake.

Définition du type varray

Il s’agit d’une référence de traduction pour convertir la déclaration Oracle Varray vers Snowflake

Avertissement

Les informations de cette section, en cours de modification, sont sujettes à modification.

Note

Cette section concerne la version PL/SQL des Varrays, pour la version autonome, voir Définition de type Array (tableau).

Note

Certaines parties du code de sortie sont omises pour des raisons de clarté.

Description

Un varray (tableau à taille variable) est un tableau dont le nombre d’éléments peut varier de zéro (vide) à la taille maximale déclarée.

Pour accéder à un élément d’une variable varray, utilisez la syntaxe suivante : variable_name(index). La borne inférieure de l”index est 1 ; la borne supérieure est le nombre actuel d’éléments. La borne supérieure change à mesure que vous ajoutez ou supprimez des éléments, mais elle ne peut pas dépasser la taille maximale. Lorsque vous stockez et récupérez un varray dans la base de données, ses index et l’ordre des éléments restent stables.

(Référence linguistique Oracle PL/SQL VARRAYS)

Pour la traduction, la définition du type est remplacée par un ARRAY type de données semi-structurées et son utilisation est modifiée en conséquence pour toutes les opérations. Veuillez noter que la traduction pour les tables imbriquées et les varrays est la même.

Pour définir un type de tableau, la syntaxe est la suivante :

type_definition := { VARRAY | [VARYING] ARRAY } (size_limit) OF datatype
            [NOT NULL];

Copy

Pour déclarer une variable de ce type :

variable_name collection_type;

Copy

Modèles d’échantillons de sources

Définitions de varray

Ceci illustre les trois différentes façons de créer un varray, et la manière de migrer ces définitions pour les variables.

Oracle
CREATE OR REPLACE PROCEDURE associative_array_procedure
IS
    TYPE varray_typ IS ARRAY(10) OF INTEGER;
    TYPE varray_typ2 IS VARRAY(10) OF INTEGER;
    TYPE varray_typ3 IS VARYING ARRAY(10) OF INTEGER;

    array_variable varray_typ;
    array_variable2 varray_typ2;
    array_variable3 varray_typ3;
BEGIN
    NULL;
END;
Copy
Snowflake
CREATE OR REPLACE PROCEDURE associative_array_procedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
--        !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'PL COLLECTION TYPE DEFINITION' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
--        TYPE varray_typ IS ARRAY(10) OF INTEGER;
--        !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'PL COLLECTION TYPE DEFINITION' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
--        TYPE varray_typ2 IS VARRAY(10) OF INTEGER;
--        !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'PL COLLECTION TYPE DEFINITION' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
--        TYPE varray_typ3 IS VARYING ARRAY(10) OF INTEGER;

        array_variable VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-0062 - CUSTOM TYPE 'varray_typ' USAGE CHANGED TO VARIANT ***/!!!;
        array_variable2 VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-0062 - CUSTOM TYPE 'varray_typ2' USAGE CHANGED TO VARIANT ***/!!!;
        array_variable3 VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-0062 - CUSTOM TYPE 'varray_typ3' USAGE CHANGED TO VARIANT ***/!!!;
    BEGIN
        NULL;
    END;
$$;
Copy

Itération de varray

Oracle
CREATE OR REPLACE PROCEDURE varray_iteration
IS
    TYPE varray_typ IS VARRAY(3) OF INTEGER;
    varray_variable varray_typ := varray_typ(10, 20, 30);
BEGIN
    FOR i IN 1..varray_variable.COUNT
    LOOP
        DBMS_OUTPUT.PUT_LINE(varray_variable(i));
    END LOOP;
    
    varray_variable(1) := 40;
    
    FOR i IN 1..varray_variable.COUNT
    LOOP
        DBMS_OUTPUT.PUT_LINE(varray_variable(i));
    END LOOP;
END;
/

CALL varray_iteration();
Copy
Résultat

DBMS OUTPUT

10

20

30

40

20

30

Snowflake

Note

Notez qu’une UDF a été ajoutée pour mettre en œuvre la fonctionnalité de mise à jour de l’élément.

Cette UDF sera ajoutée dans les révisions ultérieures.

CREATE OR REPLACE PROCEDURE varray_iteration ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
--        !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'PL COLLECTION TYPE DEFINITION' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
--        TYPE varray_typ IS VARRAY(3) OF INTEGER;
        varray_variable VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-0062 - CUSTOM TYPE 'varray_typ' USAGE CHANGED TO VARIANT ***/!!! := varray_typ(10, 20, 30);
    BEGIN
        --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
        FOR i IN 1 TO 0 /*varray_variable.COUNT*/!!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'VARRAY CUSTOM TYPE EXPRESSION' NODE ***/!!!
        --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
        LOOP
            --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
            CALL DBMS_OUTPUT.PUT_LINE_UDF(varray_variable(i));
        END LOOP;
            !!!RESOLVE EWI!!! /*** SSC-EWI-OR0108 - THE FOLLOWING ASSIGNMENT STATEMENT IS NOT SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
            varray_variable(1) := 40;
            --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
            FOR i IN 1 TO 0 /*varray_variable.COUNT*/!!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'VARRAY CUSTOM TYPE EXPRESSION' NODE ***/!!!
            --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
               LOOP
            --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
            CALL DBMS_OUTPUT.PUT_LINE_UDF(varray_variable(i));
               END LOOP;
    END;
$$;

CALL varray_iteration();
Copy
UDF
CREATE OR REPLACE FUNCTION PUBLIC.INSERT_REPLACE_COLLECTION_ELEMENT_UDF(varray ARRAY, position INTEGER, newValue VARIANT)
RETURNS ARRAY
LANGUAGE SQL
AS
$$
    ARRAY_CAT(
        ARRAY_APPEND(ARRAY_SLICE(varray, 0, (position)-1), newValue),
        ARRAY_SLICE(varray, position, ARRAY_SIZE(varray)))
$$;
Copy
Résultat

DBMS OUTPUT

10

20

30

40

20

30

Problèmes connus

1. They are currently not being converted

SnowConvert AI ne prend pas en charge la traduction de ces éléments.

2. Indexing needs to be modified

Les index d’Oracle commencent à 1, sur Snowflake ils commenceront à 0.

3. Array Density may not match the original

Le type de données ARRAY pouvant devenir clairsemé, il convient d’être prudent lors de l’ajout ou de la suppression du tableau. L’utilisation de ARRAY_COMPACT() après de telles opérations peut être utile si la densité est un sujet de préoccupation.

EWIs connexes

  1. SSC-EWI-0058: La fonctionnalité n’est pas prise en charge actuellement par Snowflake Scripting.

  2. SSC-EWI-0062: L’utilisation du type personnalisé a changé en variante.

  3. SSC-EWI-0073 : En attente de l’examen de l’équivalence fonctionnelle.

  4. SSC-EWI-OR0108: L’instruction d’affectation suivante n’est pas prise en charge par Snowflake Scripting.

  5. SSC-FDM-OR0035: DBMS_OUTPUT.PUTLINE consultez l’implémentation UDF.

Opérations de collection en masse

Il s’agit d’une référence de traduction pour convertir les opérations de collection en masse Oracle vers Snowflake

Avertissement

Les informations de cette section, en cours de modification, sont sujettes à modification.

Note

Certaines parties du code de sortie sont omises pour des raisons de clarté.

Description

La clause BULK COLLECT, une fonction de SQL en masse, renvoie les résultats de SQL à PL/SQL par lots plutôt qu’un par un.

La clause BULK COLLECT peut figurer dans :

  • Instruction SELECT INTO

  • Instruction FETCH

  • Clause de RETURNING INTO :

    • Instruction DELETE

    • Instruction INSERT

    • Instruction UPDATE

    • Instruction EXECUTE IMMEDIATE

Avec la clause BULK COLLECT, chacune des instructions précédentes récupère un jeu de résultats complet et le stocke dans une ou plusieurs variables de collection en une seule opération (ce qui est plus efficace que d’utiliser une instruction de boucle pour récupérer une ligne de résultats à la fois).

(Référence linguistique Oracle PL/SQL BULK COLLECT CLAUSE)

Cette section propose des solutions de contournement pour les SELECTs et le curseur FETCH avec clauses Bulk.

Modèles d’échantillons de sources

Table source

Oracle
CREATE TABLE bulk_collect_table(col1 INTEGER);

INSERT INTO bulk_collect_table VALUES(1);
INSERT INTO bulk_collect_table VALUES(2);
INSERT INTO bulk_collect_table VALUES(3);
INSERT INTO bulk_collect_table VALUES(4);
INSERT INTO bulk_collect_table VALUES(5);
INSERT INTO bulk_collect_table VALUES(6);
Copy
Snowflake
CREATE OR REPLACE TABLE bulk_collect_table (col1 INTEGER)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

INSERT INTO bulk_collect_table
VALUES(1);

INSERT INTO bulk_collect_table
VALUES(2);

INSERT INTO bulk_collect_table
VALUES(3);

INSERT INTO bulk_collect_table
VALUES(4);

INSERT INTO bulk_collect_table
VALUES(5);

INSERT INTO bulk_collect_table
VALUES(6);
Copy

Bulk Collect à partir d’une table

Oracle
CREATE OR REPLACE PROCEDURE bulk_collect_procedure
IS
    CURSOR record_cursor IS
        SELECT *
        FROM bulk_collect_table;
        
    TYPE fetch_collection_typ IS TABLE OF record_cursor%ROWTYPE;
    fetch_collection_variable fetch_collection_typ;
    
    TYPE collection_typ IS TABLE OF bulk_collect_table%ROWTYPE;
    collection_variable collection_typ;
BEGIN
    SELECT * BULK COLLECT INTO collection_variable FROM bulk_collect_table;
    
    FOR i IN 1..collection_variable.COUNT
    LOOP
        DBMS_OUTPUT.PUT_LINE(collection_variable(i).col1);
    END LOOP;
    
    collection_variable := null;
    OPEN record_cursor;
    FETCH record_cursor BULK COLLECT INTO collection_variable;
    CLOSE record_cursor;
    
    FOR i IN 1..collection_variable.COUNT
    LOOP
        DBMS_OUTPUT.PUT_LINE(collection_variable(i).col1+6);
    END LOOP;
    
    collection_variable := null;
    EXECUTE IMMEDIATE 'SELECT * FROM bulk_collect_table' BULK COLLECT INTO collection_variable;
    
    FOR i IN 1..collection_variable.COUNT
    LOOP
        DBMS_OUTPUT.PUT_LINE(collection_variable(i).col1+12);
    END LOOP;
END;
/

CALL bulk_collect_procedure();
Copy
Résultat

DBMS OUTPUT

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

Snowflake

Danger

EXECUTE IMMEDIATE avec la clause Bulk Collect n’a pas de solution de contournement proposée.

Note

Veuillez noter que, bien que le curseur FETCH puisse être conservé dans une large mesure, il est conseillé de le remplacer par des instructions SELECT dans la mesure du possible pour des raisons de performance.

CREATE OR REPLACE PROCEDURE bulk_collect_procedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        --** SSC-PRF-0009 - PERFORMANCE REVIEW - CURSOR USAGE **
        record_cursor CURSOR
        FOR
            SELECT *
            FROM
                bulk_collect_table;
--                !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'PL COLLECTION TYPE DEFINITION' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
--                TYPE fetch_collection_typ IS TABLE OF record_cursor%ROWTYPE;
    fetch_collection_variable VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-0062 - CUSTOM TYPE 'fetch_collection_typ' USAGE CHANGED TO VARIANT ***/!!!;
--                !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'PL COLLECTION TYPE DEFINITION' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!

--    TYPE collection_typ IS TABLE OF bulk_collect_table%ROWTYPE;
    collection_variable VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-0062 - CUSTOM TYPE 'collection_typ' USAGE CHANGED TO VARIANT ***/!!!;
    BEGIN
                !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'RECORDS AND COLLECTIONS' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
                SELECT * BULK COLLECT INTO collection_variable FROM bulk_collect_table;
                --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
                FOR i IN 1 TO 0 /*collection_variable.COUNT*/!!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'NESTED TABLE CUSTOM TYPE EXPRESSION' NODE ***/!!!
                --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
                   LOOP
            --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
            CALL DBMS_OUTPUT.PUT_LINE_UDF(:collection_variable(i).col1);
                   END LOOP;
                !!!RESOLVE EWI!!! /*** SSC-EWI-OR0108 - THE FOLLOWING ASSIGNMENT STATEMENT IS NOT SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!

                collection_variable := null;
                OPEN record_cursor;
                --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
                record_cursor := (
            CALL FETCH_BULK_COLLECTION_RECORDS_UDF(:record_cursor)
                );
                collection_variable := :record_cursor:RESULT;
                CLOSE record_cursor;
                --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
                FOR i IN 1 TO 0 /*collection_variable.COUNT*/!!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'NESTED TABLE CUSTOM TYPE EXPRESSION' NODE ***/!!!
                --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
                   LOOP
            --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
            CALL DBMS_OUTPUT.PUT_LINE_UDF(
            !!!RESOLVE EWI!!! /*** SSC-EWI-OR0036 - TYPES RESOLUTION ISSUES, ARITHMETIC OPERATION '+' MAY NOT BEHAVE CORRECTLY BETWEEN unknown AND Number ***/!!!
            :collection_variable(i).col1+6);
                   END LOOP;
                !!!RESOLVE EWI!!! /*** SSC-EWI-OR0108 - THE FOLLOWING ASSIGNMENT STATEMENT IS NOT SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!

                collection_variable := null;
                !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
                EXECUTE IMMEDIATE 'SELECT * FROM
   bulk_collect_table'
                      !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'EXECUTE IMMEDIATE RETURNING CLAUSE' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
                      BULK COLLECT INTO collection_variable;
                --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
                FOR i IN 1 TO 0 /*collection_variable.COUNT*/!!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'NESTED TABLE CUSTOM TYPE EXPRESSION' NODE ***/!!!
                --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
                   LOOP
            --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
            CALL DBMS_OUTPUT.PUT_LINE_UDF(
            !!!RESOLVE EWI!!! /*** SSC-EWI-OR0036 - TYPES RESOLUTION ISSUES, ARITHMETIC OPERATION '+' MAY NOT BEHAVE CORRECTLY BETWEEN unknown AND Number ***/!!!
            :collection_variable(i).col1+12);
                   END LOOP;
    END;
$$;

CALL bulk_collect_procedure();
Copy
Résultat

DBMS OUTPUT

1

2

3

4

5

6

7

8

9

10

11

– EXECUTE IMMEDIATE NOT EXECUTED n’est pas pris en charge

Cas d’instruction SELECT INTO

Dans ce cas, la spécification de traduction utilise des RESULTSETs. Consultez la documentation relative aux instructions WITH, SELECT et BULK COLLECT INTO ici :

with-select-and-bulk-collect-into-statements.md

Problèmes connus

1. Heavy performance issues on FETCH Cursor workaround

La solution de contournement pour le curseur Fetch a des exigences élevées en matière de performance en raison de la table temporaire. Il est conseillé de les migrer manuellement vers les instructions SELECT

2. Execute immediate statements are not transformed

Elles ne sont pas prises en charge par SnowConvert AI mais peut être manuellement remplacé par des instructions SELECT.

EWIs connexes

  1. SSC-EWI-0058: La fonctionnalité n’est pas prise en charge actuellement par Snowflake Scripting.

  2. SSC-EWI-0062: L’utilisation du type personnalisé a changé en variante.

  3. SSC-EWI-0073 : En attente de l’examen de l’équivalence fonctionnelle

  4. SSC-EWI-OR0036: Problèmes de résolution des types, l’opération arithmétique peut ne pas se comporter correctement entre la chaîne et la date.

  5. SSC-EWI-OR0108: L’instruction d’affectation suivante n’est pas prise en charge par Snowflake Scripting.

  6. SSC-FDM-OR0035: DBMS_OUTPUT.PUTLINE consultez l’implémentation UDF.

  7. SSC-PRF-0001: Cette instruction a des utilisations des opérations en masse de curseur Fetch.

  8. SSC-EWI-0030: L’instruction ci-dessous a des utilisations de Dynamic SQL

Instructions WITH, SELECT et BULKCOLLECTINTO

Danger

Cette section est une spécification de traduction. Les informations sont susceptibles d’être modifiées à l’avenir.

Note

Certaines parties du code de sortie sont omises pour des raisons de clarté.

Description

Cette section est une spécification de traduction de l’instruction WITH faisant suite à une instruction SELECT qui utilise une instruction BULK COLLECT INTO. Pour plus d’informations, consultez la documentation suivante :

Modèles d’échantillons de sources

Note

Certaines parties du code de sortie sont omises pour des raisons de clarté.

La requête suivante est utilisée pour les exemples suivants.

Oracle

-- Sample MySampleTable table
CREATE TABLE MySampleTable (
  MySampleID NUMBER PRIMARY KEY,
  FirstName VARCHAR2(50),
  Salary NUMBER,
  Department VARCHAR2(50)
);

-- Insert some sample data
INSERT INTO MySampleTable (MySampleID, FirstName, Salary, Department)
VALUES (1, 'Bob One', 50000, 'HR');

INSERT INTO MySampleTable (MySampleID, FirstName, Salary, Department)
VALUES (2, 'Bob Two', 60000, 'HR');

INSERT INTO MySampleTable (MySampleID, FirstName, Salary, Department)
VALUES (3, 'Bob Three', 75000, 'IT');

INSERT INTO MySampleTable (MySampleID, FirstName, Salary, Department)
VALUES (4, 'Bob Four', 80000, 'IT');
Copy
Snowflake
-- Sample MySampleTable table
CREATE OR REPLACE TABLE MySampleTable (
   MySampleID NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/ PRIMARY KEY,
   FirstName VARCHAR(50),
   Salary NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
   Department VARCHAR(50)
 )
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

-- Insert some sample data
INSERT INTO MySampleTable(MySampleID, FirstName, Salary, Department)
VALUES (1, 'Bob One', 50000, 'HR');

INSERT INTO MySampleTable(MySampleID, FirstName, Salary, Department)
VALUES (2, 'Bob Two', 60000, 'HR');

INSERT INTO MySampleTable(MySampleID, FirstName, Salary, Department)
VALUES (3, 'Bob Three', 75000, 'IT');

INSERT INTO MySampleTable(MySampleID, FirstName, Salary, Department)
VALUES (4, 'Bob Four', 80000, 'IT');
Copy

1. Inside procedure simple case

Danger

Il s’agit d’une approche qui utilise un type de données resultset. Les types définis par l’utilisateur doivent être revus. Consultez la documentation suivante de Snowflake pour obtenir plus d’informations sur RESULTSETs.

L’exemple suivant utilise un type défini par l’utilisateur et le déclare indirectement comme une table. La traduction pour ce cas met en œuvre un RESULTSET comme type de données dans Snowflake. Le jeu de résultats est stocké dans une variable qui doit être renvoyée enveloppée dans une fonction TABLE().

Oracle
CREATE OR REPLACE PROCEDURE simple_procedure
IS
  TYPE salary_collection IS TABLE OF NUMBER;
  v_salaries salary_collection := salary_collection();

BEGIN
  WITH IT_Employees AS (
    SELECT Salary
    FROM MySampleTable
    WHERE Department = 'IT'
  )
  SELECT Salary BULK COLLECT INTO v_salaries
  FROM IT_Employees;
END;

CALL simple_procedure();
Copy
Résultat

Note

La requête ne renvoie pas de résultats, mais l’information recueillie attendue serait l’information salariale IT utilisée pour l’exemple :

IT_Salary

75000

80000

Danger

L’une des limites des RESULTSETs est qu’ils ne peuvent pas être utilisés comme des tables. Par exemple : select * from my_result_set; (Il s’agit d’une erreur, consultez la documentation suivante pour plus d’informations).

Snowflake
CREATE OR REPLACE PROCEDURE simple_procedure ()
RETURNS STRING
LANGUAGE JAVASCRIPT
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
  // SnowConvert AI Helpers Code section is omitted.

  !!!RESOLVE EWI!!! /*** SSC-EWI-OR0072 - PROCEDURAL MEMBER TYPE DEFINITION NOT SUPPORTED. ***/!!!
  /*   TYPE salary_collection IS TABLE OF NUMBER */
  ;
  !!!RESOLVE EWI!!! /*** SSC-EWI-OR0104 - UNUSABLE VARIABLE, ITS TYPE WAS NOT TRANSFORMED ***/!!!
  /*   v_salaries salary_collection := salary_collection() */
  ;
  EXEC(`SELECT Salary
    FROM
       MySampleTable
    WHERE Department = 'IT'`);
  [
    !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'PlBulkCollectionItem' NODE ***/!!!
    //v_salaries
    null,V_SALARIES] = EXEC(`SELECT
   Salary
 FROM IT_Employees`);
$$;

CALL simple_procedure();
Copy
Résultat

SALARY

77500

80000

2. Simple case for iterations: FOR LOOP statement

Le cas suivant consiste à définir une traduction pour l’itération avec FOR...LOOP. Dans ce cas, le type défini par l’utilisateur est implicitement une table, il est donc possible d’utiliser un curseur pour itérer. Consultez la documentation suivante pour en savoir plus :

Oracle
CREATE OR REPLACE PROCEDURE simple_procedure
IS
  TYPE salary_collection IS TABLE OF NUMBER;
  v_salaries salary_collection := salary_collection();
  v_average_salary NUMBER;
  salaries_count NUMBER;

BEGIN
  salaries_count := 0;
  WITH IT_Employees AS (
    SELECT Salary
    FROM MySampleTable
    WHERE Department = 'IT'
  )
  SELECT Salary BULK COLLECT INTO v_salaries
  FROM IT_Employees;

  -- Calculate the average salary
  IF v_salaries.COUNT > 0 THEN
    v_average_salary := 0;
    FOR i IN 1..v_salaries.COUNT LOOP
		v_average_salary := v_average_salary + v_salaries(i);
		salaries_count := salaries_count + 1;
    END LOOP;
    v_average_salary := v_average_salary / salaries_count;
  END IF;

  -- Display the average salary
  DBMS_OUTPUT.PUT_LINE('Average Salary for IT Department: ' || v_average_salary);
END;
/

CALL simple_procedure();
Copy
Résultat
Statement processed.
Average Salary for IT Department: 77500

Copy
Snowflake
CREATE OR REPLACE PROCEDURE simple_procedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
	DECLARE
--		!!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'PL COLLECTION TYPE DEFINITION' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
--		TYPE salary_collection IS TABLE OF NUMBER;
		v_salaries VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-0062 - CUSTOM TYPE 'salary_collection' USAGE CHANGED TO VARIANT ***/!!! := salary_collection();
		v_average_salary NUMBER(38, 18);
		salaries_count NUMBER(38, 18);
	BEGIN
		salaries_count := 0;
		WITH IT_Employees AS
		(
		  SELECT Salary
		  FROM
		  	MySampleTable
		  WHERE Department = 'IT'
		)
		!!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'RECORDS AND COLLECTIONS' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
		SELECT Salary BULK COLLECT INTO v_salaries
		FROM IT_Employees;
		-- Calculate the average salary
		IF (null /*v_salaries.COUNT*/!!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'NESTED TABLE CUSTOM TYPE EXPRESSION' NODE ***/!!! > 0) THEN
		  v_average_salary := 0;
		  --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
		  FOR i IN 1 TO 0 /*v_salaries.COUNT*/!!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'NESTED TABLE CUSTOM TYPE EXPRESSION' NODE ***/!!!
 		                                                                                                                                                                        --** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
 		                                                                                                                                                                        LOOP
		  	v_average_salary :=
		  	!!!RESOLVE EWI!!! /*** SSC-EWI-OR0036 - TYPES RESOLUTION ISSUES, ARITHMETIC OPERATION '+' MAY NOT BEHAVE CORRECTLY BETWEEN NUMBER AND salary_collection ***/!!!
		  	:v_average_salary + v_salaries(i);
		  	salaries_count := :salaries_count + 1;
 		                                                                                                                                                                           END LOOP;
		  v_average_salary := :v_average_salary / :salaries_count;
		END IF;
		-- Display the average salary
		--** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
		CALL DBMS_OUTPUT.PUT_LINE_UDF('Average Salary for IT Department: ' || NVL(:v_average_salary :: STRING, ''));
	END;
$$;

CALL simple_procedure();
Copy
Résultat

SIMPLE_PROCEDURE

Salaire moyen pour le département IT : 77500

Problèmes connus

1. Resulset limitations.

L’utilisation du type de données RESULTSET comporte des limites. Consultez la documentation Snowflake pour en savoir plus. Les limites à ne pas dépasser sont les suivantes :

  • Déclarer une colonne de type RESULTSET.

  • Déclarer un paramètre de type RESULTSET.

  • Déclaration du type de retour d’une procédure stockée en tant que RESULTSET.

2. Execute statements with Bulk Collect clause are not supported.

Consultez la documentation suivante.

EWIs connexes

  1. SSC-EWI-0058: La fonctionnalité n’est pas prise en charge actuellement par Snowflake Scripting.

  2. SSC-EWI-0062: L’utilisation du type personnalisé a changé en variante.

  3. SSC-EWI-0073 : En attente de l’examen de l’équivalence fonctionnelle

  4. SSC-EWI-OR0036: Problèmes de résolution des types, l’opération arithmétique peut ne pas se comporter correctement entre la chaîne et la date.

  5. SSC-EWI-OR0072: Membre procédural non pris en charge

  6. SSC-EWI-OR0104: Variable de collection inutilisable.

  7. SSC-FDM-0006: La colonne de type nombre peut ne pas se comporter de la même manière dans Snowflake.

  8. SSC-FDM-OR0035: DBMS_OUTPUT.PUTLINE consultez l’implémentation UDF.