SnowConvert AI – Oracle – COLLECTIONS AND RECORDS¶
Übersetzungsreferenz zur Konvertierung von COLLECTIONS und RECORDS von Oracle in Snowflake Scripting
Warnung
Dieser Abschnitt ist noch in Arbeit, die Informationen können sich in Zukunft noch ändern.
Allgemeine Beschreibung¶
Mit PL/SQL können Sie zwei Arten von zusammengesetzten Datentypen definieren: Sammlung und Datensatz, wobei „zusammengesetzt“ ein Datentyp ist, der Werte speichert, die interne Komponenten haben.
In einer Sammlung haben die internen Komponenten immer denselben Datentyp und werden als Elemente bezeichnet.
In einem Datensatz können die internen Komponenten unterschiedliche Datentypen haben und werden als Felder bezeichnet. (Oracle PL/SQL Language Reference COLLECTIONS AND RECORDS)
Bemerkung
Berücksichtigen Sie die Übersetzungsreferenz für die CREATE TYPE-Anweisung, da sich einige Problemumgehungen überschneiden können und in beiden Szenarien anwendbar sind.
Einschränkungen¶
Snowflake unterstützt laut seiner Online-Dokumentation Nicht unterstützte Datentypen keine benutzerdefinierten Datentypen, zu denen PL-Sammlungen und -Datensätze gehören. Es werden jedoch semistrukturierte Datentypen unterstützt, mit denen sowohl die hierarchieähnliche Struktur von Datensätzen als auch die Elementstruktur von benutzerdefinierten Typen für Sammlungen nachgebildet werden kann. Aus diesem Grund gibt es mehrere Arten von Features, für die es keine Umgehungsmöglichkeit gibt.
Im Folgenden sind die Features aufgeführt, für die NO eine Umgehungsmöglichkeit vorschlägt:
Die Größe der Variablen darf nicht größer sein als 16MB¶
Snowflake setzt VARIANT, OBJECT und die maximale Größe von ARRAY auf 16MBs. Das heißt, wenn ein Datensatz, eine Sammlung oder ein Element davon diese Größe überschreitet, führt dies zu einem Laufzeitfehler.
Varray-Kapazität kann nicht begrenzt werden¶
Die Varrays von Oracle bieten die Möglichkeit, die Anzahl der Elemente innerhalb der Varrays zu begrenzen. Dies wird von Snowflake nicht unterstützt.
Vorgeschlagene Umgehungsmöglichkeit¶
Über die Definition von Datensatztypen¶
Die vorgeschlagene Umgehungsmöglichkeit ist die Verwendung eines semistrukturierten Datentyps OBJECT, um den Datentyp von Oracle nachzuahmen.
Über die Definition von Sammlungsarten¶
Es gibt zwei verschiedene Umgehungsmöglichkeiten, die von der Art der zu migrierenden Sammlung abhängen:
Es wird vorgeschlagen, assoziative Arrays in einen semistrukturierten Datentyp OBJECT umzuwandeln.
Es wird vorgeschlagen, Varrays und verschachtelte Tabellenarrays in einen semistrukturierten Datentyp ARRAY zu ändern.
Aktuelle Unterstützung von SnowConvert AI¶
Die nächste Tabelle zeigt eine Zusammenfassung der aktuellen Unterstützung, die vom SnowConvert AI Tool bereitgestellt wird. Beachten Sie, dass die Übersetzungen möglicherweise noch nicht endgültig sind und möglicherweise weitere Arbeit erforderlich ist.
Untergeordnetes Feature |
Aktueller Anerkennungsstatus |
Aktueller Übersetzungsstatus |
Hat bekannte Problemumgehungen |
|---|---|---|---|
Anerkannt. |
Nicht übersetzt. |
Ja. |
|
Nicht anerkannt. |
Nicht übersetzt. |
Ja. |
|
Anerkannt. |
Nicht übersetzt. |
Ja. |
|
Anerkannt. |
Nicht übersetzt. |
Ja. |
Bekannte Probleme¶
1. Associate Arrays are considered a Nested Table¶
Ab sofort unterscheidet SnowConvert AI nicht zwischen einem assoziativen Array und einer verschachtelten Tabelle, was bedeutet, dass sie bei der Zählung vermischt werden.
Definition eines assoziativen Array-Typs¶
Dies ist eine Übersetzungsreferenz zur Konvertierung der Deklaration für assoziative Arrays von Oracle in Snowflake
Warnung
Dieser Abschnitt ist noch in Arbeit, die Informationen können sich in Zukunft noch ändern.
Bemerkung
Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.
Beschreibung¶
Ein assoziatives Array (früher PL/SQL-Tabelle oder Index-by-Tabelle genannt) ist eine Menge von Schlüsselwert-Paaren. Jeder Schlüssel ist ein eindeutiger Index, der verwendet wird, um den zugehörigen Wert mit der Syntax
variable_name(index)zu finden.Der Datentyp des
indexkann entweder ein Zeichenfolgentyp (VARCHAR2,VARCHAR,STRING, oderLONG) oderPLS_INTEGERsein. Indizes werden in der Sortierreihenfolge gespeichert, nicht in der Reihenfolge ihrer Erstellung. Bei Zeichenfolgentypen wird die Sortierreihenfolge durch die InitialisierungsparameterNLS_SORTundNLS_COMPbestimmt.
Warnung
Nicht zu verwechseln mit der PL/SQL NESTED TABLE Typdefinition.
Für die Übersetzung wird die Typdefinition durch einen semistrukturierten Datentyp OBJECT ersetzt und anschließend werden seine Verwendungen in allen Operationen entsprechend geändert.
Um einen assoziativen Array-Typ zu definieren, lautet die Syntax wie folgt:
type_definition := TYPE IS TABLE OF datatype INDEX BY indexing_datatype;
indexing_datatype := { PLS_INTEGER
| BINARY_INTEGER
| string_datatype
}
Um eine Variable dieses Typs zu deklarieren:
variable_name collection_type;
Beispielhafte Quellcode-Muster¶
Varchar-indiziertes assoziatives Array¶
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();
Ergebnis¶
DBMS-OUTPUT |
|---|
1 |
3 |
4 |
2 |
3 |
Snowflake¶
Bitte beachten Sie den Parameter „true“ in OBJECT_INSERT. Dies geschieht, damit das Element aktualisiert wird, wenn es bereits im Array vorhanden ist.
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;
Ergebnis¶
DBMS-OUTPUT |
|---|
1 |
3 |
4 |
2 |
3 |
Numerisch indiziertes assoziatives Array¶
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();
Ergebnis¶
DBMS-OUTPUT |
|---|
-1 |
3 |
-4 |
-2 |
-3 |
Snowflake¶
Bitte beachten Sie, dass der numerische Wert entsprechend in Varchar umgewandelt wird, wenn die Operation dies erfordert. Beachten Sie außerdem den Parameter „true“ in OBJECT_INSERT. Dies geschieht, damit das Element aktualisiert wird, wenn es bereits im Array vorhanden ist.
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;
Ergebnis¶
DBMS-OUTPUT |
|---|
-1 |
3 |
-4 |
-2 |
-3 |
Datensatzelement numerisch indiziertes assoziatives Array¶
In diesem Fall besteht das assoziative Array aus einer Datensatzstruktur und diese Struktur muss erhalten bleiben. Zu diesem Zweck wurden weitere Operationen für Einfügungen hinzugefügt.
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();
Ergebnis¶
DBMS-OUTPUT |
|---|
-1 |
3 |
-4 |
-2 |
-3 |
Snowflake¶
In diesem Szenario geht das Einfügen/Aktualisieren von einer automatischen Erstellung des Datensatzes innerhalb des assoziativen Arrays aus und dies muss bei der Erstellung neuer Datensätze berücksichtigt werden.
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;
Ergebnis¶
DBMS-OUTPUT |
|---|
-1 |
3 |
-4 |
-2 |
-3 |
Bekannte Probleme¶
1. They are currently not being recognized¶
SnowConvert AI behandelt diese Sammlungen als verschachtelte Tabellenarrays. Es gibt ein Arbeitselement, um dies zu beheben.
Zugehörige EWIs¶
Keine zugehörigen EWIs.
Sammlungsmethoden¶
Dies ist eine Übersetzungsreferenz zur Konvertierung der Sammlungsmethoden von Oracle in Snowflake
Warnung
Dieser Abschnitt ist noch in Arbeit, die Informationen können sich in Zukunft ändern
Bemerkung
Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.
Beschreibung¶
Eine Sammlungsmethode ist ein PL/SQL-Unterprogramm – entweder eine Funktion, die Informationen über eine Sammlung zurückgibt, oder eine Prozedur, die auf einer Sammlung arbeitet. Sammlungsmethoden erleichtern die Verwendung von Sammlungen und die Wartung Ihrer Anwendungen.
Einige dieser Methoden lassen sich den nativen halbstrukturierten Operationen von Snowflake zuordnen. Diejenigen, die das nicht können oder Unterschiede aufweisen, werden einer UDF-Implementierung zugeordnet.
Aktuelle Unterstützung von SnowConvert AI¶
Die nächste Tabelle zeigt eine Zusammenfassung der aktuellen Unterstützung, die vom SnowConvert AI Tool bereitgestellt wird. Beachten Sie, dass die Übersetzungen möglicherweise noch nicht endgültig sind und möglicherweise weitere Arbeit erforderlich ist.
Methode |
Aktueller Anerkennungsstatus |
Aktueller Übersetzungsstatus |
Zugeordnet zu |
|---|---|---|---|
Nicht anerkannt. |
Nicht übersetzt. |
UDF |
|
Nicht anerkannt. |
Nicht übersetzt. |
UDF (To be defined) |
|
Nicht anerkannt. |
Nicht übersetzt. |
UDF |
|
Nicht anerkannt. |
Nicht übersetzt. |
||
Nicht anerkannt. |
Nicht übersetzt. |
UDF |
|
Nicht anerkannt. |
Nicht übersetzt. |
UDF |
|
Nicht anerkannt. |
Nicht übersetzt. |
||
Nicht anerkannt. |
Nicht übersetzt. |
Nicht unterstützt. |
|
Nicht anerkannt. |
Nicht übersetzt. |
UDF (To be defined) |
|
Nicht anerkannt. |
Nicht übersetzt. |
UDF (To be defined) |
Beispielhafte Quellcode-Muster¶
COUNT¶
Diese Methode gibt die Anzahl der „nicht undefinierten“ (nicht zu verwechseln mit null) Elemente innerhalb einer Sammlung zurück (verschachtelte Tabellen können spärlich werden, wenn diese Elemente dazwischen liegen). Bei assoziativen Arrays gibt sie die Anzahl der Schlüssel im Array zurück.
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();
Ergebnis¶
DBMS-OUTPUT |
|---|
2 |
3 |
4 |
Snowflake¶
Das Snowflake-Äquivalent ist die ARRAY_SIZE-Methode.
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;
Ergebnis¶
DBMS-OUTPUT |
|---|
2 |
3 |
4 |
EXISTS¶
Diese Methode gibt „true“ zurück, wenn das angegebene Element in der Sammlung enthalten ist. In assoziativen Arrays prüft es, ob der Schlüssel enthalten ist.
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();
Ergebnis¶
DBMS-OUTPUT |
|---|
2 |
3 |
4 |
Snowflake¶
Das Snowflake-Äquivalent ist die ARRAY_CONTAINS-Methode. Beachten Sie, dass bei der Verwendung von Varchar-Elementen eine Umwandlung in Variant erforderlich ist.
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;
Ergebnis¶
DBMS-OUTPUT |
|---|
2 |
3 |
4 |
FIRST/LAST¶
Diese beiden Methoden geben jeweils das erste/letzte Element der Sammlung zurück. Wenn die Sammlung leer ist, wird null zurückgegeben. Diese Operation wird einer UDF zugeordnet, die in weiteren Überarbeitungen hinzugefügt wird.
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();
Ergebnis¶
DBMS-OUTPUT |
|---|
abc |
bca |
–Diese leeren Bereiche sind auf die Auswertung auf null zurückzuführen |
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;
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]))
$$;
Ergebnis¶
DBMS-OUTPUT |
|---|
abc |
bca |
–Diese leeren Bereiche sind auf die Auswertung auf null zurückzuführen |
1 |
4 |
DELETE¶
Diese Methode wird verwendet, um Elemente aus einer Sammlung zu entfernen. Es gibt drei mögliche Varianten:
.DELETE entfernt alle Elemente.
.DELETE(n) entfernt das Element, dessen Index mit „n“ übereinstimmt.
.DELETE(n, m) entfernt die Indizes von „n“ bis „m“.
Bemerkung
In Oracle führt die Verwendung dieser Operation für verschachtelte Tabellen dazu, dass sie „undefinierte“ Elemente enthalten, da sie spärlich sind.
Warnung
Bitte beachten Sie, dass die zweite und dritte Version nicht für Varrays gilt.
Oracle¶
Der Einfachheit halber prüft dieses Beispiel nur die Anzahl der Elemente, kann aber so geändert werden, dass der Inhalt der einzelnen Sammlungen angezeigt wird.
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();
Ergebnis¶
DBMS-OUTPUT |
|---|
0 |
0 |
3 |
2 |
0 |
3 |
1 |
Snowflake¶
Snowflake unterstützt keine Löschungen aus einem bestehenden ARRAY und aus diesem Grund besteht die einzige angebotene Umgehungsmöglichkeit darin, ein neues ARRAY in Abhängigkeit von den ursprünglichen Parametern des DELETE neu zu erstellen.
Bemerkung
Beachten Sie, dass eine UDF hinzugefügt wurde, um die Funktionalität für die Aktualisierung des Elements zu implementieren.
Diese UDF wird in späteren Revisionen hinzugefügt werden.
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;
Ergebnis¶
DBMS-OUTPUT |
|---|
0 |
0 |
3 |
2 |
0 |
3 |
1 |
EXTEND¶
Diese Methode wird verwendet, um neue Elemente an eine verschachtelte Tabelle oder ein Varray anzuhängen. Es gibt drei mögliche Varianten:
.EXTEND fügt ein Nullelement ein.
.EXTEND(n) fügt „n“ Nullelemente ein.
.EXTEND(n, i) fügt „n“ Kopien des Elements bei „i“ ein.
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();
Ergebnis¶
DBMS-OUTPUT |
|---|
5 |
5 |
5 |
Snowflake¶
Bemerkung
Beachten Sie, dass eine UDF hinzugefügt wurde, um die Funktionalität für die Aktualisierung des Elements zu implementieren.
Diese UDF wird in späteren Revisionen hinzugefügt werden.
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;
Ergebnis¶
DBMS-OUTPUT |
|---|
5 |
5 |
5 |
TRIM¶
Diese Methode wird verwendet, um die letzten Elemente aus einer verschachtelten Tabelle oder einem Varray zu entfernen. Es gibt zwei mögliche Varianten:
.TRIM entfernt das letzte Element.
.TRIM(n) löscht die letzten „n“ Elemente.
Bemerkung
Diese Funktion kann mit Hilfe von ARRAYwerden _SLICE implementiert werden
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();
Ergebnis¶
DBMS OUTPUT
-----------
2
2
LIMIT¶
Diese Methode gibt das maximale Limit eines Varrays zurück.
Gefahr
Diese Methode wird in Snowflake nicht unterstützt.
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();
Ergebnis¶
DBMS-OUTPUT |
|---|
5 |
6 |
PRIOR/NEXT¶
Diese Methode gibt den vorherigen/nächsten Index zurück, wenn ein Index angegeben wird. Wenn es keinen vorherigen/nächsten gibt, wird null zurückgegeben. Sie wird am häufigsten verwendet, um eine Sammlung zu durchsuchen.
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();
Ergebnis¶
DBMS-OUTPUT |
|---|
– Leere Bereiche sind auf Nullergebnisse zurückzuführen |
1 |
3 |
abc |
jkl |
jkl |
Bekannte Probleme¶
1. Limit method is not supported in Snowflake¶
Snowflake bietet keine Unterstützung für Varrays mit begrenztem Speicherplatz. Aus diesem Grund wird diese Methode nicht unterstützt.
Zugehörige EWIs¶
Keine zugehörigen EWIs.
Typdefinition für verschachtelte Tabellen-Arrays¶
Dies ist eine Übersetzungsreferenz zur Konvertierung der Deklaration für verschachtelte Tabellenarrays von Oracle in Snowflake
Warnung
Dieser Abschnitt ist noch in Arbeit, die Informationen können sich in Zukunft noch ändern.
Bemerkung
Dieser Abschnitt gilt für die PL/SQL-Version der verschachtelten Tabellenarrays; für die eigenständige Version siehe Definition verschachtelter Tabellentypen.
Bemerkung
Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.
Beschreibung¶
In der Datenbank ist eine verschachtelte Tabelle ein Spaltentyp, der eine unbestimmte Anzahl von Zeilen in keiner bestimmten Reihenfolge speichert.
Wenn Sie einen verschachtelten Tabellenwert aus der Datenbank in eine PL/SQL-Variable für verschachtelte Tabellen abrufen, vergibt PL/SQL den Zeilen fortlaufende Indizes, beginnend bei 1. Mit diesen Indizes können Sie auf die einzelnen Zeilen der Variablen für verschachtelte Tabellen zugreifen. Die Syntax lautet
variable_name(index). Die Indizes und die Zeilenreihenfolge einer verschachtelten Tabelle bleiben möglicherweise nicht stabil, wenn Sie die verschachtelte Tabelle speichern und aus der Datenbank abrufen.
Für die Übersetzung wird die Typdefinition durch einen semistrukturierten Datentyp ARRAY ersetzt und anschließend werden seine Verwendungen in allen Operationen entsprechend geändert. Bitte beachten Sie, dass die Übersetzung für verschachtelte Tabellen und Varrays identisch ist.
Um einen verschachtelten Tabellen-Array-Typ zu definieren, lautet die Syntax wie folgt:
type_definition := TYPE IS TABLE OF datatype;
Um eine Variable dieses Typs zu deklarieren:
variable_name collection_type;
Beispielhafte Quellcode-Muster¶
Definitionen für verschachtelte Tabellen-Arrays¶
Dies veranschaulicht, wie Sie verschiedene verschachtelte Tabellenarrays erstellen und die Definitionen für die Variablen migrieren können.
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;
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;
$$;
Iteration der verschachtelten Tabelle¶
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();
Ergebnis¶
DBMS-OUTPUT |
|---|
10 |
20 |
30 |
40 |
20 |
30 |
Snowflake¶
Bemerkung
Beachten Sie, dass eine UDF hinzugefügt wurde, um die Funktionalität für die Aktualisierung des Elements zu implementieren.
Diese UDF wird in späteren Revisionen hinzugefügt werden.
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;
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)))
$$;
Ergebnis¶
DBMS-OUTPUT |
|---|
10 |
20 |
30 |
40 |
20 |
30 |
Bekannte Probleme¶
1. They are currently not being converted¶
SnowConvert AI unterstützt nicht die Übersetzung dieser Elemente.
2. Indexing needs to be modified¶
Die Indizes von Oracle beginnen bei 1, bei Snowflake beginnen sie bei 0.
Zugehörige EWIs¶
Keine zugehörigen EWIs.
Datensatztyp-Definition¶
Dies ist eine Übersetzungsreferenz zur Konvertierung der Datensatzdeklaration von Oracle in Snowflake
Warnung
Dieser Abschnitt ist noch in Arbeit, die Informationen können sich in Zukunft noch ändern.
Bemerkung
Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.
Beschreibung¶
Eine Datensatzvariable ist eine zusammengesetzte Variable, deren interne Komponenten, Felder genannt, unterschiedliche Datentypen haben können. Der Wert einer Datensatzvariablen und die Werte ihrer Felder können sich ändern.
Sie referenzieren eine ganze Datensatzvariable über ihren Namen. Sie referenzieren ein Datensatzfeld mit der Syntax
record.field.Sie können eine Datensatzvariable auf jede dieser Arten erstellen:
Definieren Sie einen Datensatztyp und deklarieren Sie dann eine Variable dieses Typs.
Verwenden Sie
%ROWTYPE, um eine Datensatzvariable zu deklarieren, die entweder eine vollständige oder teilweise Zeile einer Datenbanktabelle oder -ansicht darstellt.Verwenden Sie
%TYPE, um eine Datensatzvariable vom gleichen Typ wie eine zuvor deklarierte Datensatzvariable zu deklarieren.
Für die Übersetzung wird die Typdefinition durch einen semistrukturierten Datentyp OBJECT ersetzt und anschließend werden seine Verwendungen in allen Operationen entsprechend geändert.
Um einen Datensatztyp zu definieren, lautet die Syntax wie folgt:
type_definition := TYPE IS RECORD ( field_definition [, field_definition...] );
field_definition := field_name datatype [ { [NOT NULL default ] | default } ]
default := [ { := | DEFAULT } expression]
Um eine Variable dieses Typs zu deklarieren:
variable_name { record_type
| rowtype_attribute
| record_variable%TYPE
};
Beispielhafte Quellcode-Muster¶
Bemerkung
Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.
Datensatzinitialisierung und -zuweisung¶
In diesem Beispiel wird versucht, zwei neue Zeilen mit Hilfe einer Datensatzvariablen einzufügen, die mitten in der Prozedur neu zugewiesen wird.
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;
Ergebnis¶
COL1 |
COL2 |
|---|---|
1,5 |
1 |
2.5 |
2 |
Snowflake¶
Beachten Sie, wie die Neuzuweisungen durch ein OBJECT_INSERT ersetzt werden, die aktualisiert, wenn die Spalte bereits existiert, und wie die VALUES-Klausel durch ein SELECT ersetzt wird.
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;
Ergebnis¶
COL1 |
COL2 |
|---|---|
1,5 |
1 |
2.5 |
2 |
%ROWTYPE Record and Values Record¶
Da es die Operationen sind, die die Struktur definieren, können diese Definitionen durch einen OBJECT-Datentyp ersetzt werden, aber die Werte des Datensatzes müssen zerlegt werden, da das Einfügen des Datensatzes „wie er ist“ nicht unterstützt wird.
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;
Ergebnis¶
COL1 |
COL2 |
COL3 |
|---|---|---|
1 |
„Hello“ |
25-DEC-20 |
Snowflake¶
Bitte beachten Sie abschließend, dass die Variable OBJECT initialisiert werden muss, um die Informationen hinzufügen zu können.
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;
Ergebnis¶
COL1 |
COL2 |
COL3 |
|---|---|---|
1 |
„Hello“ |
25-DEC-20 |
Abrufen von Daten in einem Datensatz¶
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();
Ergebnis¶
DBMS-OUTPUT |
|---|
1 |
Hello |
25-DEC-20 |
Snowflake¶
Bitte beachten Sie das zusätzliche OBJECT_CONSTRUCT in der Cursor-Definition. Dadurch kann ein OBJECT extrahiert werden, das dann verwendet werden kann, um die FETCH-Anweisung nahtlos zu migrieren.
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();
Ergebnis¶
DBMS-OUTPUT |
|---|
1 |
Hello |
25-DEC-20 |
Zuweisung einer Datensatzvariable in einem SELECT INTO¶
Diese Transformation besteht darin, die Funktion OBJECT_CONTRUCT zu nutzen, um den Datensatz unter Verwendung der SELECT-Spalten als Argumente zu initialisieren.
Beispiel für Hilfscode¶
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');
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');
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;
Ergebnis¶
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;
Ergebnis¶
COL1 |
COL2 |
|---|---|
SELECT 1 |
NAME 1 |
SELECT 2 |
NAME 2 |
SELECT 3 |
NAME 3 |
SELECT 4 |
NAME 4 |
Bekannte Probleme¶
1. The following functionalities are currently not being converted:¶
Abrufen von Daten in einem Datensatz.
Verschachtelte Datensätze (Datensätze in Datensätzen).
Sammlungen innerhalb von Aufzeichnungen.
Zugehörige EWIs¶
[SSC-EWI-0036](../../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0036): Datentyp in einen anderen Datentyp konvertiert.
SSC-EWI-0056: CREATE-Typ wird nicht unterstützt
SSC-FDM-0006: Spalte vom Typ ‚number‘ verhält sich in Snowflake möglicherweise nicht ähnlich.
SSC-FDM-OR0042: In Zeitstempel transformierter Datumstyp weist ein anderes Verhalten auf.
SSC-FDM-OR0035: DBMS_OUTPUT. UDF-Implementierung von PUTLINE-Prüfung.
SSC-PRF-0003: Das Abrufen innerhalb einer Schleife wird als komplexes Muster betrachtet; dies kann die Leistung von Snowflake beeinträchtigen.
Definition des Varray-Typs¶
Dies ist eine Übersetzungsreferenz zur Konvertierung der Varray-Deklaration von Oracle in Snowflake
Warnung
Dieser Abschnitt ist noch in Arbeit, die Informationen können sich in Zukunft noch ändern.
Bemerkung
Dieser Abschnitt gilt für die PL/SQL-Version von Varrays; für die eigenständige Version siehe Definition von Array-Typen.
Bemerkung
Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.
Beschreibung¶
Ein Varray (Array mit variabler Größe) ist ein Array, dessen Anzahl der Elemente zwischen null (leer) und der angegebenen Maximalgröße variieren kann.
Um auf ein Element einer Varray-Variablen zuzugreifen, verwenden Sie die Syntax
variable_name(index). Der untere Grenzwert fürindexist 1, der obere Grenzwert ist die aktuelle Anzahl der Elemente. Der obere Grenzwert ändert sich, wenn Sie Elemente hinzufügen oder löschen, aber er kann die maximale Größe nicht überschreiten. Wenn Sie ein Varray speichern und aus der Datenbank abrufen, bleiben seine Indizes und die Reihenfolge der Elemente unverändert.
Für die Übersetzung wird die Typdefinition durch einen semistrukturierten Datentyp ARRAY ersetzt und anschließend werden seine Verwendungen in allen Operationen entsprechend geändert. Bitte beachten Sie, dass die Übersetzung für verschachtelte Tabellen und Varrays identisch ist.
Um einen Varray-Typ zu definieren, lautet die Syntax wie folgt:
type_definition := { VARRAY | [VARYING] ARRAY } (size_limit) OF datatype
[NOT NULL];
Um eine Variable dieses Typs zu deklarieren:
variable_name collection_type;
Beispielhafte Quellcode-Muster¶
Varray-Definitionen¶
Dies veranschaulicht, wie Sie auf drei verschiedene Arten ein Varray erstellen und wie Sie diese Definitionen für die Variablen migrieren können.
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;
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;
$$;
Varray-Iteration¶
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();
Ergebnis¶
DBMS-OUTPUT |
|---|
10 |
20 |
30 |
40 |
20 |
30 |
Snowflake¶
Bemerkung
Beachten Sie, dass eine UDF hinzugefügt wurde, um die Funktionalität für die Aktualisierung des Elements zu implementieren.
Diese UDF wird in späteren Revisionen hinzugefügt werden.
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();
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)))
$$;
Ergebnis¶
DBMS-OUTPUT |
|---|
10 |
20 |
30 |
40 |
20 |
30 |
Bekannte Probleme¶
1. They are currently not being converted¶
SnowConvert AI unterstützt nicht die Übersetzung dieser Elemente.
2. Indexing needs to be modified¶
Die Indizes von Oracle beginnen bei 1, bei Snowflake beginnen sie bei 0.
3. Array Density may not match the original¶
Da der Datentyp ARRAY spärlich werden kann, sollten Sie beim Hinzufügen oder Löschen von Arrays vorsichtig sein. Die Verwendung von ARRAY_COMPACT() nach solchen Operationen kann hilfreich sein, wenn die Dichte ein Problem darstellt.
Zugehörige EWIs¶
SSC-EWI-0058: Die Funktionalität wird derzeit nicht von Snowflake Scripting unterstützt.
SSC-EWI-0062: Die Verwendung des CUSTOM-Typs wurde in ‚variant‘ geändert.
[SSC-EWI-0073](../../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0073): Überprüfung der Funktionsäquivalenz ausstehend.
SSC-EWI-OR0108: Die folgende ASSIGNMENT-Anweisung wird von Snowflake Scripting nicht unterstützt.
SSC-FDM-OR0035: DBMS_OUTPUT. UDF-Implementierung von PUTLINE-Prüfung.
Sammlung Bulk-Operationen¶
Dies ist eine Übersetzungsreferenz zur Konvertierung der Sammlung Bulk-Operationen von Oracle in Snowflake
Warnung
Dieser Abschnitt ist noch in Arbeit, die Informationen können sich in Zukunft ändern
Bemerkung
Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.
Beschreibung¶
Die
BULKCOLLECT-Klausel, ein Feature von Bulk-SQL, gibt die Ergebnisse von SQL bis PL/SQL in Batches und nicht einzeln zurück.Die
BULKCOLLECT-Klausel kann vorkommen in der:
SELECT``INTO-Anweisung
FETCH-Anweisung
RETURNINGINTO-Klausel von:
DELETE-Anweisung
INSERT-Anweisung
UPDATE-Anweisung
EXECUTE``IMMEDIATE-AnweisungMit der Klausel
BULKCOLLECTruft jede der vorangehenden Anweisungen ein ganzes Resultset ab und speichert es in einer oder mehreren Sammlungsvariablen in einer einzigen Operation (was effizienter ist als die Verwendung einer Schleifenanweisung, um eine Ergebniszeile nach der anderen abzurufen).
(Oracle PL/SQL Language Reference BULK COLLECT CLAUSE)
In diesem Abschnitt finden Sie einige Umgehungsmöglichkeiten für SELECTs und FETCH-Cursor mit BULK-Klauseln.
Beispielhafte Quellcode-Muster¶
Quelltabelle¶
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);
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);
BULK COLLECT von einer Tabelle¶
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();
Ergebnis¶
DBMS-OUTPUT |
|---|
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
Snowflake¶
Gefahr
EXECUTE IMMEDIATE mit der BULK COLLECT-Klausel werden keine Umgehungsmöglichkeiten angeboten.
Bemerkung
Bitte beachten Sie, dass der FETCH-Cursor zwar größtenteils beibehalten werden kann, aus Leistungsgründen aber nach Möglichkeit in SELECT-Anweisungen umgewandelt werden sollte.
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();
Ergebnis¶
DBMS-OUTPUT |
|---|
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
– EXECUTE IMMEDIATE NOT EXECUTED, wird nicht unterstützt. |
SELECT INTO-Anweisungsfall¶
In diesem Fall verwendet die Übersetzungsspezifikation RESULTSETs. Lesen Sie die Dokumentation zu den Anweisungen WITH, SELECT und BULK COLLECT INTO hier:
Bekannte Probleme¶
1. Heavy performance issues on FETCH Cursor workaround¶
Die Umgehungsmöglichkeit für den FETCH-Cursor hat aufgrund der temporären Tabelle hohe Leistungsanforderungen. Es wird empfohlen, diese manuell in SELECT-Anweisungen zu migrieren
2. Execute immediate statements are not transformed¶
Sie werden von SnowConvert AI nicht unterstützt, können aber manuell in SELECT-Anweisungen geändert werden.
Zugehörige EWIs¶
SSC-EWI-0058: Die Funktionalität wird derzeit nicht von Snowflake Scripting unterstützt.
SSC-EWI-0062: Die Verwendung des CUSTOM-Typs wurde in ‚variant‘ geändert.
[SSC-EWI-0073](../../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0073): Überprüfung der Funktionsäquivalenz ausstehend
SSC-EWI-OR0036: Bei Problemen mit der Auflösung von Typen verhält sich die arithmetische Operation zwischen Zeichenfolge und Datum möglicherweise nicht korrekt.
SSC-EWI-OR0108: Die folgende ASSIGNMENT-Anweisung wird von Snowflake Scripting nicht unterstützt.
SSC-FDM-OR0035: DBMS_OUTPUT. UDF-Implementierung von PUTLINE-Prüfung.
SSC-PRF-0001: Diese Anweisung umfasst die Verwendung von Cursor-Fetch-Bulk-Vorgängen.
SSC-EWI-0030: Die folgende Anweisung enthält Verwendungen von dynamischem SQL.
WITH-, SELECT- und BULKCOLLECTINTO-Anweisungen¶
Gefahr
Dieser Abschnitt ist eine Übersetzungsspezifikation. Die Informationen können sich in Zukunft ändern.
Bemerkung
Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.
Beschreibung¶
Dieser Abschnitt ist eine Übersetzungsspezifikation für die Anweisung WITH im Anschluss an eine Anweisung SELECT, die eine Anweisung BULK COLLECT INTO verwendet. Weitere Informationen finden Sie in der folgenden Dokumentation:
[SnowConvert AI – Übersetzung von Bulk Collect](# Bulk-collect-from-a-table).
Beispielhafte Quellcode-Muster¶
Bemerkung
Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.
Die folgende Abfrage wird für die folgenden Beispiele verwendet.
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');
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');
1. Inside procedure simple case¶
Gefahr
Dies ist ein Ansatz, der einen Resultset-Datentyp verwendet. Benutzerdefinierte Typen müssen überprüft werden. In der folgenden Snowflake-Dokumentation finden Sie weitere Informationen zu RESULTSETs.
Das folgende Beispiel verwendet einen benutzerdefinierten Typ, der indirekt als Tabelle deklariert ist. Die Übersetzung für diesen Fall implementiert ein RESULTSET als Datentyp in Snowflake. Das Resultset wird in einer Variablen gespeichert, die in einer TABLE() Funktion eingeschlossen zurückgegeben werden muss.
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();
Ergebnis¶
Bemerkung
Die Abfrage liefert keine Ergebnisse, aber die erwarteten gesammelten Informationen wären die für das Beispiel verwendeten IT-Gehaltsinformationen:
IT_Salary |
|---|
75000 |
80000 |
Gefahr
Eine der Beschränkungen von RESULTSETs ist, dass sie nicht als Tabellen verwendet werden können. Z.B.: select * from my_result_set; (Dies ist ein Fehler, lesen Sie die folgende Dokumentation für weitere Informationen).
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();
Ergebnis¶
SALARY |
|---|
77500 |
80000 |
2. Simple case for iterations: FOR LOOP statement¶
Im folgenden Fall geht es darum, eine Übersetzung für die Iteration mit FOR...LOOP zu definieren. In diesem Fall ist der benutzerdefinierte Typ implizit eine Tabelle, so dass es möglich ist, einen Cursor für die Iteration zu verwenden. Lesen Sie die folgende Dokumentation, um mehr zu erfahren:
Snowflake-Dokumentation über die Rückgabe einer Tabelle für einen Cursor.
In diesem Fall ist es notwendig, einen Cursor für die Iteration zu erstellen. Lesen Sie die folgende Dokumentation zur zur Syntax der Cursorzuweisung.
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();
Ergebnis¶
Statement processed.
Average Salary for IT Department: 77500
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();
Ergebnis¶
SIMPLE_PROCEDURE |
|---|
Durchschnittsgehalt für IT-Abteilung: 77.500 |
Bekannte Probleme¶
1. Resulset limitations.¶
Es gibt Beschränkungen bei der Verwendung des Datentyps RESULTSET. Lesen Sie die folgende Snowflake Dokumentation , um mehr zu erfahren. Markante Beschränkungen sind die folgenden:
Deklarieren einer Spalte vom Typ RESULTSET
Deklarieren eines Parameters vom Typ RESULTSET
Deklarieren des Rückgabetyps einer gespeicherten Prozedur als RESULTSET.
2. Execute statements with Bulk Collect clause are not supported.¶
Lesen Sie die folgende Dokumentation Bulk Collect from a Table.
Zugehörige EWIs¶
SSC-EWI-0058: Die Funktionalität wird derzeit nicht von Snowflake Scripting unterstützt.
SSC-EWI-0062: Die Verwendung des CUSTOM-Typs wurde in ‚variant‘ geändert.
[SSC-EWI-0073](../../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0073): Überprüfung der Funktionsäquivalenz ausstehend
SSC-EWI-OR0036: Bei Problemen mit der Auflösung von Typen verhält sich die arithmetische Operation zwischen Zeichenfolge und Datum möglicherweise nicht korrekt.
SSC-EWI-OR0072: Prozedurales Element wird nicht unterstützt
SSC-EWI-OR0104: Nicht verwendbare Sammlungsvariable.
SSC-FDM-0006: Spalte vom Typ ‚number‘ verhält sich in Snowflake möglicherweise nicht ähnlich.
SSC-FDM-OR0035: DBMS_OUTPUT. UDF-Implementierung von PUTLINE-Prüfung.