SnowConvert:PL/SQL zu Snowflake Scripting

ASSIGNMENT STATEMENT

Beschreibung

Die ASSIGNMENT-Anweisung setzt den Wert eines Datenelements auf einen gültigen Wert.\ (Oracle PL/SQL Language Reference ASSIGNMENT Statement)

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

 assignment_statement_target := expression ;

assignment_statement_target = 
{ collection_variable [ ( index ) ]
| cursor_variable
| :host_cursor_variable
| object[.attribute]
| out_parameter
| placeholder
| record_variable[.field]
| scalar_variable
}
Copy
 LET <variable_name> <type> { DEFAULT | := } <expression> ;

LET <variable_name> { DEFAULT | := } <expression> ;
Copy

Bemerkung

LET-Schlüsselwort wird für Zuweisungsanweisungen nicht benötigt, wenn die Variable zuvor deklariert wurde. Weitere Informationen finden Sie in der Dokumentation Snowflake-Zuweisung.

Beispielhafte Quellcode-Muster

1. Scalar Variables

Oracle
 CREATE TABLE TASSIGN (
    COL1 NUMBER,
    COL2 NUMBER,
    COL3 VARCHAR(20),
    COL4 VARCHAR(20)
);

CREATE OR REPLACE PROCEDURE PSCALAR
AS
   var1  NUMBER := 40;
   var2  NUMBER := 22.50;
   var3  VARCHAR(20);
   var4  BOOLEAN;
   var5  NUMBER;
BEGIN
   var1 := 1;
   var2 := 2.1;
   var2 := var2 + var2;
   var3 := 'Hello World';
   var4 := true;
   var4 := var1 > 500;
   IF var4 THEN
      var5 := 0;
   ELSE
      var5 := 1;
   END IF;
  INSERT INTO TASSIGN VALUES(var1, var2, var3, var5);
END;

CALL PSCALAR();

SELECT * FROM TASSIGN;
Copy
COL1|COL2|COL3       |COL4|
----+----+-----------+----+
   1| 4.2|Hello World|   1|

Copy
Snowflake Scripting
 CREATE OR REPLACE TABLE TASSIGN (
     COL1 NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
     COL2 NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
     COL3 VARCHAR(20),
     COL4 VARCHAR(20)
 )
 COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
 ;

 CREATE OR REPLACE PROCEDURE PSCALAR ()
 RETURNS VARCHAR
 LANGUAGE SQL
 COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
 EXECUTE AS CALLER
 AS
 $$
     DECLARE
     var1 NUMBER(38, 18) := 40;
     var2 NUMBER(38, 18) := 22.50;
     var3  VARCHAR(20);
     var4  BOOLEAN;
     var5 NUMBER(38, 18);
     BEGIN
     var1 := 1;
     var2 := 2.1;
     var2 := :var2 + :var2;
     var3 := 'Hello World';
     var4 := true;
     var4 := :var1 > 500;
     IF (:var4) THEN
       var5 := 0;
       ELSE
       var5 := 1;
       END IF;
       INSERT INTO TASSIGN
       VALUES(:var1, :var2, :var3, :var5);
     END;
 $$;

 CALL PSCALAR();
 
SELECT * FROM
     TASSIGN;
Copy
COL1                |COL2                |COL3       |COL4|
--------------------+--------------------+-----------+----+
1.000000000000000000|4.000000000000000000|Hello World|1   |

Copy

Warnung

Die Transformation für einige Datentypen muss aktualisiert werden, dies kann zu anderen Ergebnissen führen. Zum Beispiel rundet NUMBER auf NUMBER den Wert und das Dezimalkomma geht verloren. Es gibt bereits ein Work-Element zu diesem Thema.

2. Out Parameter Assignment

Weitere Informationen darüber, wie die Ausgabeparameter umgewandelt werden, finden Sie im folgenden Artikel Ausgabeparameter.

3. Not Supported Assignments

Oracle
 CREATE OR REPLACE PROCEDURE pinvalid(out_parameter   IN OUT NUMBER)
AS
record_variable       employees%ROWTYPE;

TYPE cursor_type IS REF CURSOR;
cursor1   cursor_type;
cursor2   SYS_REFCURSOR;

TYPE collection_type IS TABLE OF NUMBER INDEX BY VARCHAR(64);
collection_variable     collection_type;

BEGIN
--Record Example
  record_variable.last_name := 'Ortiz';

--Cursor Example
  cursor1 := cursor2;
  
--Collection
  collection_variable('Test') := 5;

--Out Parameter
  out_parameter := 123;
END;
Copy
Snowflake Scripting
 --** SSC-FDM-0007 - MISSING DEPENDENT OBJECT "employees" **
CREATE OR REPLACE PROCEDURE pinvalid (out_parameter NUMBER(38, 18))
RETURNS VARIANT
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();
--    !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'PL REF CURSOR TYPE DEFINITION' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!

--    TYPE cursor_type IS REF CURSOR;
    cursor1_res RESULTSET;
    cursor2_res RESULTSET;
--    !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'PL COLLECTION TYPE DEFINITION' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!

--    TYPE collection_type IS TABLE OF NUMBER INDEX BY VARCHAR(64);
    collection_variable VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-0062 - CUSTOM TYPE 'collection_type' USAGE CHANGED TO VARIANT ***/!!!;
  BEGIN
    --Record Example
    record_variable := OBJECT_INSERT(record_variable, 'LAST_NAME', 'Ortiz', true);

    --Cursor Example
    !!!RESOLVE EWI!!! /*** SSC-EWI-OR0108 - THE FOLLOWING ASSIGNMENT STATEMENT IS NOT SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
      cursor1 := :cursor2;

    --Collection
    !!!RESOLVE EWI!!! /*** SSC-EWI-OR0108 - THE FOLLOWING ASSIGNMENT STATEMENT IS NOT SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
      collection_variable('Test') := 5;
    --Out Parameter
    out_parameter := 123;
    RETURN out_parameter;
  END;
$$;
Copy

Bekannte Probleme

1. Several Unsupported Assignment Statements

Derzeit werden Transformationen für Cursor-, Auflistungs-, Datensatz- und benutzerdefinierte Typvariablen von Snow Scripting nicht unterstützt. Daher werden Zuweisungsanweisungen, die diese Variablen verwenden, kommentiert und als nicht unterstützt gekennzeichnet. Die Änderung dieser Variablen in semistrukturierte Daten von Snowflake könnte in einigen Szenarien eine Umgehungsmöglichkeit schaffen.

CALL

Beschreibung

Es gibt zwei Arten von CALL-Anweisungen in Oracle:

1-CALL-Anweisung:

Verwenden Sie die Anweisung CALL, um eine Routine (eine eigenständige Prozedur oder Funktion oder eine innerhalb eines Typs oder Pakets definierte Prozedur oder Funktion) aus SQL heraus auszuführen. (Oracle SQL Language Reference CALL)

2-Call-Spezifikation:

Eine Call-Spezifikation deklariert eine Java-Methode oder ein C-Unterprogramm, so dass es von PL/SQL aus aufgerufen werden kann. (Oracle SQL Language Reference Call Specification)

Die CALL-Spezifikation wird in Snowflake Scripting nicht unterstützt, da sie Teil der Entwicklungsbibliotheken für C und JAVA ist, nicht aber eine SQL-Anweisung, daher wird diese Anweisung nicht transformiert.

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIs

Keine zugehörigen EWIs.

CASE

Beschreibung

Die Anweisung CASE wählt aus einer Sequenz von Bedingungen aus und führt eine entsprechende Anweisung aus. Weitere Informationen zu Oracle CASE finden Sie hier.

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

Simple Case

 [ <<label>> ] CASE case_operand
  WHEN boolean_expression THEN statement ;
  [ WHEN boolean_expression THEN statement ; ]...
  [ ELSE statement [ statement ]... ;
END CASE [ label ] ;
Copy
 CASE ( <expression_to_match> )
    WHEN <expression> THEN
        <statement>;
        [ <statement>; ... ]
    [ WHEN ... ]
    [ ELSE
        <statement>;
        [ <statement>; ... ]
    ]
END [ CASE ] ;
Copy

Searched Case

 [ <<label>> ] CASE
  WHEN boolean_expression THEN statement ;
  [ WHEN boolean_expression THEN statement ; ]...
  [ ELSE statement [ statement ]... ;
END CASE [ label ];
Copy
 CASE
    WHEN <boolean_expression> THEN
        <statement>;
        [ <statement>; ... ]
    [ WHEN ... ]
    [ ELSE
        <statement>;
        [ <statement>; ... ]
    ]
END [ CASE ] ;
Copy

Beispielhafte Quellcode-Muster

Beispiel einer Hilfstabelle

 CREATE TABLE case_table(col varchar(30));
Copy
 CREATE OR REPLACE TABLE case_table (col varchar(30))
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;
Copy

Simple Case

Oracle
 CREATE OR REPLACE PROCEDURE caseExample1 ( grade NUMBER )
IS
RESULT VARCHAR(20);
BEGIN
   <<CASE1>>
   CASE grade
    WHEN 10 THEN RESULT:='Excellent';
    WHEN 9 THEN RESULT:='Very Good';
    WHEN 8 THEN RESULT:='Good';
    WHEN 7 THEN RESULT:='Fair';
    WHEN 6 THEN RESULT:='Poor';
    ELSE RESULT:='No such grade';
  END CASE CASE1;
  INSERT INTO CASE_TABLE(COL) VALUES (RESULT);
END;

CALL caseExample1(6);

CALL caseExample1(4);

CALL caseExample1(10);

SELECT * FROM CASE_TABLE;
Copy
|COL          |
|-------------|
|Poor         |
|No such grade|
|Excellent    |


Copy
Snowflake Scripting
 CREATE OR REPLACE PROCEDURE caseExample1 (grade NUMBER(38, 18))
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    RESULT VARCHAR(20);
  BEGIN
    !!!RESOLVE EWI!!! /*** SSC-EWI-0094 - LABEL DECLARATION FOR A STATEMENT IS NOT SUPPORTED BY SNOWFLAKE SCRIPTING <<CASE1>> ***/!!!
    CASE :grade
      WHEN 10 THEN
        RESULT := 'Excellent';
      WHEN 9 THEN
        RESULT := 'Very Good';
      WHEN 8 THEN
        RESULT := 'Good';
      WHEN 7 THEN
        RESULT := 'Fair';
      WHEN 6 THEN
        RESULT := 'Poor';
        ELSE
        RESULT := 'No such grade';
    END CASE;
    INSERT INTO CASE_TABLE(COL) VALUES (:RESULT);
  END;
$$;

CALL caseExample1(6);

CALL caseExample1(4);

CALL caseExample1(10);

--** SSC-FDM-0007 - MISSING DEPENDENT OBJECT "CASE_TABLE" **

SELECT * FROM
  CASE_TABLE;
Copy
|COL          |
|-------------|
|Poor         |
|No such grade|
|Excellent    |


Copy

Searched Case

Oracle
 CREATE OR REPLACE PROCEDURE caseExample2 ( grade NUMBER )
IS
RESULT VARCHAR(20);
BEGIN
    <<CASE1>>
    CASE
    	WHEN grade = 10 THEN RESULT:='Excellent';
    	WHEN grade = 9 THEN RESULT:='Very Good';
    	WHEN grade = 8 THEN RESULT:='Good';
    	WHEN grade = 7 THEN RESULT:='Fair';
    	WHEN grade = 6 THEN RESULT:='Poor';
    	ELSE RESULT:='No such grade';
  END CASE CASE1;
  INSERT INTO CASE_TABLE(COL) VALUES (RESULT);
END;

CALL caseExample2(6);
CALL caseExample2(4);
CALL caseExample2(10);
SELECT * FROM CASE_TABLE;
Copy
|COL          |
|-------------|
|Poor         |
|No such grade|
|Excellent    |


Copy
Snowflake Scripting
 CREATE OR REPLACE PROCEDURE caseExample2 (grade NUMBER(38, 18))
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    RESULT VARCHAR(20);
  BEGIN
    !!!RESOLVE EWI!!! /*** SSC-EWI-0094 - LABEL DECLARATION FOR A STATEMENT IS NOT SUPPORTED BY SNOWFLAKE SCRIPTING <<CASE1>> ***/!!!
    CASE
      WHEN :grade = 10 THEN
        RESULT := 'Excellent';
      WHEN :grade = 9 THEN
        RESULT := 'Very Good';
      WHEN :grade = 8 THEN
        RESULT := 'Good';
      WHEN :grade = 7 THEN
        RESULT := 'Fair';
      WHEN :grade = 6 THEN
        RESULT := 'Poor';
        ELSE
        RESULT := 'No such grade';
    END CASE;
    INSERT INTO CASE_TABLE(COL) VALUES (:RESULT);
  END;
$$;

CALL caseExample2(6);

CALL caseExample2(4);

CALL caseExample2(10);

--** SSC-FDM-0007 - MISSING DEPENDENT OBJECT "CASE_TABLE" **
SELECT * FROM
  CASE_TABLE;
Copy
|COL          |
|-------------|
|Poor         |
|No such grade|
|Excellent    |


Copy

Bekannte Probleme

1. Labels are not supported in Snowflake Scripting CASE syntax

Die Beschriftungen werden je nach ihrer Position auskommentiert oder entfernt.

Zugehörige EWIS

  1. [SSC-EWI-0094](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0094): Label-Deklaration wird nicht unterstützt.

  2. [SSC-FDM-0007](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0007): Element mit fehlenden Abhängigkeiten.

COMPOUND STATEMENTS

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.

Allgemeine Beschreibung

Die Grundeinheit eines PL/SQL-Quellprogramms ist der Block, in dem zusammengehörige Deklarationen und Anweisungen zusammengefasst werden.

Ein PL/SQL-Block wird durch die Schlüsselwörter DECLARE, BEGIN, EXCEPTION, und END definiert. Diese Schlüsselwörter unterteilen den Block in einen deklarativen Teil, einen ausführbaren Teil und einen Teil zur Behandlung von Ausnahmen. Es wird nur der ausführbare Teil benötigt. (PL/SQL Anonyme Blöcke)

Der BEGIN...END-Block in Oracle kann die folgenden Eigenschaften haben:

  1. Verschachtelt sein.

  2. Enthält die Anweisung DECLARE für Variablen.

  3. Gruppieren Sie mehrere SQL oder PL/SQL-Anweisungen.

Oracle-Syntax

 [DECLARE <Variable declaration>]
BEGIN
  <Executable statements>
[EXCEPTION <Exception handler>]
END
Copy

Snowflake-Syntax

 BEGIN
    <statement>;
    [ <statement>; ... ]
[ EXCEPTION <exception_handler> ]
END;
Copy

Bemerkung

In Snowflake kann ein BEGIN/END-Block das Top-Level-Konstrukt innerhalb eines anonymen Blocks sein (Snowflake-Dokumentation).

Beispielhafte Quellcode-Muster

1. IF-ELSE block

Lesen Sie die folgende Dokumentation über IF-Anweisungen, um mehr zu erfahren: Übersetzung von SnowConvert IF-Anweisungen und Dokumentation zu Snowflake IF-Anweisungen

Oracle
 DECLARE
    age NUMBER := 18;
BEGIN
    IF age >= 18 THEN 
        DBMS_OUTPUT.PUT_LINE('You are an adult.');
    ELSE 
        DBMS_OUTPUT.PUT_LINE('You are a minor.');
    END IF;
END;
Copy
Statement processed.
You are an adult.

Copy
Snowflake

Warnung

Wenn Sie eine Prozedur oder eine benutzerdefinierte Funktion (UDF) aufrufen, müssen Sie Code generieren, um die Äquivalenz als Aufrufergebnisse-Variable zu unterstützen. Wird in diesem Fall zum Drucken der Informationen verwendet.

Überprüfen Sie die benutzerdefinierte Funktion (UDF), die [hier] verwendet wird (./built-in-packages.md#put_line-procedure).

 DECLARE
    age NUMBER(38, 18) := 18;
    call_results VARIANT;
BEGIN
    IF (:age >= 18) THEN
        --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
        call_results := (
            CALL DBMS_OUTPUT.PUT_LINE_UDF('You are an adult.')
        );
    ELSE
        --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
        call_results := (
            CALL DBMS_OUTPUT.PUT_LINE_UDF('You are a minor.')
        );
    END IF;
    RETURN call_results;
END;
Copy
 anonymous block
You are an adult.
Copy

2. CASE statement

Weitere Informationen finden Sie in der folgenden Dokumentation: Dokumentation SnowConvert CASE-Anweisung und der Snowflake CASE-Dokumentation

Oracle
 BEGIN
   DECLARE
      day_of_week NUMBER := 3;
   BEGIN
      CASE day_of_week
         WHEN 1 THEN DBMS_OUTPUT.PUT_LINE('Sunday');
         WHEN 2 THEN DBMS_OUTPUT.PUT_LINE('Monday');
         WHEN 3 THEN DBMS_OUTPUT.PUT_LINE('Tuesday');
         WHEN 4 THEN DBMS_OUTPUT.PUT_LINE('Wednesday');
         WHEN 5 THEN DBMS_OUTPUT.PUT_LINE('Thursday');
         WHEN 6 THEN DBMS_OUTPUT.PUT_LINE('Friday');
         WHEN 7 THEN DBMS_OUTPUT.PUT_LINE('Saturday');
         ELSE DBMS_OUTPUT.PUT_LINE('Invalid day');
      END CASE;
   END;
END;
Copy
Statement processed.
Tuesday

Copy
Snowflake

Warnung

Wenn Sie eine Prozedur oder eine benutzerdefinierte Funktion (UDF) aufrufen, müssen Sie Code generieren, um die Äquivalenz als Aufrufergebnisse-Variable zu unterstützen. Wird in diesem Fall zum Drucken der Informationen verwendet.

Überprüfen Sie die benutzerdefinierte Funktion (UDF), die [hier] verwendet wird (./built-in-packages.md#put_line-procedure).

 DECLARE
   call_results VARIANT;
BEGIN
   DECLARE
      day_of_week NUMBER(38, 18) := 3;
   BEGIN
      CASE :day_of_week
         WHEN 1 THEN
            --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
            call_results := (
               CALL DBMS_OUTPUT.PUT_LINE_UDF('Sunday')
            );
         WHEN 2 THEN
            --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
            call_results := (
               CALL DBMS_OUTPUT.PUT_LINE_UDF('Monday')
            );
         WHEN 3 THEN
            --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
            call_results := (
               CALL DBMS_OUTPUT.PUT_LINE_UDF('Tuesday')
            );
         WHEN 4 THEN
            --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
            call_results := (
               CALL DBMS_OUTPUT.PUT_LINE_UDF('Wednesday')
            );
         WHEN 5 THEN
            --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
            call_results := (
               CALL DBMS_OUTPUT.PUT_LINE_UDF('Thursday')
            );
         WHEN 6 THEN
            --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
            call_results := (
               CALL DBMS_OUTPUT.PUT_LINE_UDF('Friday')
            );
         WHEN 7 THEN
            --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
            call_results := (
               CALL DBMS_OUTPUT.PUT_LINE_UDF('Saturday')
            );
         ELSE
            --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
            call_results := (
               CALL DBMS_OUTPUT.PUT_LINE_UDF('Invalid day')
            );
      END CASE;
   END;
   RETURN call_results;
END;
Copy
 anonymous block
Tuesday
Copy

3. LOOP statements

Weitere Informationen finden Sie in der folgenden Dokumentation: SnowConvert FOR LOOP- und Snowflake LOOP-Dokumentation und der FOR- Dokumentation.

Oracle
 BEGIN
    FOR i IN 1..10 LOOP
        NULL;
    END LOOP;
END;
Copy
Statement processed.

Copy
Snowflake
 BEGIN
    FOR i IN 1 TO 10 LOOP
        NULL;
    END LOOP;
END;
Copy
anonymous block

Copy

4. Procedure call and OUTPUT parameters

Anonyme Blöcke in Oracle können Aufrufe zu Prozeduren enthalten. Außerdem kann die folgende Dokumentation nützlich sein: Dokumentation zur SnowConvert-Prozedur.

Das folgende Beispiel verwendet die OUT-Parameter. Die Informationen zur aktuellen Transformation finden Sie hier: SnowConvert OUTPUT-Parameter

Oracle
 -- Procedure declaration
CREATE OR REPLACE PROCEDURE calculate_sum(
    p_num1 IN NUMBER,
    p_num2 IN NUMBER,
    p_result OUT NUMBER
)
IS
BEGIN
    -- Calculate the sum of the two numbers
    p_result := p_num1 + p_num2;
END;
/

-- Anonymous block with a procedure call
DECLARE
    -- Declare variables to hold the input and output values
    v_num1 NUMBER := 10;
    v_num2 NUMBER := 20;
    v_result NUMBER;
BEGIN
    -- Call the procedure with the input values and get the result
    calculate_sum(v_num1, v_num2, v_result);
    
    -- Display the result
    DBMS_OUTPUT.PUT_LINE('The sum of ' || v_num1 || ' and ' || v_num2 || ' is ' || v_result);
END;
/
Copy
Statement processed.
The sum of 10 and 20 is 30

Copy
Snowflake
 -- Procedure declaration
CREATE OR REPLACE PROCEDURE calculate_sum (p_num1 NUMBER(38, 18), p_num2 NUMBER(38, 18), p_result NUMBER(38, 18)
)
RETURNS VARIANT
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
    -- Calculate the sum of the two numbers
        p_result := :p_num1 + :p_num2;
        RETURN p_result;
    END;
$$;

-- Anonymous block with a procedure call
DECLARE
    -- Declare variables to hold the input and output values
    v_num1 NUMBER(38, 18) := 10;
    v_num2 NUMBER(38, 18) := 20;
    v_result NUMBER(38, 18);
    call_results VARIANT;
BEGIN
    call_results := (
        CALL
        -- Call the procedure with the input values and get the result
        calculate_sum(:v_num1, :v_num2, :v_result)
    );
    v_result := :call_results;

    -- Display the result
    --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
    call_results := (
        CALL DBMS_OUTPUT.PUT_LINE_UDF('The sum of ' || NVL(:v_num1 :: STRING, '') || ' and ' || NVL(:v_num2 :: STRING, '') || ' is ' || NVL(:v_result :: STRING, ''))
    );
    RETURN call_results;
END;
Copy
anonymous block
The sum of 10 and 20 is 30

Copy

5. Alter session

Weitere Informationen finden Sie in der folgenden Dokumentation: Dokumentation zu Alter Session.

Beachten Sie, dass in Oracle der Block BEGIN...END die Anweisung EXECUTE IMMEDIATE verwenden sollte, um die Anweisungen Alter Session auszuführen.

Oracle
 DECLARE
     lv_sql_txt VARCHAR2(200);
BEGIN
     lv_sql_txt := 'ALTER SESSION SET nls_date_format = ''DD-MM-YYYY''';
     EXECUTE IMMEDIATE lv_sql_txt;
END;
Copy
Statement processed.
Done

Copy
Snowflake

Warnung

Die folgende Warnung kann in Zukunft hinzugefügt werden:\ /***MSC-WARNING - MSCEWI3058 - NLS_DATE_FORMAT SESSION PARAMETER DOES NOT ENFORCE THE INPUT FORMAT IN ORACLE***/

 DECLARE
     lv_sql_txt VARCHAR(200);
BEGIN
     lv_sql_txt := 'ALTER SESSION SET nls_date_format = ''DD-MM-YYYY''';
     !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!!!!RESOLVE EWI!!! /*** SSC-EWI-0027 - THE FOLLOWING STATEMENT USES A VARIABLE/LITERAL WITH AN INVALID QUERY AND IT WILL NOT BE EXECUTED ***/!!! 
     EXECUTE IMMEDIATE :lv_sql_txt;
END;
Copy
anonymous block
Done

Copy

6. Cursors

Das folgende Beispiel zeigt die Verwendung eines cursor innerhalb eines BEGIN. ..END-Blocks. Lesen Sie die folgende Dokumentation, um mehr zu erfahren: Cursor-Dokumentation.

Oracle
 CREATE TABLE employee (
    ID_Number	NUMBER,
    emp_Name	VARCHAR(200),
    emp_Phone	NUMBER
);

INSERT INTO employee VALUES (1, 'NameA NameZ', 1234567890);
INSERT INTO employee VALUES (2, 'NameB NameY', 1234567890);

DECLARE
    var1 VARCHAR(20);
    CURSOR cursor1 IS SELECT emp_Name FROM employee ORDER BY ID_Number;
BEGIN
    OPEN cursor1;
    FETCH cursor1 INTO var1;
    CLOSE cursor1;
	DBMS_OUTPUT.PUT_LINE(var1);
END;
Copy
Statement processed.
NameA NameZ

Copy
Snowflake

Warnung

Wenn Sie eine Prozedur oder eine benutzerdefinierte Funktion (UDF) aufrufen, müssen Sie Code generieren, um die Äquivalenz als Aufrufergebnisse-Variable zu unterstützen. Wird in diesem Fall zum Drucken der Informationen verwendet.

Überprüfen Sie die benutzerdefinierte Funktion (UDF), die [hier] verwendet wird (./built-in-packages.md#put_line-procedure).

 CREATE OR REPLACE TABLE employee (
	   ID_Number NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
	   emp_Name	VARCHAR(200),
	   emp_Phone NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
;

INSERT INTO employee
VALUES (1, 'NameA NameZ', 1234567890);

INSERT INTO employee
VALUES (2, 'NameB NameY', 1234567890);

DECLARE
    var1 VARCHAR(20);
	   cursor1 CURSOR
	   FOR
		SELECT emp_Name FROM
			employee
		ORDER BY ID_Number;
	   call_results VARIANT;
BEGIN
	   OPEN cursor1;
	   FETCH cursor1 INTO
		:var1;
	   CLOSE cursor1;
	   --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
	   call_results := (
		CALL DBMS_OUTPUT.PUT_LINE_UDF(:var1)
	   );
	   RETURN call_results;
END;
Copy
anonymous block
NameA NameZ

Copy

7. Select statements

Weitere Informationen finden Sie in der folgenden Dokumentation: Select-Dokumentation.

Oracle
 CREATE TABLE employee (
    ID_Number NUMBER,
    emp_Name VARCHAR(200),
    emp_Phone NUMBER
);

INSERT INTO employee VALUES (1, 'NameA NameZ', 1234567890);
INSERT INTO employee VALUES (2, 'NameB NameY', 1234567890);

DECLARE
    var_Result NUMBER;
BEGIN
    SELECT COUNT(*) INTO var_Result FROM employee;
    DBMS_OUTPUT.PUT_LINE(var_Result);
END;
Copy
Statement processed.
2

Copy
Snowflake

Warnung

Wenn Sie eine Prozedur oder eine benutzerdefinierte Funktion (UDF) aufrufen, müssen Sie Code generieren, um die Äquivalenz als Aufrufergebnisse-Variable zu unterstützen. Wird in diesem Fall zum Drucken der Informationen verwendet.

Überprüfen Sie die benutzerdefinierte Funktion (UDF), die [hier] verwendet wird (./built-in-packages.md#put_line-procedure).

 CREATE OR REPLACE TABLE employee (
       ID_Number NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
       emp_Name VARCHAR(200),
       emp_Phone NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/
   )
   COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
   ;

   INSERT INTO employee
   VALUES (1, 'NameA NameZ', 1234567890);

   INSERT INTO employee
   VALUES (2, 'NameB NameY', 1234567890);

   DECLARE
    var_Result NUMBER(38, 18);
       call_results VARIANT;
   BEGIN
       SELECT COUNT(*) INTO
           :var_Result
       FROM
           employee;
       --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
       call_results := (
           CALL DBMS_OUTPUT.PUT_LINE_UDF(:var_Result)
       );
       RETURN call_results;
   END;
Copy
anonymous block
2

Copy

8. Join Statements

Weitere Informationen finden Sie in der folgenden Dokumentation: Joins-Dokumentation.

Oracle
 CREATE TABLE t1 (col1 INTEGER);
CREATE TABLE t2 (col1 INTEGER);

INSERT INTO t1 (col1) VALUES (2);
INSERT INTO t1 (col1) VALUES (3);
INSERT INTO t1 (col1) VALUES (4);

INSERT INTO t2 (col1) VALUES (1);
INSERT INTO t2 (col1) VALUES (2);
INSERT INTO t2 (col1) VALUES (2);
INSERT INTO t2 (col1) VALUES (3);


DECLARE
    total_price FLOAT;
    CURSOR cursor1 IS SELECT t1.col1 as FirstTable, t2.col1 as SecondTable
    FROM t1 INNER JOIN t2
        ON t2.col1 = t1.col1
    ORDER BY 1,2;
BEGIN
    total_price := 0.0;
    FOR rec IN cursor1 LOOP
      total_price := total_price + rec.FirstTable;
    END LOOP;
    DBMS_OUTPUT.PUT_LINE(total_price);
END;
Copy
Statement processed.
7

Copy
Snowflake

Warnung

Wenn Sie eine Prozedur oder eine benutzerdefinierte Funktion (UDF) aufrufen, müssen Sie Code generieren, um die Äquivalenz als Aufrufergebnisse-Variable zu unterstützen. Wird in diesem Fall zum Drucken der Informationen verwendet.

Überprüfen Sie die benutzerdefinierte Funktion (UDF), die [hier] verwendet wird (./built-in-packages.md#put_line-procedure).

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

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

INSERT INTO t1(col1) VALUES (2);

INSERT INTO t1(col1) VALUES (3);

INSERT INTO t1(col1) VALUES (4);

INSERT INTO t2(col1) VALUES (1);

INSERT INTO t2(col1) VALUES (2);

INSERT INTO t2(col1) VALUES (2);

INSERT INTO t2(col1) VALUES (3);

DECLARE
    total_price FLOAT;
    cursor1 CURSOR
    FOR
        SELECT t1.col1 as FIRSTTABLE, t2.col1 as SECONDTABLE
           FROM
            t1
            INNER JOIN
                t2
               ON t2.col1 = t1.col1
           ORDER BY 1,2;
    call_results VARIANT;
BEGIN
    total_price := 0.0;
    OPEN cursor1;
    --** SSC-PRF-0004 - THIS STATEMENT HAS USAGES OF CURSOR FOR LOOP **
    FOR rec IN cursor1 DO
        total_price :=
        !!!RESOLVE EWI!!! /*** SSC-EWI-OR0036 - TYPES RESOLUTION ISSUES, ARITHMETIC OPERATION '+' MAY NOT BEHAVE CORRECTLY BETWEEN AproxNumeric AND unknown ***/!!!
        :total_price + rec.FIRSTTABLE;
    END FOR;
    CLOSE cursor1;
    --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
    call_results := (
        CALL DBMS_OUTPUT.PUT_LINE_UDF(:total_price)
    );
    RETURN call_results;
END;
Copy

9. Exception handling

Oracle
 DECLARE
      v_result NUMBER;
BEGIN
   v_result := 1 / 0;
   EXCEPTION
      WHEN ZERO_DIVIDE THEN
         DBMS_OUTPUT.PUT_LINE( SQLERRM );
END;
Copy
Statement processed.
ORA-01476: divisor is equal to zero

Copy
Snowflake

Warnung

ZERO_DIVIDE-Ausnahme wird in Snowflake nicht unterstützt.

 DECLARE
      v_result NUMBER(38, 18);
      error_results VARIANT;
BEGIN
      v_result := 1 / 0;
   EXCEPTION
      WHEN ZERO_DIVIDE THEN
      --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
      error_results := (
         CALL DBMS_OUTPUT.PUT_LINE_UDF( SQLERRM )
      );
      RETURN error_results;
END;
Copy
anonymous block
Division by zero

Copy

Bekannte Probleme

  1. Nicht unterstützte GOTO-Anweisungen in Oracle.

  2. Ausnahmen, die GOTO-Anweisungen verwenden, können ebenfalls betroffen sein.

  3. Die Cursor-Funktionalität kann im Rahmen der derzeitigen Übersetzungsbeschränkungen angepasst werden.

Zugehörige EWIs

  1. [SSC-EWI-0027](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0027):Die folgende Anweisung verwendet ein/e Variable/Literal mit einer ungültigen Abfrage und wird nicht ausgeführt.

  2. [SSC-EWI-OR0036](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0036): Probleme bei der Auflösung von Typen, die arithmetische Operation verhält sich möglicherweise nicht korrekt zwischen Zeichenfolge und Datum.

  3. [SSC-FDM-OR0035](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/oracleFDM. md#ssc-fdm-or0035): DBMS_OUTPUT.PUTLINE UDF Implementierung überprüfen.

  4. [SSC-FDM-0006](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0006): Zahlentyp-Spalte verhält sich in Snowflake möglicherweise nicht ähnlich.

  5. [SSC-PRF-0004](../../general/technical-documentation/issues-and-troubleshooting/performance-review/README. md#ssc-prf-0004): In dieser Anweisung wird eine Cursor-FOR-Schleife verwendet.

  6. [SSC-EWI-0030](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0030): Die folgende Anweisung enthält dynamische SQL-Verwendungen

CONTINUE

Beschreibung

Die Anweisung CONTINUE beendet die aktuelle Iteration einer Schleife, entweder bedingt oder bedingungslos, und übergibt die Kontrolle an die nächste Iteration entweder der aktuellen Schleife oder einer eingeschlossenen beschrifteten Schleife.\ (Oracle PL/SQL Language Reference CONTINUE Statement)

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

 CONTINUE [ label ] [ WHEN boolean_expression ] ;
Copy
 { CONTINUE | ITERATE } [ <label> ] ;
Copy

Beispielhafte Quellcode-Muster

1. Simple Continue

Der Code überspringt die Anweisung INSERT, indem er CONTINUE verwendet.

Dieser Fall ist funktionell gleichwertig.

Oracle
 CREATE TABLE continue_testing_table_1 (iterator VARCHAR2(5));

CREATE OR REPLACE PROCEDURE continue_procedure_1 
IS
I NUMBER := 0;
J NUMBER := 20;
BEGIN
    WHILE I <= J LOOP 
        I := I + 1;
        CONTINUE;
        INSERT INTO continue_testing_table_1
        VALUES (TO_CHAR(I));
    END LOOP;
END;

CALL continue_procedure_1();
SELECT * FROM continue_testing_table_1;
Copy
ITERATOR|
--------+

Copy
Snowflake Scripting
 CREATE OR REPLACE TABLE continue_testing_table_1 (iterator VARCHAR(5))
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE PROCEDURE continue_procedure_1 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        I NUMBER(38, 18) := 0;
        J NUMBER(38, 18) := 20;
    BEGIN
        WHILE (:I <= :J) LOOP
            I := :I + 1;
            CONTINUE;
            INSERT INTO continue_testing_table_1
            VALUES (TO_CHAR(:I));
        END LOOP;
    END;
$$;

CALL continue_procedure_1();

SELECT * FROM
    continue_testing_table_1;
Copy
ITERATOR|
--------+

Copy

2. Continue with condition

Der Code überspringt das Einfügen gerader Zahlen durch die Verwendung von CONTINUE.

Bemerkung

Dieser Fall ist funktionell nicht gleichwertig, aber Sie können die Bedingung in eine IF-Anweisung umwandeln.

Oracle
 CREATE TABLE continue_testing_table_2 (iterator VARCHAR2(5));

CREATE OR REPLACE PROCEDURE continue_procedure_2
IS
I NUMBER := 0;
J NUMBER := 20;
BEGIN
    WHILE I <= J LOOP
        I := I + 1;
        CONTINUE WHEN MOD(I,2) = 0;
        INSERT INTO continue_testing_table_2 VALUES(TO_CHAR(I));
    END LOOP;  
END;

CALL continue_procedure_2();
SELECT * FROM continue_testing_table_2;
Copy
ITERATOR|
--------+
1       |
3       |
5       |
7       |
9       |
11      |
13      |
15      |
17      |
19      |
21      |

Copy
Snowflake Scripting
 CREATE OR REPLACE TABLE continue_testing_table_2 (iterator VARCHAR(5))
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE PROCEDURE continue_procedure_2 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        I NUMBER(38, 18) := 0;
        J NUMBER(38, 18) := 20;
    BEGIN
        WHILE (:I <= :J) LOOP
            I := :I + 1;
            IF (MOD(:I,2) = 0) THEN
                CONTINUE;
            END IF;
            INSERT INTO continue_testing_table_2
            VALUES(TO_CHAR(:I));
        END LOOP;
    END;
$$;

CALL continue_procedure_2();

SELECT * FROM
    continue_testing_table_2;
Copy
ITERATOR|
--------+
1       |
3       |
5       |
7       |
9       |
11      |
13      |
15      |
17      |
19      |
21      |

Copy

3. Continue with label and condition

Der Code überspringt Zeile 19, und die innere Schleife wird nur einmal ausgeführt, da CONTINUE über das Label immer zur äußeren Schleife springt.

Dieser Fall ist funktionell äquivalent zur Anwendung des gleichen Prozesses wie das vorherige Beispiel.

Bemerkung

Beachten Sie, dass die Labels auskommentiert werden.

Oracle
 CREATE OR REPLACE PROCEDURE continue_procedure_3
IS
I NUMBER := 0;
J NUMBER := 10;
K NUMBER := 0;
BEGIN
    <<out_loop>>
    WHILE I <= J LOOP
        I := I + 1;
        INSERT INTO continue_testing_table_3 VALUES('I' || TO_CHAR(I));

        <<in_loop>>
        WHILE K <= J * 2 LOOP
            K := K + 1;
            CONTINUE out_loop WHEN K > J / 2;
            INSERT INTO continue_testing_table_3 VALUES('K' || TO_CHAR(K));
        END LOOP in_loop;

        K := 0;
    END LOOP out_loop; 
END;

CALL continue_procedure_3();
SELECT * FROM continue_testing_table_3;
Copy
ITERATOR|
--------+
I1      |
K1      |
K2      |
K3      |
K4      |
K5      |
I2      |
I3      |
I4      |
I5      |
I6      |
I7      |
I8      |
I9      |
I10     |
I11     |

Copy
Snowflake Scripting
 CREATE OR REPLACE PROCEDURE continue_procedure_3 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        I NUMBER(38, 18) := 0;
        J NUMBER(38, 18) := 10;
        K NUMBER(38, 18) := 0;
    BEGIN
        !!!RESOLVE EWI!!! /*** SSC-EWI-0094 - LABEL DECLARATION FOR A STATEMENT IS NOT SUPPORTED BY SNOWFLAKE SCRIPTING <<out_loop>> ***/!!!
        WHILE (:I <= :J) LOOP
            I := :I + 1;
                   INSERT INTO continue_testing_table_3
            VALUES('I' || NVL(TO_CHAR(:I) :: STRING, ''));
            !!!RESOLVE EWI!!! /*** SSC-EWI-0094 - LABEL DECLARATION FOR A STATEMENT IS NOT SUPPORTED BY SNOWFLAKE SCRIPTING <<in_loop>> ***/!!!
            WHILE (:K <= :J * 2) LOOP
                K := :K + 1;
                IF (:K > :J / 2) THEN
                    CONTINUE out_loop;
                END IF;
                       INSERT INTO continue_testing_table_3
                VALUES('K' || NVL(TO_CHAR(:K) :: STRING, ''));
                   END LOOP in_loop;
            K := 0;
               END LOOP out_loop;
    END;
$$;

CALL continue_procedure_3();

SELECT * FROM
    continue_testing_table_3;
Copy
ITERATOR|
--------+
I1      |
K1      |
K2      |
K3      |
K4      |
K5      |
I2      |
I3      |
I4      |
I5      |
I6      |
I7      |
I8      |
I9      |
I10     |
I11     |

Copy

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIs

  1. [SSC-EWI-0094](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0094): Label-Deklaration wird nicht unterstützt.

CREATE PROCEDURE

Beschreibung

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

Eine Prozedur ist eine Gruppe von PL/SQL-Anweisungen, die Sie mit einem Namen aufrufen können. Eine Aufrufspezifikation (manchmal auch Call spec genannt) deklariert eine Java-Methode oder eine Routine der dritten Generation (3GL) so, dass sie von SQL und PL/SQL aufgerufen werden kann. Die Aufrufspezifikation teilt der Oracle-Datenbank mit, welche Java-Methode bei einem Aufruf aufgerufen werden soll. Sie teilt der Datenbank auch mit, welche Typkonvertierungen für die Argumente und den Rückgabewert vorgenommen werden sollen. Oracle SQL Language Reference Create Procedure.

Weitere Informationen zu Oracle Create Procedure finden Sie hier.

 CREATE [ OR REPLACE ] [ EDITIONABLE | NONEDITIONABLE ]
PROCEDURE
[ schema. ] procedure_name
[ ( parameter_declaration [, parameter_declaration ]... ) ] [ sharing_clause ]
[ ( default_collation_option | invoker_rights_clause | accessible_by_clause)... ] 
{ IS | AS } { [ declare_section ] 
    BEGIN statement ...
    [ EXCEPTION exception_handler [ exception_handler ]... ]
    END [ name ] ;
      |
    { java_declaration | c_declaration } } ;
Copy

Weitere Informationen zu Snowflake Create Procedure finden Sie hier.

 CREATE [ OR REPLACE ] PROCEDURE <name> ( [ <arg_name> <arg_data_type> ] [ , ... ] )
  RETURNS <result_data_type> [ NOT NULL ]
  LANGUAGE SQL
  [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
  [ VOLATILE | IMMUTABLE ]
  [ COMMENT = '<string_literal>' ]
  [ EXECUTE AS { CALLER | OWNER } ]
  AS '<procedure_definition>'
Copy

Beispielhafte Quellcode-Muster

1. Basic Procedure

 CREATE OR REPLACE PROCEDURE PROC1
IS
BEGIN
null;
END;
Copy
 CREATE OR REPLACE PROCEDURE PROC1 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
BEGIN
null;
END;
$$;
Copy

2. Procedure with Different Parameters

 CREATE OR REPLACE PROCEDURE proc2
(
    p1 OUT INTEGER,
    p2 OUT INTEGER,
    p3 INTEGER := 1,
    p4 INTEGER DEFAULT 1
)
AS
BEGIN
	p1 := 17;
	p2 := 93;
END;
Copy
 CREATE OR REPLACE PROCEDURE proc2
(p1 INTEGER, p2 INTEGER,
    p3 INTEGER DEFAULT 1,
    p4 INTEGER DEFAULT 1
)
RETURNS VARIANT
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
	BEGIN
		p1 := 17;
		p2 := 93;
		RETURN OBJECT_CONSTRUCT('p1', :p1, 'p2', :p2);
	END;
$$;
Copy
Ausgabeparameter

Snowflake erlaubt keine Ausgabeparameter in Prozeduren. Eine Möglichkeit, diese Verhaltensweise zu simulieren, könnte darin bestehen, eine Variable zu deklarieren und ihren Wert am Ende der Prozedur zurückzugeben.

Parameter mit Standardwerten

Snowflake erlaubt es nicht, Standardwerte für Parameter in Prozeduren zu setzen. Eine Möglichkeit, diese Verhaltensweise zu simulieren, könnte darin bestehen, eine Variable mit dem Standardwert zu deklarieren oder die Prozedur zu überladen.

3. Procedure with Additional Settings

 CREATE OR REPLACE PROCEDURE proc3
DEFAULT COLLATION USING_NLS_COMP
AUTHID CURRENT_USER
AS
BEGIN
NULL;
END;
Copy
 CREATE OR REPLACE PROCEDURE proc3 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "oracle",  "convertedOn": "11/14/2024",  "domain": "test" }}'
EXECUTE AS CALLER
AS
$$
BEGIN
NULL;
END;
$$;
Copy

4. Procedure with Basic Statements

 CREATE OR REPLACE PROCEDURE proc4
(
  param1 NUMBER
)
IS
  localVar1 NUMBER;
  countRows NUMBER;
  tempSql VARCHAR(100);
  tempResult NUMBER;
  CURSOR MyCursor IS SELECT COL1 FROM Table1;

BEGIN
    localVar1 := param1;
    countRows := 0;
    tempSql := 'SELECT COUNT(*) FROM Table1 WHERE COL1 =' || localVar1;

    FOR myCursorItem IN MyCursor
        LOOP
            localVar1 := myCursorItem.Col1;
            countRows := countRows + 1; 
        END LOOP;
    INSERT INTO Table2 VALUES(countRows, 'ForCursor: Total Row count is: ' || countRows);
    countRows := 0;

    OPEN MyCursor;
    LOOP
        FETCH MyCursor INTO tempResult;
        EXIT WHEN MyCursor%NOTFOUND;
        countRows := countRows + 1;
    END LOOP;
    CLOSE MyCursor;
    INSERT INTO Table2 VALUES(countRows, 'LOOP: Total Row count is: ' || countRows);

    EXECUTE IMMEDIATE tempSql INTO tempResult;
    IF tempResult > 0 THEN 
        INSERT INTO Table2 (COL1, COL2) VALUES(tempResult, 'Hi, found value:' || localVar1 || ' in Table1 -- There are ' || tempResult || ' rows');
        COMMIT;
    END IF;
END proc3;
Copy
 CREATE OR REPLACE PROCEDURE proc4
(param1 NUMBER(38, 18)
)
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    localVar1 NUMBER(38, 18);
    countRows NUMBER(38, 18);
    tempSql VARCHAR(100);
    tempResult NUMBER(38, 18);
    MyCursor CURSOR
    FOR
      SELECT COL1 FROM
        Table1;
  BEGIN
    localVar1 := :param1;
    countRows := 0;
    tempSql := 'SELECT COUNT(*) FROM
   Table1
WHERE COL1 =' || NVL(:localVar1 :: STRING, '');
    OPEN MyCursor;
    --** SSC-PRF-0004 - THIS STATEMENT HAS USAGES OF CURSOR FOR LOOP **
    FOR myCursorItem IN MyCursor DO
      localVar1 := myCursorItem.Col1;
      countRows := :countRows + 1;
    END FOR;
    CLOSE MyCursor;
    INSERT INTO Table2
    VALUES(:countRows, 'ForCursor: Total Row count is: ' || NVL(:countRows :: STRING, ''));
    countRows := 0;
    OPEN MyCursor;
    LOOP
      --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
      FETCH MyCursor INTO
        :tempResult;
      IF (tempResult IS NULL) THEN
        EXIT;
      END IF;
      countRows := :countRows + 1;
    END LOOP;
    CLOSE MyCursor;
    INSERT INTO Table2
    SELECT
      :countRows,
      'LOOP: Total Row count is: ' || NVL(:countRows :: STRING, '');
!!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!

    EXECUTE IMMEDIATE :tempSql
                               !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'EXECUTE IMMEDIATE RETURNING CLAUSE' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
                               INTO tempResult;
    IF (:tempResult > 0) THEN
      INSERT INTO Table2(COL1, COL2)
      SELECT
        :tempResult,
        'Hi, found value:' || NVL(:localVar1 :: STRING, '') || ' in Table1 -- There are ' || NVL(:tempResult :: STRING, '') || ' rows';
      --** SSC-FDM-OR0012 - COMMIT REQUIRES THE APPROPRIATE SETUP TO WORK AS INTENDED **
      COMMIT;
    END IF;
  END;
$$;
Copy

5. Procedure with empty RETURN statements

In Oracle-Prozeduren können Sie leere RETURN-Anweisungen haben, um die Ausführung einer Prozedur zu beenden. In Snowflake Scripting können Prozeduren RETURN-Anweisungen haben, aber sie müssen einen Wert haben. Standardmäßig werden alle leeren RETURN-Anweisungen mit einem NULL Wert konvertiert.

 -- Procedure with empty return
CREATE OR REPLACE PROCEDURE MY_PROC
IS
BEGIN
   NULL;
   RETURN;
END;
Copy
 -- Procedure with empty return
CREATE OR REPLACE PROCEDURE MY_PROC ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
   BEGIN
      NULL;
      RETURN NULL;
   END;
$$;
Copy
RETURN-Anweisungen in Prozeduren mit Ausgabeparametern

In Prozeduren mit Ausgabeparametern wird anstelle eines NULL-Wertes ein OBJECT_CONSTRUCT in den leeren RETURN-Anweisungen verwendet, um die Ausgabeparameter in Snowflake Scripting zu simulieren.

 CREATE OR REPLACE PROCEDURE PROC_WITH_OUTPUT_PARAMETERS (
    param1 OUT NUMBER,
    param2 OUT NUMBER,
    param3 NUMBER
)
IS
BEGIN 
    IF param3 > 0 THEN
        param1 := 2;
        param2 := 1000;
        RETURN;
    END IF;
    param1 := 5;
    param2 := 3000;
END;
Copy
 CREATE OR REPLACE PROCEDURE PROC_WITH_OUTPUT_PARAMETERS (param1 NUMBER(38, 18), param2 NUMBER(38, 18), param3 NUMBER(38, 18)
)
RETURNS VARIANT
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        IF (:param3 > 0) THEN
            param1 := 2;
            param2 := 1000;
            RETURN OBJECT_CONSTRUCT('param1', :param1, 'param2', :param2);
        END IF;
        param1 := 5;
        param2 := 3000;
        RETURN OBJECT_CONSTRUCT('param1', :param1, 'param2', :param2);
    END;
$$;
Copy

6. Procedure with DEFAULT parameters

DEFAULT-Parameter können benannte Parameter mit Standardwerten initialisiert werden, wenn kein Wert übergeben wird.

 CREATE OR REPLACE PROCEDURE TEST(
    X IN VARCHAR DEFAULT 'P',
    Y IN VARCHAR DEFAULT 'Q'
)
AS 
    varX VARCHAR(32767) := NVL(X, 'P');
    varY NUMBER := NVL(Y, 1);
BEGIN
    NULL;
END TEST;

BEGIN
    TEST(Y => 'Y');
END;
Copy
 CREATE OR REPLACE PROCEDURE TEST (
    X VARCHAR DEFAULT 'P',
    Y VARCHAR DEFAULT 'Q'
)
    RETURNS VARCHAR
    LANGUAGE SQL
    COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
    EXECUTE AS CALLER
    AS
    $$
        DECLARE
            varX VARCHAR(32767) := NVL(:X, 'P');
            varY NUMBER(38, 18) := NVL(:Y, 1 :: STRING);
        BEGIN
            NULL;
        END;
    $$;

    DECLARE
        call_results VARIANT;
    BEGIN
        CALL
        TEST(Y => 'Y');
        RETURN call_results;
    END;
Copy

Bekannte Probleme

1. Unsupported OUT parameters

Snowflake-Prozeduren verfügen nicht über eine native Option für Ausgabeparameter.

2. Unsupported Oracle additional settings

Die folgenden Oracle-Einstellungen und -Klauseln werden von Snowflake-Prozeduren nicht unterstützt:

  • sharing_clause

  • default_collation_option

  • invoker_rights_clause

  • accessible_by_clause

  • java_declaration

  • c_declaration

Zugehörige EWIS

  1. [SSC-EWI-0058](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0058): Die Funktionalität wird derzeit nicht von Snowflake Scripting unterstützt

  2. [SSC-EWI-OR0097](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0097): Prozedureigenschaften werden in Snowflake-Prozeduren nicht unterstützt.

  3. [SSC-FDM-OR0012: ](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/oracleFDM. md#ssc-fdm-or0012) COMMIT- und ROLLBACK-Anweisungen erfordern eine angemessene Einrichtung, um wie vorgesehen zu funktionieren.

  4. [SSC-PRF-0003](../../general/technical-documentation/issues-and-troubleshooting/performance-review/README. md#ssc-prf-0003): Fetch innerhalb einer Schleife wird als komplexes Muster betrachtet, was die Leistung von Snowflake beeinträchtigen kann.

  5. [SSC-PRF-0004](../../general/technical-documentation/issues-and-troubleshooting/performance-review/README. md#ssc-prf-0004): In dieser Anweisung wird eine Cursor-FOR-Schleife verwendet.

  6. [SSC-EWI-0030](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0030): Die folgende Anweisung enthält dynamische SQL-Verwendungen

DECLARE

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

Beschreibung

Die Oracle DECLARE-Anweisung ist ein optionaler Teil der PL/SQL Blockanweisung. Es ermöglicht die Erstellung von Variablen, Konstanten, Prozedurendeklarationen und -definitionen, Funktionsdeklarationen und -definitionen, Ausnahmen, Cursors, Typen und vielen anderen Anweisungen. Weitere Informationen zu Oracle DECLARE finden Sie hier.

 declare_section body

declare_section::= { item_list_1 [ item_list_2 ] | item_list_2 }

item_list_1::= 
{ type_definition
| cursor_declaration
| item_declaration
| function_declaration
| procedure_declaration
}
 ...
 
item_list_2::=
{ cursor_declaration
| cursor_definition
| function_declaration
| function_definition
| procedure_declaration
| procedure_definition
}
 ...

item_declaration::=
{ collection_variable_decl
| constant_declaration
| cursor_variable_declaration
| exception_declaration
| record_variable_declaration
| variable_declaration
}

body::= BEGIN statement ...
  [ EXCEPTION exception_handler [ exception_handler ]... ] END [ name ] ;
Copy
 [ DECLARE
  { <variable_declaration> | <cursor_declaration> | <exception_declaration> | <resultset_declaration> }
  [, { <variable_declaration> | <cursor_declaration> | <exception_declaration> | <resultset_declaration> } ... ]
]
BEGIN
    <statement>;
    [ <statement>; ... ]
[ EXCEPTION <exception_handler> ]
END [ <label> ] ;
Copy

Beispielhafte Quellcode-Muster

Variablendeklaration

 variable_declaration::= 
variable datatype [ [ NOT NULL] {:= | DEFAULT} expression ] ;
Copy
 <variable_name> <type>;

<variable_name> DEFAULT <expression> ;

<variable_name> <type> DEFAULT <expression> ;
Copy
Oracle
 CREATE OR REPLACE PROCEDURE var_decl_proc
IS
var1 NUMBER; 
var2 NUMBER := 1;
var3 NUMBER NOT NULL := 1;
var4 NUMBER DEFAULT 1;
var5 NUMBER NOT NULL DEFAULT 1;
BEGIN
    NULL; 
END;
Copy
Snowflake Scripting
 CREATE OR REPLACE PROCEDURE var_decl_proc ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        var1 NUMBER(38, 18);
        var2 NUMBER(38, 18) := 1;
        var3 NUMBER(38, 18) := 1 /*** SSC-FDM-OR0025 - NOT NULL CONSTRAINT IS NOT SUPPORTED BY SNOWFLAKE ***/;
        var4 NUMBER(38, 18) DEFAULT 1;
        var5 NUMBER(38, 18) DEFAULT 1 /*** SSC-FDM-OR0025 - NOT NULL CONSTRAINT IS NOT SUPPORTED BY SNOWFLAKE ***/;
    BEGIN
        NULL;
    END;
$$;
Copy

Konstanten-Deklaration

Warnung

Konstanten werden in Snowflake Scripting nicht unterstützt, aber sie werden in Variablen umgewandelt, um die Verhaltensweise zu simulieren.

 constant_declaration::=
constant CONSTANT datatype [NOT NULL] { := | DEFAULT } expression ;
Copy
 <variable_name> <type>;

<variable_name> DEFAULT <expression> ;

<variable_name> <type> DEFAULT <expression> ; 
Copy
Oracle
 CREATE OR REPLACE PROCEDURE const_decl_proc
IS
my_const1 CONSTANT NUMBER := 40;
my_const2 CONSTANT NUMBER NOT NULL := 40;
my_const2 CONSTANT NUMBER DEFAULT 40;
my_const2 CONSTANT NUMBER NOT NULL DEFAULT 40;
BEGIN
    NULL; 
END;
Copy
Snowflake Scripting
 CREATE OR REPLACE PROCEDURE const_decl_proc ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        --** SSC-FDM-0016 - CONSTANTS ARE NOT SUPPORTED BY SNOWFLAKE SCRIPTING. IT WAS TRANSFORMED TO A VARIABLE **
        my_const1 NUMBER(38, 18) := 40;
        --** SSC-FDM-0016 - CONSTANTS ARE NOT SUPPORTED BY SNOWFLAKE SCRIPTING. IT WAS TRANSFORMED TO A VARIABLE **
        --** SSC-FDM-OR0025 - NOT NULL CONSTRAINT IS NOT SUPPORTED BY SNOWFLAKE **
        my_const2 NUMBER(38, 18) := 40;
        --** SSC-FDM-0016 - CONSTANTS ARE NOT SUPPORTED BY SNOWFLAKE SCRIPTING. IT WAS TRANSFORMED TO A VARIABLE **
        my_const2 NUMBER(38, 18) DEFAULT 40;
        --** SSC-FDM-0016 - CONSTANTS ARE NOT SUPPORTED BY SNOWFLAKE SCRIPTING. IT WAS TRANSFORMED TO A VARIABLE **
        --** SSC-FDM-OR0025 - NOT NULL CONSTRAINT IS NOT SUPPORTED BY SNOWFLAKE **
        my_const2 NUMBER(38, 18) DEFAULT 40;
    BEGIN
        NULL;
    END;
$$;
Copy

Cursordeklaration

 cursor_declaration::= CURSOR cursor
  [( cursor_parameter_dec [, cursor_parameter_dec ]... )]
    RETURN rowtype;

cursor_parameter_dec::= parameter [IN] datatype [ { := | DEFAULT } expression ]

rowtype::= 
{ {db_table_or_view | cursor | cursor_variable}%ROWTYPE
  | record%TYPE
  | record_type
  }
Copy
 <cursor_name> CURSOR [ ( <argument> [, <argument> ... ] ) ]
        FOR <query> ;
Copy

Die Oracle _ Cursordeklaration _ ist nicht erforderlich, so dass sie im Ausgabecode auskommentiert werden kann. Die _ Cursordefinition _ wird anstelle von verwendet und in die Snowflake Scripting _ Cursordeklaration _ umgewandelt. Lesen Sie bitte den Abschnitt CURSOR um weitere Informationen über die Cursordefinition zu erhalten.

Ausnahmedeklaration

Auf die Ausnahmendeklaration kann manchmal auch die Initialisierung der Ausnahme folgen. Die aktuelle Transformation nimmt beide und fügt sie in die Snowflake Scripting-Ausnahmendeklaration ein. Das Original PRAGMA EXCEPTION_INIT wird auskommentiert.

 exception_declaration::= exception EXCEPTION;

PRAGMA EXCEPTION_INIT ( exception, error_code ) ;
Copy
 <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
Copy
Oracle
 CREATE OR REPLACE PROCEDURE procedure_exception
IS
my_exception EXCEPTION;
my_exception2 EXCEPTION;
PRAGMA EXCEPTION_INIT ( my_exception2, -20100 );
my_exception3 EXCEPTION;
PRAGMA EXCEPTION_INIT ( my_exception3, -19000 );
BEGIN
    NULL; 
END;
Copy
Snowflake Scripting
 CREATE OR REPLACE PROCEDURE procedure_exception ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        my_exception EXCEPTION;
        my_exception2 EXCEPTION (-20100, '');
        !!!RESOLVE EWI!!! /*** SSC-EWI-OR0051 - PRAGMA EXCEPTION_INIT IS NOT SUPPORTED ***/!!!
        PRAGMA EXCEPTION_INIT ( my_exception2, -20100 );
        !!!RESOLVE EWI!!! /*** SSC-EWI-OR0099 - EXCEPTION CODE NUMBER EXCEEDS SNOWFLAKE SCRIPTING LIMITS ***/!!!
        my_exception3 EXCEPTION;
        !!!RESOLVE EWI!!! /*** SSC-EWI-OR0051 - PRAGMA EXCEPTION_INIT IS NOT SUPPORTED ***/!!!
PRAGMA EXCEPTION_INIT ( my_exception3, -19000 );
    BEGIN
        NULL;
    END;
$$;
Copy

Nicht unterstützte Fälle

Die folgenden Oracle-Deklarationsanweisungen werden vom Snowflake Scripting-Deklarationsblock nicht unterstützt:

  1. Deklaration von Cursorvariablen

  2. Deklaration von Sammlungsvariablen

  3. Deklaration von Datensatzvariablen

  4. Typdefinition (alle Varianten)

  5. Deklaration und Definition von Funktionen

  6. Deklaration und Definition von Prozeduren

Known issues

1. The variable declarations with NOT NULL constraints are not supported by Snow Scripting.

Die Erstellung von Variablen mit der Einschränkung NOT NULL führt in Snow Scripting zu einem Fehler.

2. The cursor declaration has no equivalent to Snowflake Scripting.

Die Oracle-Cursordeklaration ist nutzlos, daher kann sie im Ausgabecode auskommentiert werden. Die Cursordefinition wird stattdessen verwendet und in die Snowflake Scripting Cursordeklaration umgewandelt.

3. The exception code exceeds Snowflake Scripting limits.

Der Oracle-Ausnahmecode wird entfernt, wenn er die Grenzen des Snowflake Scripting-Codes überschreitet. Der Ausnahmecode muss eine Ganzzahl zwischen -20000 und -20999 sein.

3. The not supported cases.

Es gibt einige Oracle-Deklarationsanweisungen, die vom Snowflake Scripting-Deklarationsblock nicht unterstützt werden, so dass sie möglicherweise auskommentiert werden und eine Warnung hinzugefügt wird.

Related EWIS

  1. [SSC-EWI-OR0051](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0051): PRAGMA EXCEPTION_INIT wird nicht unterstützt.

  2. [SSC-EWI-OR0099](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0099): Der Ausnahmecode überschreitet das Snowflake Scripting-Limit.

  3. [SSC-FDM-0016](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0016): Konstanten werden von Snowflake Scripting nicht unterstützt. Sie wurden in eine Variable umgewandelt.

  4. [SSC-FDM-OR0025](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/oracleFDM. md#ssc-fdm-or0025): Die Nicht-Null-Einschränkung wird in Snowflake-Prozeduren nicht unterstützt.

DEFAULT PARAMETERS

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

Beschreibung

Ein Standardparameter ist ein Parameter, der einen Wert hat, falls ein Argument in der Prozedur oder dem Funktionsaufruf nicht übergeben wird. Da Snowflake keine Standardparameter unterstützt, fügt SnowConvert den Standardwert in den Aufruf der Prozedur oder Funktion ein.

In der Deklaration wird die DEFAULT VALUE-Klausel des Parameters entfernt. Beide Syntaxen, das Symbol : = und die Klausel DEFAULT werden unterstützt.

Beispielhafte Quellcode-Muster

Beispiel für Hilfscode

 CREATE TABLE TABLE1(COL1 NUMBER, COL2 NUMBER);
CREATE TABLE TABLE2(COL1 NUMBER, COL2 NUMBER, COL2 NUMBER);0016
Copy
 CREATE OR REPLACE TABLE TABLE1 (COL1 NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
COL2 NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE TABLE TABLE2 (COL1 NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
COL2 NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
COL2 NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;
Copy

Standardparameter-Deklaration

Oracle
 CREATE OR REPLACE PROCEDURE PROC_WITH_DEFAULT_PARAMS1 (
    param1 NUMBER,
    param2 NUMBER default TO_NUMBER(1)
)
AS
BEGIN 
	INSERT INTO TABLE1 (COL1, COL2)
    VALUES(param1, param2);
END;
CREATE OR REPLACE PROCEDURE PROC_WITH_DEFAULT_PARAMS2 (
    param1 NUMBER default 1,
    param2 NUMBER default 2
)
AS
BEGIN 
	INSERT INTO TABLE1 (COL1, COL2)
    VALUES(param1, param2);
END;

CREATE OR REPLACE PROCEDURE PROCEDURE_WITH_DEAFAULT_PARAMS3 (
    param1 NUMBER DEFAULT 100,
    param2 NUMBER,
    param3 NUMBER DEFAULT 1000
)
IS
BEGIN
	INSERT INTO TABLE2(COL1, COL2, COL3)
    VALUES (param1, param2, param3);
END;
Copy
Snowflake Scripting
 CREATE OR REPLACE PROCEDURE PROC_WITH_DEFAULT_PARAMS1 (param1 NUMBER(38, 18),
   param2 NUMBER(38, 18) DEFAULT TO_NUMBER(1)
)
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
	BEGIN
		INSERT INTO TABLE1(COL1, COL2)
		   VALUES(:param1, :param2);
	END;
$$;

CREATE OR REPLACE PROCEDURE PROC_WITH_DEFAULT_PARAMS2 (
   param1 NUMBER(38, 18) DEFAULT 1,
   param2 NUMBER(38, 18) DEFAULT 2
)
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
	BEGIN
		INSERT INTO TABLE1(COL1, COL2)
		   VALUES(:param1, :param2);
	END;
$$;

CREATE OR REPLACE PROCEDURE PROCEDURE_WITH_DEAFAULT_PARAMS3 (
   param1 NUMBER(38, 18) DEFAULT 100, param2 NUMBER(38, 18),
   param3 NUMBER(38, 18) DEFAULT 1000
)
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
	BEGIN
		INSERT INTO TABLE2(COL1, COL2, COL3)
		   VALUES (:param1, :param2, :param3);
	END;
$$;
Copy

Aufrufen von Prozeduren mit Standardparametern

Oracle
 CREATE OR REPLACE PROCEDURE PROC_WITH_DEFAULT_CALLS
AS
BEGIN 
    PROC_WITH_DEFAULT_PARAMS1(10, 15);
    PROC_WITH_DEFAULT_PARAMS1(10);
    PROC_WITH_DEFAULT_PARAMS2(10, 15);
    PROC_WITH_DEFAULT_PARAMS2(10);
    PROC_WITH_DEFAULT_PARAMS2();
END;
Copy
Snowflake Scripting
 CREATE OR REPLACE PROCEDURE PROC_WITH_DEFAULT_CALLS ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        CALL
        PROC_WITH_DEFAULT_PARAMS1(10, 15);
        CALL
        PROC_WITH_DEFAULT_PARAMS1(10);
        CALL
        PROC_WITH_DEFAULT_PARAMS2(10, 15);
        CALL
        PROC_WITH_DEFAULT_PARAMS2(10);
        CALL
        PROC_WITH_DEFAULT_PARAMS2();
    END;
$$;
Copy

Um zu überprüfen, ob die Funktionalität korrekt emuliert wird, führt die folgende Abfrage die Prozedur und SELECT aus der zuvor erwähnten Tabelle aus.

Oracle
 CALL PROC_WITH_DEFAULT_CALLS();

SELECT * FROM TABLE1;
Copy
|COL1|COL2|
|----|----|
|10  |15  |
|10  |1   |
|10  |15  |
|10  |2   |
|1   |2   |


Copy
Snowflake Scripting
 CALL PROC_WITH_DEFAULT_CALLS();

SELECT * FROM TABLE1;
Copy
|COL1|COL2|
|----|----|
|10  |15  |
|10  |1   |
|10  |15  |
|10  |2   |
|1   |2   |


Copy

Aufrufen von Prozeduren mit benannten Argumenten und Standardparametern

Oracle
 CREATE OR REPLACE PROCEDURE PROC_WITH_DEFAULT_CALLS2
AS
BEGIN 
    PROCEDURE_WITH_DEAFAULT_PARAMS3(10, 20, 30);
    PROCEDURE_WITH_DEAFAULT_PARAMS3(param1 => 10, param2 => 20, param3 => 30);
    PROCEDURE_WITH_DEAFAULT_PARAMS3(param3 => 10, param1 => 20, param2 => 30);
    PROCEDURE_WITH_DEAFAULT_PARAMS3(param3 => 10, param2 => 30);
    PROCEDURE_WITH_DEAFAULT_PARAMS3(param2 => 10, param3 => 30);
    PROCEDURE_WITH_DEAFAULT_PARAMS3(param2 => 10);
END;
Copy
Snowflake Scripting
 CREATE OR REPLACE PROCEDURE PROC_WITH_DEFAULT_CALLS2 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        CALL
        PROCEDURE_WITH_DEAFAULT_PARAMS3(10, 20, 30);
        CALL
        PROCEDURE_WITH_DEAFAULT_PARAMS3(10, 20, 30);
        CALL
        PROCEDURE_WITH_DEAFAULT_PARAMS3(10, 20, 30);
        CALL
        PROCEDURE_WITH_DEAFAULT_PARAMS3(10, 30);
        CALL
        PROCEDURE_WITH_DEAFAULT_PARAMS3(10, 30);
        CALL
        PROCEDURE_WITH_DEAFAULT_PARAMS3(10);
    END;
$$;
Copy

Um zu überprüfen, ob die Funktionalität korrekt emuliert wird, führt die folgende Abfrage die Prozedur und SELECT aus der zuvor erwähnten Tabelle aus.

Oracle
 CALL PROC_WITH_DEFAULT_CALLS2();

SELECT * FROM TABLE2;
Copy
|COL1|COL2|COL3|
|----|----|----|
|10  |20  |30  |
|10  |20  |30  |
|20  |30  |10  |
|100 |30  |10  |
|100 |10  |30  |
|100 |10  |1000|


Copy
Snowflake Scripting
 CALL PROC_WITH_DEFAULT_CALLS2();

SELECT * FROM TABLE2;
Copy
|COL1|COL2|COL3|
|----|----|----|
|10  |20  |30  |
|10  |20  |30  |
|20  |30  |10  |
|100 |30  |10  |
|100 |10  |30  |
|100 |10  |1000|


Copy

Bekannte Probleme

1. Keine Probleme gefunden

Zugehörige EWIs

Keine zugehörigen EWIs.

EXECUTE IMMEDIATE

Beschreibung

Die Anweisung EXECUTE IMMEDIATE erstellt und führt eine dynamische Anweisung SQL in einer einzigen Operation aus.

Native dynamische SQL verwendet die Anweisung EXECUTE IMMEDIATE, um die meisten dynamischen SQL-Anweisungen zu verarbeiten. (Oracle PL/SQL Language Reference EXECUTE IMMEDIATE Statement)

 EXECUTE IMMEDIATE <dynamic statement> [<additional clause> , ...];

dynamic statement::= { '<string literal>' | <variable> }

additional clauses::=
{ <into clause> [<using clause>]
| <bulk collect into clause> [<using clause>]
| <using clause> [<dynamic return clause>]
| <dynamic return clasue> }
Copy

Snowflake Scripting unterstützt diese Anweisung, wenn auch mit einigen funktionalen Unterschieden. Weitere Informationen über das Snowflake-Pendant finden Sie in der Snowflake-Dokumentation EXECUTE IMMEDIATE.

 EXECUTE IMMEDIATE <dynamic statement> ;

dynamic statement::= {'<string literal>' | <variable> | $<session variable>}
Copy

Beispielhafte Quellcode-Muster

In den nächsten Beispielen wird eine Tabelle erstellt und versucht, die Tabelle mit Execute Immediate zu löschen.

Verwendung einer fest codierten Zeichenfolge

Oracle
 CREATE TABLE immediate_dropped_table(
    col1 INTEGER
);

CREATE OR REPLACE PROCEDURE dropping_procedure
AS BEGIN
    EXECUTE IMMEDIATE 'DROP TABLE immediate_dropped_table PURGE';
END;

CALL dropping_procedure();
SELECT * FROM immediate_dropped_table;
Copy
Snowflake Scripting
 CREATE OR REPLACE TABLE immediate_dropped_table (
    col1 INTEGER
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE PROCEDURE dropping_procedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
        EXECUTE IMMEDIATE 'DROP TABLE immediate_dropped_table';
    END;
$$;

CALL dropping_procedure();

SELECT * FROM
    immediate_dropped_table;
Copy

Speichern der Zeichenfolge in einer Variablen

Oracle
 CREATE TABLE immediate_dropped_table(
    col1 INTEGER
);

CREATE OR REPLACE PROCEDURE dropping_procedure
AS
BEGIN
    DECLARE
        statement_variable VARCHAR2(500) := 'DROP TABLE immediate_dropped_table PURGE';
    BEGIN
        EXECUTE IMMEDIATE statement_variable;
    END;
END;

CALL dropping_procedure();
SELECT * FROM immediate_dropped_table;
Copy
Snowflake Scripting
 CREATE OR REPLACE TABLE immediate_dropped_table (
    col1 INTEGER
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE PROCEDURE dropping_procedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        DECLARE
            statement_variable VARCHAR(500) := 'DROP TABLE immediate_dropped_table';
        BEGIN
            !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
            EXECUTE IMMEDIATE :statement_variable;
        END;
    END;
$$;

CALL dropping_procedure();

SELECT * FROM
    immediate_dropped_table;
Copy

Verkettung für Parameter in dynamischen Anweisungen

Oracle
 CREATE TABLE immediate_dropped_table(
    col1 INTEGER
);

CREATE OR REPLACE PROCEDURE dropping_procedure(param1 VARCHAR2)
AS
BEGIN
    DECLARE
        statement_variable VARCHAR2(500) := 'DROP TABLE ' || param1 || ' PURGE';
    BEGIN
        EXECUTE IMMEDIATE statement_variable;
    END;
END;

CALL dropping_procedure();
SELECT * FROM immediate_dropped_table;
Copy
Snowflake Scripting
 CREATE OR REPLACE TABLE immediate_dropped_table (
    col1 INTEGER
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE PROCEDURE dropping_procedure (param1 VARCHAR)
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        DECLARE
            statement_variable VARCHAR(500) := 'DROP TABLE ' || NVL(:param1 :: STRING, '');
        BEGIN
            !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
            EXECUTE IMMEDIATE :statement_variable;
        END;
    END;
$$;

CALL dropping_procedure();

SELECT * FROM
    immediate_dropped_table;
Copy

Transformation der USING-Klausel

Oracle
 CREATE TABLE immediate_inserted_table(COL1 INTEGER);

CREATE OR REPLACE PROCEDURE inserting_procedure_using(param1 INTEGER)
AS
BEGIN
    EXECUTE IMMEDIATE 'INSERT INTO immediate_inserted_table VALUES (:1)' USING param1;
END;

CALL inserting_procedure_using(1);

SELECT * FROM immediate_inserted_table;
Copy
COL1|
----+
   1|

Copy
Snowflake Scripting

Bemerkung

Bitte beachten Sie, dass Parameter in der USING-Klausel in Snowflake Scripting in Klammern gesetzt werden müssen.

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

CREATE OR REPLACE PROCEDURE inserting_procedure_using (param1 INTEGER)
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
        EXECUTE IMMEDIATE 'INSERT INTO immediate_inserted_table
VALUES (?)' USING ( param1);
    END;
$$;

CALL inserting_procedure_using(1);

SELECT * FROM
    immediate_inserted_table;
Copy
COL1|
----+
   1|

Copy

Bekannte Probleme

1. Immediate Execution results cannot be stored in variables.

SnowScripting unterstützt weder INTO- noch BULK COLLECT INTO-Klauseln. Aus diesem Grund müssen die Ergebnisse auf anderem Wege übermittelt werden.

2. Numeric Placeholders

Numerische Namen für Platzhalter werden derzeit von SnowConvert nicht erkannt. Es gibt jedoch ein Work-Element zur Behebung dieses Problems.

3. Argument Expressions are not supported by Snowflake Scripting

In Oracle ist es möglich, Ausdrücke als Argumente für die verwendende Klausel zu verwenden. Dies wird jedoch von Snowflake Scripting nicht unterstützt und ist daher auskommentiert.

4. Dynamic SQL Execution queries may be marked incorrectly as non-runnable.

In einigen Szenarien kann eine Ausführungsanweisung unabhängig davon, ob sie sicher oder nicht sicher ist, kommentiert werden. Bitte berücksichtigen Sie dies:

Oracle
 CREATE OR REPLACE PROCEDURE inserting_procedure_variable_execute_concatenation_parameter(param1 INTEGER)
IS
    query VARCHAR2(500) := 'INSERT INTO immediate_inserted_table VALUES (';
BEGIN
    EXECUTE IMMEDIATE query || param1 || ')';
END;
Copy
Snowflake Scripting

Bemerkung

Bitte beachten Sie, dass Parameter in der USING-Klausel in Snowflake Scripting in Klammern gesetzt werden müssen.

CREATE OR REPLACE PROCEDURE inserting_procedure_variable_execute_concatenation_parameter (param1 INTEGER)
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
    DECLARE
        query VARCHAR(500) := 'INSERT INTO immediate_inserted_table VALUES (';
    BEGIN
        !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
        !!!RESOLVE EWI!!! /*** SSC-EWI-0027 - THE FOLLOWING STATEMENT USES A VARIABLE/LITERAL WITH AN INVALID QUERY AND IT WILL NOT BE EXECUTED ***/!!!
        EXECUTE IMMEDIATE NVL(:query :: STRING, '') || NVL(:param1 :: STRING, '') || ')';
    END;
$$;
Copy

Zugehörige EWIs

  1. [SSC-EWI-0027](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0027): Variable mit ungültiger Abfrage.

  2. [SSC-EWI-0030](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0030): Die nachstehende Anweisung enthält Verwendungen von dynamischen SQL.

EXIT

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

Beschreibung

Die Anweisung EXIT beendet die aktuelle Iteration einer Schleife, entweder bedingt oder bedingungslos, und übergibt die Kontrolle entweder an das Ende der aktuellen Schleife oder an das Ende einer umschließenden beschrifteten Schleife.\ (Oracle PL/SQL Language Reference EXIT Statement)

 EXIT [ label ] [ WHEN boolean_expression ] ;
Copy
 { BREAK | EXIT } [ <label> ] ;
Copy

Beispielhafte Quellcode-Muster

Bemerkung

Beachten Sie, dass Sie EXITmit BREAKändern können und alles wie gewohnt funktioniert.

1. Simple Exit

Der Code überspringt die Anweisung INSERT, indem er EXIT verwendet.

Dieser Fall ist funktionell gleichwertig.

Oracle
 CREATE TABLE exit_testing_table_1 (
    iterator VARCHAR2(5)
);

CREATE OR REPLACE PROCEDURE exit_procedure_1
IS
I NUMBER := 0;
J NUMBER := 20;
BEGIN
    WHILE I <= J LOOP
        I := I + 1;
        EXIT;
        INSERT INTO exit_testing_table_1 VALUES(TO_CHAR(I));
    END LOOP;  
END;

CALL exit_procedure_1();
SELECT * FROM exit_testing_table_1;
Copy
ITERATOR|
--------+

Copy
Snowflake Scripting
 CREATE OR REPLACE TABLE exit_testing_table_1 (
       iterator VARCHAR(5)
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE PROCEDURE exit_procedure_1 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        I NUMBER(38, 18) := 0;
        J NUMBER(38, 18) := 20;
    BEGIN
        WHILE (:I <= :J) LOOP
            I := :I + 1;
            EXIT;
            INSERT INTO exit_testing_table_1
            VALUES(TO_CHAR(:I));
        END LOOP;
    END;
$$;

CALL exit_procedure_1();

SELECT * FROM
    exit_testing_table_1;
Copy
ITERATOR|
--------+

Copy

2. Exit with condition

Der Code verlässt die Schleife, wenn der Iterator größer als 5 ist.

Dieser Fall ist funktionell gleichwertig, indem die Bedingung in eine IF- Anweisung umgewandelt wird.

Oracle
 CREATE TABLE exit_testing_table_2 (
    iterator VARCHAR2(5)
);

CREATE OR REPLACE PROCEDURE exit_procedure_2
IS
I NUMBER := 0;
J NUMBER := 20;
BEGIN
    WHILE I <= J LOOP
        EXIT WHEN I > 5;
        I := I + 1;
        INSERT INTO exit_testing_table_2 VALUES(TO_CHAR(I)); 
    END LOOP;  
END;

CALL exit_procedure_2();
SELECT * FROM exit_testing_table_2;
Copy
ITERATOR|
--------+
1       |
2       |
3       |
4       |
5       |
6       |

Copy
Snowflake Scripting
 CREATE OR REPLACE TABLE exit_testing_table_2 (
       iterator VARCHAR(5)
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE PROCEDURE exit_procedure_2 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        I NUMBER(38, 18) := 0;
        J NUMBER(38, 18) := 20;
    BEGIN
        WHILE (:I <= :J) LOOP
            IF (:I > 5) THEN
                EXIT;
            END IF;
            I := :I + 1;
            INSERT INTO exit_testing_table_2
            VALUES(TO_CHAR(:I));
        END LOOP;
    END;
$$;

CALL exit_procedure_2();

SELECT * FROM
    exit_testing_table_2;
Copy
ITERATOR|
--------+
1       |
2       |
3       |
4       |
5       |
6       |

Copy

3. Exit with label and condition

Der Code unterbricht beide Schleifen, indem er die Anweisung EXIT verwendet, die auf die äußere Schleife verweist.

Dieser Fall ist funktionell äquivalent zur Anwendung des gleichen Prozesses wie das vorherige Beispiel.

Bemerkung

Beachten Sie, dass die Labels auskommentiert werden.

Oracle
 CREATE TABLE exit_testing_table_3 (
    iterator VARCHAR2(5)
);

CREATE OR REPLACE PROCEDURE exit_procedure_3
IS
I NUMBER := 0;
J NUMBER := 10;
K NUMBER := 0;
BEGIN
    <<out_loop>>
    WHILE I <= J LOOP
        I := I + 1;
        INSERT INTO exit_testing_table_3 VALUES('I' || TO_CHAR(I));

        <<in_loop>>
        WHILE K <= J * 2 LOOP
            K := K + 1;    
                EXIT out_loop WHEN K > J / 2;
            INSERT INTO exit_testing_table_3 VALUES('K' || TO_CHAR(K));
        END LOOP in_loop; 

        K := 0;
    END LOOP out_loop; 
END;

CALL exit_procedure_3();
SELECT * FROM exit_testing_table_3;
Copy
ITERATOR|
--------+
I1      |
K1      |
K2      |
K3      |
K4      |
K5      |

Copy
Snowflake Scripting
 CREATE OR REPLACE TABLE exit_testing_table_3 (
       iterator VARCHAR(5)
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE PROCEDURE exit_procedure_3 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        I NUMBER(38, 18) := 0;
        J NUMBER(38, 18) := 10;
        K NUMBER(38, 18) := 0;
    BEGIN
        !!!RESOLVE EWI!!! /*** SSC-EWI-0094 - LABEL DECLARATION FOR A STATEMENT IS NOT SUPPORTED BY SNOWFLAKE SCRIPTING <<out_loop>> ***/!!!
        WHILE (:I <= :J) LOOP
            I := :I + 1;
                   INSERT INTO exit_testing_table_3
            VALUES('I' || NVL(TO_CHAR(:I) :: STRING, ''));
            !!!RESOLVE EWI!!! /*** SSC-EWI-0094 - LABEL DECLARATION FOR A STATEMENT IS NOT SUPPORTED BY SNOWFLAKE SCRIPTING <<in_loop>> ***/!!!
            WHILE (:K <= :J * 2) LOOP
                K := :K + 1;
                IF (:K > :J / 2) THEN
                    EXIT out_loop;
                END IF;
                       INSERT INTO exit_testing_table_3
                VALUES('K' || NVL(TO_CHAR(:K) :: STRING, ''));
                   END LOOP in_loop;
            K := 0;
               END LOOP out_loop;
    END;
$$;

CALL exit_procedure_3();

SELECT * FROM
    exit_testing_table_3;
Copy
ITERATOR|
--------+
I1      |
K1      |
K2      |
K3      |
K4      |
K5      |

Copy

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIs

  1. [SSC-EWI-0094](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0094): Label-Deklaration wird nicht unterstützt.

EXPRESSIONS

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

Beschreibung

In der folgenden Tabelle finden Sie eine Zusammenfassung, wie Sie die verschiedenen Oracle-Ausdruckstypen in Snow Scripting umwandeln können.

Syntax

Status der Konvertierung

Notizen

Zeichenausdrücke

Teilweise

Teilweise unterstützte allgemeine Szenarien

Numerische Ausdrücke

Teilweise

Teilweise unterstützte allgemeine Szenarien

Date Expressions

Teilweise

Teilweise unterstützte allgemeine Szenarien

Boolesche Ausdrücke

Teilweise

Nicht unterstützte boolesche Ausdrücke

Simple CASE-Ausdrücke

Voll

N/A

Searched CASE-Ausdrücke

Voll

N/A

Collection Constructor

Nicht übersetzt

Snowflake verfügt nicht über ein natives Äquivalent für Oracle-Sammlungen. Siehe Sammlungen und Datensätze.

Qualifizierte Ausdrücke

Nicht übersetzt

Snowflake verfügt nicht über eine native Entsprechung für Oracle-Datensatztypen. Siehe Sammlungen und Datensätze.

Teilweise unterstützte gemeinsame Szenarien

Oracle-Konstanten

Weitere Informationen finden Sie unter Oracle-Konstantendeklaration.

Oracle
 CREATE TABLE EXPRESSIONS_TABLE(col VARCHAR(30));
CREATE OR REPLACE PROCEDURE EXPRESSIONS_SAMPLE
IS
RESULT VARCHAR(50);
CONST CONSTANT VARCHAR(20) := 'CONSTANT TEXT';
BEGIN
	-- CONSTANT EXPRESSIONS
	RESULT := CONST;
	INSERT INTO EXPRESSIONS_TABLE(COL) VALUES (RESULT);
END;

CALL EXPRESSIONS_SAMPLE();
SELECT * FROM EXPRESSIONS_TABLE;
Copy
|COL          |
|-------------|
|CONSTANT TEXT|


Copy
Snowflake
 CREATE OR REPLACE TABLE EXPRESSIONS_TABLE (col VARCHAR(30))
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE PROCEDURE EXPRESSIONS_SAMPLE ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
	DECLARE
		RESULT VARCHAR(50);
		--** SSC-FDM-0016 - CONSTANTS ARE NOT SUPPORTED BY SNOWFLAKE SCRIPTING. IT WAS TRANSFORMED TO A VARIABLE **
		CONST VARCHAR(20) := 'CONSTANT TEXT';
	BEGIN
		-- CONSTANT EXPRESSIONS
		RESULT := :CONST;
		INSERT INTO EXPRESSIONS_TABLE(COL) VALUES (:RESULT);
	END;
$$;

CALL EXPRESSIONS_SAMPLE();

SELECT * FROM
	EXPRESSIONS_TABLE;
Copy
|COL          |
|-------------|
|CONSTANT TEXT|


Copy

Nicht unterstützte numerische Ausdrücke

Oracle
 CREATE TABLE NUMERIC_EXPRESSIONS_TABLE(col number);

CREATE OR REPLACE PROCEDURE NUMERIC_EXPRESSIONS
IS
RESULT NUMBER;
CURSOR C1 IS SELECT * FROM NUMERIC_EXPRESSIONS_TABLE;
TYPE NUMERIC_TABLE IS TABLE OF NUMBER(10);
COLLECTION NUMERIC_TABLE; 
BEGIN
	-- CURSOR EXPRESSIONS
	OPEN C1;
	RESULT := C1%ROWCOUNT;
	CLOSE C1;
	INSERT INTO NUMERIC_EXPRESSIONS_TABLE(COL) VALUES (RESULT);
	
	-- ** OPERATOR
	RESULT := 10 ** 2;
	INSERT INTO NUMERIC_EXPRESSIONS_TABLE(COL) VALUES (RESULT);
	
	-- COLLECTION EXPRESSIONS
	COLLECTION := NUMERIC_TABLE(1, 2, 3, 4, 5, 6); 
	RESULT := COLLECTION.COUNT + COLLECTION.FIRST;
	INSERT INTO NUMERIC_EXPRESSIONS_TABLE(COL) VALUES (RESULT);

	-- IMPLICIT CURSOR EXPRESSIONS
	UPDATE NUMERIC_EXPRESSIONS_TABLE SET COL = COL + 4;
	RESULT := SQL%ROWCOUNT;
	INSERT INTO NUMERIC_EXPRESSIONS_TABLE(COL) VALUES (RESULT);
END;

CALL NUMERIC_EXPRESSIONS();
SELECT * FROM NUMERIC_EXPRESSIONS_TABLE;
Copy
|COL|
|---|
|4  |
|104|
|11 |
|3  |

Copy

Nicht unterstützte boolesche Ausdrücke

Oracle
 --Aux function to convert BOOLEAN to VARCHAR
CREATE OR REPLACE FUNCTION convert_bool(p1 in BOOLEAN)
RETURN VARCHAR
AS
var1 VARCHAR(20) := 'FALSE';
BEGIN
IF p1 THEN
var1 := 'TRUE';
END IF;
RETURN var1;
END;

--Table
CREATE TABLE t_boolean_table
(
conditional_predicate VARCHAR(20),
collection_variable VARCHAR(20),
sql_variable VARCHAR(20)
)

--Main Procedure
CREATE OR REPLACE PROCEDURE p_boolean_limitations
AS

TYPE varray_example IS VARRAY(4) OF VARCHAR(15);
colection_example varray_example := varray_example('John', 'Mary', 'Alberto', 'Juanita');
collection_variable BOOLEAN;
conditional_predicate BOOLEAN;
sql_variable BOOLEAN;

--Result variables
col1 VARCHAR(20);
col2 VARCHAR(20);
col3 VARCHAR(20);
BEGIN

--Conditional predicate
conditional_predicate := INSERTING;

--Collection.EXISTS(index)
collection_variable := colection_example.EXISTS(2);

--Cursor FOUND / NOTFOUND / ISOPEN
sql_variable:= SQL%FOUND OR SQL%NOTFOUND OR SQL%ISOPEN;

--Convert BOOLEAN to VARCHAR to insert
col1 := convert_bool(conditional_predicate);
col2 := convert_bool(collection_variable);
col3 := convert_bool(sql_variable);

INSERT INTO t_boolean_table VALUES (col1, col2, col3);

END;

CALL p_boolean_limitations();

SELECT * FROM t_boolean_table;
Copy

Zugehörige EWIs.

  1. [SSC-FDM-0016](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0016): Konstanten werden von Snowflake Scripting nicht unterstützt. Sie wurden in eine Variable umgewandelt.

FOR LOOP

Beschreibung

Bei jeder Iteration der Anweisung FOR LOOP werden die Anweisungen ausgeführt, der Index wird entweder erhöht oder verringert und die Kontrolle kehrt an den Anfang der Schleife zurück. (Oracle PL/SQL Language Reference FOR LOOP Statement).

 FOR
pls_identifier [ MUTABLE | IMMUTABLE ] [ constrained_type ]
[ , iterand_decl ]

IN

[ REVERSE ] iteration_control pred_clause_seq
[, qual_iteration_ctl]...

LOOP
statement... 
END LOOP [ label ] ;
Copy
 FOR <counter_variable> IN [ REVERSE ] <start> TO <end> { DO | LOOP }
    statement;
    [ statement; ... ]
END { FOR | LOOP } [ <label> ] ;
Copy

Snowflake Scripting unterstützt FOR LOOP, das eine bestimmte Anzahl von Schleifen durchläuft. Die Ober- und Untergrenzen müssen INTEGER sein. Weitere Informationen finden Sie in der Snowflake Scripting-Dokumentation.

Die Verhaltensweise von Oracle FOR LOOP kann auch durch die Verwendung der Anweisungen geändert werden:

Beispielhafte Quellcode-Muster

1. FOR LOOP

Dieser Fall ist funktionell gleichwertig.

 CREATE OR REPLACE PROCEDURE P1
AS
BEGIN
    FOR i IN 1..10
    LOOP
        NULL;
    END LOOP;

    FOR i IN VAR1..VAR2
    LOOP
        NULL;
    END LOOP; 

    FOR i IN REVERSE 1+2..10+5
    LOOP
        NULL;
    END LOOP; 
END;
Copy
 CREATE OR REPLACE PROCEDURE P1 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        FOR i IN 1 TO 10 LOOP
            NULL;
        END LOOP;
        FOR i IN VAR1 TO VAR2 LOOP
            NULL;
        END LOOP;
        FOR i IN REVERSE 1+2 TO 10+5 LOOP
            NULL;
        END LOOP;
    END;
$$;
Copy

2. FOR LOOP with additional clauses

 CREATE OR REPLACE PROCEDURE P2
AS
BEGIN
    FOR i IN 1..10 WHILE i <= 5 LOOP
        NULL;
    END LOOP;

    FOR i IN 5..15 BY 5 LOOP
        NULL;
    END LOOP;
END;
Copy
 CREATE OR REPLACE PROCEDURE P2 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        !!!RESOLVE EWI!!! /*** SSC-EWI-OR0101 - FOR LOOP WITH "WHILE" CLAUSE IS CURRENTLY NOT SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
        FOR i IN 1 TO 10 LOOP
            NULL;
        END LOOP;
        !!!RESOLVE EWI!!! /*** SSC-EWI-OR0101 - FOR LOOP WITH "BY" CLAUSE IS CURRENTLY NOT SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
        FOR i IN 5 TO 15 LOOP
            NULL;
        END LOOP;
    END;
$$;
Copy

3. FOR LOOP with multiple conditions

 CREATE OR REPLACE PROCEDURE P3
AS
BEGIN
    FOR i IN REVERSE 1..3,
    REVERSE i+5..i+7
    LOOP
        NULL;
    END LOOP; 
END;
Copy
 CREATE OR REPLACE PROCEDURE P3 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        !!!RESOLVE EWI!!! /*** SSC-EWI-OR0100 - FOR LOOP WITH MULTIPLE CONDITIONS IS CURRENTLY NOT SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
        FOR i IN REVERSE 1 TO 3 LOOP
            NULL;
        END LOOP;
    END;
$$;
Copy

4. FOR LOOP with unsupported format

 CREATE OR REPLACE PROCEDURE P3
AS
TYPE values_aat IS TABLE OF PLS_INTEGER INDEX BY PLS_INTEGER;
l_employee_values   values_aat;
BEGIN
    FOR power IN REPEAT power*2 WHILE power <= 64 LOOP
        NULL;
    END LOOP;

    FOR i IN VALUES OF l_employee_values LOOP
        NULL;
    END LOOP; 
END;
Copy
 CREATE OR REPLACE PROCEDURE P3 ()
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 values_aat IS TABLE OF PLS_INTEGER INDEX BY PLS_INTEGER;
        l_employee_values VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-0062 - CUSTOM TYPE 'values_aat' USAGE CHANGED TO VARIANT ***/!!!;
    BEGIN
        !!!RESOLVE EWI!!! /*** SSC-EWI-OR0103 - FOR LOOP FORMAT IS CURRENTLY NOT SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!!!!RESOLVE EWI!!! /*** SSC-EWI-OR0101 - FOR LOOP WITH "WHILE" CLAUSE IS CURRENTLY NOT SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
        FOR power IN REPEAT power*2 WHILE power <= 64 LOOP
            NULL;
        END LOOP;
        !!!RESOLVE EWI!!! /*** SSC-EWI-OR0103 - FOR LOOP FORMAT IS CURRENTLY NOT SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!

        FOR i IN VALUES OF :l_employee_values LOOP
            NULL;
        END LOOP;
    END;
$$;
Copy

Warnung

Die Transformation für benutzerdefinierte Typen wird für Snowflake Scripting derzeit nicht unterstützt.

Bekannte Probleme

1. For With Multiple Conditions

Oracle erlaubt mehrere Bedingungen in einer einzigen FOR LOOP, Snowflake Scripting hingegen erlaubt nur eine Bedingung pro FOR LOOP. Nur die erste Bedingung wird migriert und die anderen werden bei der Transformation ignoriert. Prüfen Sie SSC-FDM-OR0022.

 FOR i IN REVERSE 1..3,
REVERSE i+5..i+7
LOOP
    NULL;
END LOOP;
Copy
 --** SSC-FDM-OR0022 - FOR LOOP WITH MULTIPLE CONDITIONS IS CURRENTLY NOT SUPPORTED BY SNOWFLAKE SCRIPTING **
FOR i IN REVERSE 1 TO 3 LOOP
    NULL;
END LOOP;
Copy

2. Veränderliche vs. unveränderliche Zählervariable

Oracle erlaubt es, den Wert der Variable FOR LOOP innerhalb der Schleife zu ändern. Die aktuelle Dokumentation enthält diese Funktion, aber Snowflake empfiehlt, dies zu vermeiden. Das Ändern des Werts dieser Variable kann zu fehlerhaften Ergebnissen bei Snowflake Scripting führen.

3. Ganzzahl vs. Float-Zahl für Ober- oder Untergrenze

Snowflake Scripting erlaubt nur einen INTEGER oder einen Ausdruck, der zu einem INTEGER ausgewertet wird, als Begrenzung für die Bedingung FOR LOOP. Fließende Zahlen werden auf- oder abgerundet und verändern die ursprüngliche Grenze. Prüfen Sie SSC-EWI-OR0102.

4. Von Oracle nicht unterstützte Klauseln

Oracle erlaubt zusätzliche Klauseln zur FOR LOOP-Bedingung. Wie die BY-Klausel für eine schrittweise Erhöhung in der Bedingung. Und die WHILE- und WHEN-Klausel für boolesche Ausdrücke. Diese zusätzlichen Klauseln werden in Snowflake Scripting nicht unterstützt und werden bei der Transformation ignoriert. Prüfen Sie [SSC-EWI-OR0101](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0101).

 FOR i IN 5..15 BY 5 LOOP
    NULL;
END LOOP;
Copy
 !!!RESOLVE EWI!!! /*** SSC-EWI-OR0101 - FOR LOOP WITH "BY" CLAUSE IS CURRENTLY NOT SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
FOR i IN 5 TO 15 LOOP
    NULL;
END LOOP;
Copy

5. Nicht unterstützte Formate

Oracle erlaubt verschiedene Arten von Bedingungen für eine FOR LOOP. Es unterstützt boolesche Ausdrücke, Sammlungen, Datensätze… Snowflake Scripting unterstützt jedoch nur FOR LOOP mit definierten Ganzzahlen als Begrenzungen. Alle anderen Formate sind als nicht unterstützt gekennzeichnet und erfordern zusätzlichen manuellen Aufwand für die Transformation. Prüfen Sie [SSC-EWI-OR0103](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0103).

Zugehörige EWIs

  1. [SSC-EWI-0058](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0058): Die Funktionalität wird derzeit nicht von Snowflake Scripting unterstützt.

  2. [SSC-EWI-0062](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0062): Benutzerdefinierte Typverwendung auf Variante geändert.

  3. [SSC-EWI-OR0100](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0100): FOR-Schleife mit mehreren Bedingungen wird derzeit von Snowflake Scripting nicht unterstützt. Nur der erste Zustand wird verwendet.

  4. [SSC-EWI-OR0101](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0101): Eine bestimmte FOR-Schleife-Klausel wird derzeit nicht von Snowflake Scripting unterstützt.

  5. [SSC-EWI-OR0103](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0103): Das FOR-Schleife-Format wird derzeit nicht von Snowflake Scripting unterstützt.

FORALL

Beschreibung

Die Anweisung FORALL führt eine Anweisung DML mehrfach aus, mit unterschiedlichen Werten in den VALUES- und WHERE-Klauseln. (Oracle PL/SQL Language Reference FORALL Statement).

FORALL index IN bounds_clause [ SAVE ] [ EXCEPTIONS ] dml_statement ;
Copy

Warnung

Snowflake Scripting ist nicht direkt gleichwertig mit der Anweisung FORALL, kann aber mit verschiedenen Umgehungsmöglichkeiten emuliert werden, um eine funktionale Gleichwertigkeit zu erreichen.

Beispielhafte Quellcode-Muster

Datenkonfiguration

Oracle
 CREATE TABLE table1 (
    column1 NUMBER,
    column2 NUMBER
);

INSERT INTO table1 (column1, column2) VALUES (1, 2);
INSERT INTO table1 (column1, column2) VALUES (2, 3);
INSERT INTO table1 (column1, column2) VALUES (3, 4);
INSERT INTO table1 (column1, column2) VALUES (4, 5);
INSERT INTO table1 (column1, column2) VALUES (5, 6);

CREATE TABLE table2 (
    column1 NUMBER,
    column2 NUMBER
);

INSERT INTO table2 (column1, column2) VALUES (1, 2);
Copy
 CREATE TABLE error_table (
    ORA_ERR_NUMBER$ NUMBER,
    ORA_ERR_MESG$ VARCHAR2(2000),
    ORA_ERR_ROWID$ ROWID,
    ORA_ERR_OPTYP$ VARCHAR2(2),
    ORA_ERR_TAG$ VARCHAR2(2000)
);

--departments
CREATE TABLE parent_table( 
    Id   INT PRIMARY KEY, 
    Name VARCHAR2(10) 
);
INSERT INTO parent_table VALUES (10, 'IT');
INSERT INTO parent_table VALUES (20, 'HR');
INSERT INTO parent_table VALUES (30, 'INFRA');

--employees
CREATE TABLE source_table(
  Id INT PRIMARY KEY,
  Name VARCHAR2(20) NOT NULL,
  DepartmentID INT REFERENCES parent_table(Id)
);
INSERT INTO source_table VALUES (101, 'Anurag111111111', 10); 
INSERT INTO source_table VALUES (102, 'Pranaya11111111', 20); 
INSERT INTO source_table VALUES (103, 'Hina11111111111', 30);

--a copy of source
CREATE TABLE target_table(
  Id INT PRIMARY KEY,
  Name VARCHAR2(10) NOT NULL,
  DepartmentID INT REFERENCES parent_table(Id)
);

INSERT INTO target_table VALUES (101, 'Anurag', 10);
Copy
Snowflake
 CREATE OR REPLACE TABLE table1 (
    column1 NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
    column2 NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

INSERT INTO table1(column1, column2) VALUES (1, 2);

INSERT INTO table1(column1, column2) VALUES (2, 3);

INSERT INTO table1(column1, column2) VALUES (3, 4);

INSERT INTO table1(column1, column2) VALUES (4, 5);

INSERT INTO table1(column1, column2) VALUES (5, 6);

CREATE OR REPLACE TABLE table2 (
    column1 NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
    column2 NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

INSERT INTO table2(column1, column2) VALUES (1, 2);
Copy
 CREATE OR REPLACE TABLE error_table (
  "ORA_ERR_NUMBER$" NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
  "ORA_ERR_MESG$" VARCHAR(2000),
  "ORA_ERR_ROWID$" VARCHAR(18) !!!RESOLVE EWI!!! /*** SSC-EWI-0036 - ROWID DATA TYPE CONVERTED TO VARCHAR ***/!!!,
  "ORA_ERR_OPTYP$" VARCHAR(2),
  "ORA_ERR_TAG$" VARCHAR(2000)
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

--departments
CREATE OR REPLACE TABLE parent_table (
      Id   INT PRIMARY KEY,
      Name VARCHAR(10)
  )
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

INSERT INTO parent_table
VALUES (10, 'IT');

INSERT INTO parent_table
VALUES (20, 'HR');

INSERT INTO parent_table
VALUES (30, 'INFRA');

--employees
CREATE OR REPLACE TABLE source_table (
  Id INT PRIMARY KEY,
  Name VARCHAR(20) NOT NULL,
  DepartmentID INT REFERENCES parent_table (Id)
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

INSERT INTO source_table
VALUES (101, 'Anurag111111111', 10);

INSERT INTO source_table
VALUES (102, 'Pranaya11111111', 20);

INSERT INTO source_table
VALUES (103, 'Hina11111111111', 30);

--a copy of source
CREATE OR REPLACE TABLE target_table (
  Id INT PRIMARY KEY,
  Name VARCHAR(10) NOT NULL,
  DepartmentID INT REFERENCES parent_table (Id)
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

INSERT INTO target_table
VALUES (101, 'Anurag', 10);
Copy

1. FORALL With Collection of Records

Oracle

Die drei folgenden Fälle haben die gleiche Transformation zu Snowflake Scripting und sind funktional gleichwertig.

 CREATE OR REPLACE PROCEDURE myProcedure IS
    CURSOR cursorVariable IS SELECT * FROM table1;
    TYPE tableType IS TABLE OF cursorVariable%ROWTYPE;
    tableVariable tableType;
BEGIN
    OPEN cursorVariable;
    LOOP
        FETCH cursorVariable BULK COLLECT INTO tableVariable LIMIT 100;
        EXIT WHEN tableVariable.COUNT = 0;

        FORALL forIndex IN 1..tableVariable.COUNT
            INSERT INTO table2 (column1, column2)
            VALUES (tableVariable(forIndex).column1, tableVariable(forIndex).column2);
    END LOOP;
    CLOSE cursorVariable;
END;
Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	2|
       1|       2|
       2|       3|
       3|       4|
       4|       5|
       5|       6|

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        INSERT INTO table2(column1, column2)
        (
            SELECT
                column1,
                column2
            FROM
                table1
        );
    END;
$$;
Copy
             COLUMN1|	             COLUMN2|
--------------------+-----------------------+
1.000000000000000000|	2.000000000000000000|
1.000000000000000000|	2.000000000000000000|
2.000000000000000000|	3.000000000000000000|
3.000000000000000000|	4.000000000000000000|
4.000000000000000000|	5.000000000000000000|
5.000000000000000000|	6.000000000000000000|

Copy

Bemerkung

Die EWIs SSC-PRF-0001 und SSC-PRF-0003 werden in jedem FETCH BULK COLLECT-Vorkommen in die FORALL-Anweisung eingefügt.

2. FORALL With INSERT INTO

Oracle
 CREATE OR REPLACE PROCEDURE myProcedure IS
    CURSOR cursorVariable IS
        SELECT * FROM table1;
    TYPE collectionTypeDefinition IS TABLE OF table1%ROWTYPE;
    collectionVariable collectionTypeDefinition;
BEGIN
    OPEN cursorVariable;
    LOOP
        FETCH cursorVariable BULK COLLECT INTO collectionVariable limit 2;
        EXIT WHEN collectionVariable.COUNT = 0;
        FORALL forIndex IN collectionVariable.FIRST..collectionVariable.LAST
            INSERT INTO table2 VALUES collectionVariable(forIndex);
        collectionVariable.DELETE;
    END LOOP;
    CLOSE cursorVariable;
END;
Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	2|
       1|       2|
       2|       3|
       3|       4|
       4|       5|
       5|       6|

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        INSERT INTO table2
        (
            SELECT
                * FROM
                table1
        );
    END;
$$;
Copy
             COLUMN1|	             COLUMN2|
--------------------+-----------------------+
1.000000000000000000|	2.000000000000000000|
1.000000000000000000|	2.000000000000000000|
2.000000000000000000|	3.000000000000000000|
3.000000000000000000|	4.000000000000000000|
4.000000000000000000|	5.000000000000000000|
5.000000000000000000|	6.000000000000000000|

Copy

3. FORALL With Multiple Fetched Collections

Oracle
 CREATE OR REPLACE PROCEDURE myProcedure IS
    CURSOR cursorVariable IS
        SELECT * FROM table1;
    column1Collection dbms_sql.NUMBER_table;
    column2Collection dbms_sql.NUMBER_table;
BEGIN
    OPEN cursorVariable;
    LOOP
        FETCH cursorVariable BULK COLLECT INTO column1Collection, column2Collection limit 20;
        EXIT WHEN column1Collection.COUNT = 0;
        FORALL forIndex IN 1..column1Collection.COUNT
            INSERT INTO table2 VALUES (
                column1Collection(forIndex),
                column2Collection(forIndex)
            );
    END LOOP;
    CLOSE cursorVariable;
END;
Copy
 CREATE OR REPLACE PROCEDURE myProcedure IS
    CURSOR cursorVariable IS
        SELECT * FROM table1;
    column1Collection dbms_sql.NUMBER_table;
    column2Collection dbms_sql.NUMBER_table;
BEGIN
    OPEN cursorVariable;
    LOOP
        FETCH cursorVariable BULK COLLECT INTO column1Collection, column2Collection limit 2;
        EXIT WHEN column1Collection.COUNT = 0;
        FORALL forIndex IN 1..column1Collection.COUNT
            UPDATE table2 SET column2 = column2Collection(forIndex)
            WHERE column1 = column1Collection(forIndex);
    END LOOP;
    CLOSE cursorVariable;
END;
Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	2|
       2|       3|
       3|       4|
       4|       5|
       5|       6|
       1|       2|

Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	2|

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        INSERT INTO table2
        (
            SELECT
                $1,
                $2
            FROM
                table1
        );
    END;
$$;
Copy
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        UPDATE table2
            SET column2 = column1Collection.$2
            FROM
                (
                    SELECT
                        * FROM
                        table1) AS column1Collection
            WHERE
                column1 = column1Collection.$1;
    END;
$$;
Copy
             COLUMN1|	             COLUMN2|
--------------------+-----------------------+
1.000000000000000000|	2.000000000000000000|
1.000000000000000000|	2.000000000000000000|
2.000000000000000000|	3.000000000000000000|
3.000000000000000000|	4.000000000000000000|
4.000000000000000000|	5.000000000000000000|
5.000000000000000000|	6.000000000000000000|

Copy
             COLUMN1|	             COLUMN2|
--------------------+-----------------------+
1.000000000000000000|	2.000000000000000000|

Copy

4. FORALL With Record of Collections

Oracle
 CREATE OR REPLACE PROCEDURE myProcedure IS
    CURSOR cursorVariable IS
        SELECT * FROM table1;
    TYPE recordType IS RECORD(
        column1Collection dbms_sql.NUMBER_table,
        column2Collection dbms_sql.NUMBER_table
    );
    columnRecord recordType;
BEGIN
    OPEN cursorVariable;
    LOOP
        FETCH cursorVariable BULK COLLECT INTO columnRecord.column1Collection, columnRecord.column2Collection limit 20;
        FORALL forIndex IN 1..columnRecord.column1Collection.COUNT
            INSERT INTO table2 VALUES (
                columnRecord.column1Collection(forIndex),
                columnRecord.column2Collection(forIndex)
            );
        EXIT WHEN cursorVariable%NOTFOUND;
    END LOOP;
    CLOSE cursorVariable;
END;
Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	2|
       1|       2|
       2|       3|
       3|       4|
       4|       5|
       5|       6|

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        INSERT INTO table2
        (
            SELECT
                $1,
                $2
            FROM
                table1
        );
    END;
$$;
Copy
             COLUMN1|	             COLUMN2|
--------------------+-----------------------+
1.000000000000000000|	2.000000000000000000|
1.000000000000000000|	2.000000000000000000|
2.000000000000000000|	3.000000000000000000|
3.000000000000000000|	4.000000000000000000|
4.000000000000000000|	5.000000000000000000|
5.000000000000000000|	6.000000000000000000|

Copy

5. FORALL With Dynamic SQL

Oracle
 CREATE OR REPLACE PROCEDURE myProcedure IS
    cursorVariable SYS_REFCURSOR;
    TYPE collectionTypeDefinition IS
        TABLE OF table1%ROWTYPE;
    collectionVariable collectionTypeDefinition;
    query VARCHAR(200) := 'SELECT * FROM table1';
BEGIN
    OPEN cursorVariable FOR query;
    LOOP
        FETCH cursorVariable BULK COLLECT INTO collectionVariable;
        EXIT WHEN collectionVariable.COUNT = 0;
        FORALL forIndex IN collectionVariable.FIRST..collectionVariable.LAST
            INSERT INTO table2 VALUES collectionVariable(forIndex);
        collectionVariable.DELETE;
    END LOOP;
    CLOSE cursorVariable;
END;
Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	2|
       1|       2|
       2|       3|
       3|       4|
       4|       5|
       5|       6|

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        query VARCHAR(200) := 'SELECT * FROM
   table1';
    BEGIN
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
        EXECUTE IMMEDIATE 'CREATE OR REPLACE TEMPORARY TABLE query AS ' || :query;
        INSERT INTO table2
        (
            SELECT
                *
            FROM
                query
        );
    END;
$$;
Copy
             COLUMN1|	             COLUMN2|
--------------------+-----------------------+
1.000000000000000000|	2.000000000000000000|
1.000000000000000000|	2.000000000000000000|
2.000000000000000000|	3.000000000000000000|
3.000000000000000000|	4.000000000000000000|
4.000000000000000000|	5.000000000000000000|
5.000000000000000000|	6.000000000000000000|

Copy

6. FORALL With Literal SQL

Oracle
 CREATE OR REPLACE PROCEDURE SampleProcedure
IS
TYPE TabRecType IS RECORD (
    column1 NUMBER,
    column2 NUMBER
);
TYPE tabType IS TABLE OF TabRecType;
cursorRef SYS_REFCURSOR;
tab tabType;
BEGIN
    OPEN cursorRef FOR 'SELECT src.column1, src.column2 FROM ' || 'table1' || ' src';

    LOOP
        BEGIN
            FETCH cursorRef BULK COLLECT INTO tab LIMIT 1000;
            FORALL i IN 1..tab.COUNT
                INSERT INTO table2 (column1, column2)
                VALUES (tab(i).column1, tab(i).column2);

            EXIT WHEN cursorRef%NOTFOUND;
        END;
    END LOOP;

    CLOSE cursorRef;
END;
Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	2|
       1|       2|
       2|       3|
       3|       4|
       4|       5|
       5|       6|

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE SampleProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        EXECUTE IMMEDIATE 'CREATE OR REPLACE TEMPORARY TABLE cursorRef_TEMP_TABLE AS ' || 'SELECT src.column1, src.column2 FROM ' || 'table1' || ' src';
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        INSERT INTO table2(column1, column2)
        (
            SELECT
                *
            FROM
                cursorRef_TEMP_TABLE
        );
    END;
$$;
Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	2|
       1|       2|
       2|       3|
       3|       4|
       4|       5|
       5|       6|

Copy

7. FORALL With Parametrized Cursors

Oracle
 CREATE OR REPLACE PROCEDURE myProcedure IS
    intVariable INTEGER := 7;
    CURSOR cursorVariable(param1 INTEGER, param2 INTEGER default 5) IS
        SELECT * FROM table1
        WHERE
            column2 = intVariable OR
            column1 BETWEEN param1 AND param2;
    TYPE collectionTypeDefinition IS
        TABLE OF table1%ROWTYPE;
    collectionVariable collectionTypeDefinition;
BEGIN
    OPEN cursorVariable(1);
    LOOP
        FETCH cursorVariable BULK COLLECT INTO collectionVariable limit 20;
        EXIT WHEN collectionVariable.COUNT = 0;
        FORALL forIndex IN collectionVariable.FIRST..collectionVariable.LAST
            INSERT INTO table2 VALUES collectionVariable(forIndex);
        collectionVariable.DELETE;
    END LOOP;
    CLOSE cursorVariable;
END;
Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	2|
       1|       2|
       2|       3|
       3|       4|
       4|       5|
       5|       6|

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        intVariable INTEGER := 7;
    BEGIN
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        INSERT INTO table2
        (
            SELECT
                * FROM
                table1
                   WHERE
                       column2 = :intVariable
                OR
                       column1 BETWEEN 1 AND 5
        );
    END;
$$;
Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	2|
       1|       2|
       2|       3|
       3|       4|
       4|       5|
       5|       6|

Copy

8. FORALL Without LOOPS

Oracle
 CREATE OR REPLACE PROCEDURE  myProcedure IS
    TYPE collectionTypeDefinition IS TABLE OF table1%ROWTYPE;
    collectionVariable collectionTypeDefinition;
BEGIN
    SELECT * BULK COLLECT INTO collectionVariable FROM table1;
        FORALL forIndex IN 1..collectionVariable.COUNT
            INSERT INTO table2 VALUES (
                collectionVariable (forIndex).column1,
                collectionVariable (forIndex).column2
            );
        collectionVariable.DELETE;
END;
Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	2|
       1|       2|
       2|       3|
       3|       4|
       4|       5|
       5|       6|

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        INSERT INTO table2
        (
            SELECT
                column1,
                column2
            FROM
                table1
        );
    END;
$$;
Copy
             COLUMN1|	             COLUMN2|
--------------------+-----------------------+
1.000000000000000000|	2.000000000000000000|
1.000000000000000000|	2.000000000000000000|
2.000000000000000000|	3.000000000000000000|
3.000000000000000000|	4.000000000000000000|
4.000000000000000000|	5.000000000000000000|
5.000000000000000000|	6.000000000000000000|

Copy

9. FORALL With UPDATE Statements

Oracle
 CREATE OR REPLACE PROCEDURE myProcedure IS
    CURSOR cursorVariable IS
        SELECT * FROM table1;
    TYPE collectionTypeDefinition IS TABLE OF table1%ROWTYPE;
    collectionVariable collectionTypeDefinition;
BEGIN
    OPEN cursorVariable;
    LOOP
        FETCH cursorVariable BULK COLLECT INTO collectionVariable limit 2;
        EXIT WHEN collectionVariable.COUNT = 0;
        FORALL forIndex IN collectionVariable.FIRST..collectionVariable.LAST
            UPDATE table2 SET column1 = '54321' WHERE column2 = collectionVariable(forIndex).column2;
        collectionVariable.DELETE;
    END LOOP;
    CLOSE cursorVariable;
END;
Copy
 COLUMN1| COLUMN2|
--------+--------+
   54321|	2|

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        UPDATE table2
            SET column1 = '54321'
            FROM
                (
                    SELECT
                        * FROM
                        table1) AS collectionVariable
            WHERE
                column2 = collectionVariable.column2;
    END;
$$;
Copy
 COLUMN1| COLUMN2|
--------+--------+
   54321|	2|

Copy

10. FORALL With DELETE Statements

Oracle
 CREATE OR REPLACE PROCEDURE myProcedure IS
    CURSOR cursorVariable IS
        SELECT * FROM table1;
    TYPE collectionTypeDefinition IS TABLE OF table1%ROWTYPE;
    collectionVariable collectionTypeDefinition;
BEGIN
    OPEN cursorVariable;
    LOOP
        FETCH cursorVariable BULK COLLECT INTO collectionVariable limit 2;
        EXIT WHEN collectionVariable.COUNT = 0;
        FORALL forIndex IN collectionVariable.FIRST..collectionVariable.LAST
            DELETE FROM table2 WHERE column2 = collectionVariable(forIndex).column2;
        collectionVariable.DELETE;
    END LOOP;
    CLOSE cursorVariable;
END;
Copy
no data found

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        DELETE FROM
            table2
        USING (
            SELECT
                * FROM
                table1) collectionVariable
                WHERE
            table2.column2 = collectionVariable.column2;
    END;
$$;
Copy
Query produced no results

Copy

11. FORALL With PACKAGE References

Oracle
 CREATE OR REPLACE PACKAGE MyPackage AS
    TYPE collectionTypeDefinition IS
        TABLE OF table1%ROWTYPE;
    collectionVariable collectionTypeDefinition;
END;
/
 
CREATE OR REPLACE PROCEDURE InsertIntoPackage(param integer) IS
BEGIN
    SELECT
        param,
        param BULK COLLECT INTO MyPackage.collectionVariable
    FROM
        DUAL;
END;
/
 
CREATE OR REPLACE PROCEDURE InsertUsingPackage IS
BEGIN
        FORALL forIndex IN MyPackage.collectionVariable.FIRST..MyPackage.collectionVariable.LAST
            INSERT INTO table2 VALUES MyPackage.collectionVariable(forIndex);
        MyPackage.collectionVariable.DELETE;
END;
/

DECLARE
    param_value INTEGER := 10;
BEGIN
    InsertIntoPackage(param_value);
    InsertUsingPackage;
END;

select * from table2;
Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	2|
      10|      10|       

Copy
Snowflake
 CREATE SCHEMA IF NOT EXISTS MyPackage
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

!!!RESOLVE EWI!!! /*** SSC-EWI-OR0049 - PACKAGE TYPE DEFINITIONS in stateful package MyPackage are not supported yet ***/!!!
TYPE collectionTypeDefinition IS
    TABLE OF table1%ROWTYPE;

CREATE OR REPLACE TEMPORARY TABLE MYPACKAGE_COLLECTIONVARIABLE (
);

CREATE OR REPLACE PROCEDURE InsertIntoPackage (param integer)
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        DELETE FROM
            MYPACKAGE_COLLECTIONVARIABLE;
        INSERT INTO MYPACKAGE_COLLECTIONVARIABLE
        (
            SELECT
                :param,
                :param
            FROM
        DUAL
        );
    END;
$$;

CREATE OR REPLACE PROCEDURE InsertUsingPackage ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        INSERT INTO table2
        (
            SELECT
                *
            FROM
                MYPACKAGE_COLLECTIONVARIABLE
        );
    END;
$$;

DECLARE
    param_value INTEGER := 10;
    call_results VARIANT;
BEGIN
    CALL
    InsertIntoPackage(:param_value);
    CALL
    InsertUsingPackage();
    RETURN call_results;
END;

select * from
    table2;
Copy
              COLUMN1|	              COLUMN2|
---------------------+-----------------------+
 1.000000000000000000|	 2.000000000000000000| 
10.000000000000000000|	10.000000000000000000|

Copy

Warnung

Die obige Transformation funktioniert nur, wenn die im Paket definierte Variable ein Datensatz von Collections ist.

12. FORALL With MERGE Statements

Oracle
 CREATE OR REPLACE PROCEDURE myProcedure IS
    CURSOR cursorVariable IS
        SELECT * FROM table1;
    TYPE collectionTypeDefinition IS
        TABLE OF table1%ROWTYPE;
    collectionVariable collectionTypeDefinition;
BEGIN
    OPEN cursorVariable;
    LOOP
        FETCH cursorVariable BULK COLLECT INTO collectionVariable limit 2;
        EXIT WHEN collectionVariable.COUNT = 0;
        FORALL forIndex IN collectionVariable.FIRST..collectionVariable.LAST
        MERGE INTO table2 tgt
            USING (
                SELECT
                    collectionVariable(forIndex).column1 column1,
                    collectionVariable(forIndex).column2 column2
                FROM DUAL
            ) src
           ON (tgt.column1 = src.column1)
        WHEN MATCHED THEN
            UPDATE SET
               tgt.column2 = src.column2 * 2
        WHEN NOT MATCHED THEN
            INSERT (column1, column2)
            VALUES (src.column1, src.column2);
    END LOOP;
    CLOSE cursorVariable;
END;
Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	4|
       2|       3|
       3|       4|
       4|       5|
       5|       6|

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        MERGE INTO table2 tgt
            USING (
                SELECT
                    collectionVariable.column1 column1,
                    collectionVariable.column2 column2
                FROM
                    (
                        SELECT
                            * FROM
                            table1
                    ) collectionVariable
            ) src
           ON (tgt.column1 = src.column1)
        WHEN MATCHED THEN
            UPDATE SET
               tgt.column2 = src.column2 * 2
        WHEN NOT MATCHED THEN
            INSERT (column1, column2)
            VALUES (src.column1, src.column2);
    END;
$$;
Copy
             COLUMN1|	             COLUMN2|
--------------------+-----------------------+
2.000000000000000000|	3.000000000000000000|
3.000000000000000000|	4.000000000000000000|
4.000000000000000000|	5.000000000000000000|
5.000000000000000000|	6.000000000000000000|
1.000000000000000000|	4.000000000000000000|

Copy

Warnung

Die obige Transformation funktioniert nur, wenn die Anweisung SELECT innerhalb von MERGE eine Auswahl aus der Tabelle DUAL trifft.

13. Default FORALL transformation

Bemerkung

Das könnte Sie auch interessieren: Bulk Cursor-Hilfsfunktionen .

Oracle
 CREATE OR REPLACE PROCEDURE myProcedure IS
    CURSOR cursorVariable IS SELECT * FROM table1;
    TYPE columnsRecordType IS RECORD (column1 dbms_sql.NUMBER_table, column2 dbms_sql.NUMBER_table);
    recordVariable columnsRecordType;
    TYPE collectionTypeDefinition IS TABLE OF table1%ROWTYPE;
    collectionVariable collectionTypeDefinition;
    col1 dbms_sql.NUMBER_table;
    col2 dbms_sql.NUMBER_table;
BEGIN
    OPEN cursorVariable;
    FETCH cursorVariable BULK COLLECT INTO collectionVariable limit 2;
    FORALL forIndex IN collectionVariable.FIRST..collectionVariable.LAST
        INSERT INTO table2 (column1, column2)
        VALUES (collectionVariable(forIndex).column1, collectionVariable(forIndex).column2);

    FETCH cursorVariable BULK COLLECT INTO col1, col2 limit 2;
    FORALL forIndex IN col1.FIRST..col1.LAST
        INSERT INTO table2 (column1, column2)
        VALUES (col1(forIndex), col2(forIndex));

    LOOP
        FETCH cursorVariable BULK COLLECT INTO recordVariable limit 2;
        EXIT WHEN recordVariable.column1.COUNT = 0;
        FORALL forIndex IN recordVariable.column1.FIRST..recordVariable.column1.LAST
            INSERT INTO table2 (column1, column2)
            VALUES (recordVariable.column1(forIndex), recordVariable.column2(forIndex));
    END LOOP;
    CLOSE cursorVariable;
END;
Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	2|
       1|       2|
       2|       3|
       3|       4|
       4|       5|
       5|       6|

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        cursorVariable OBJECT := INIT_CURSOR_UDF('cursorVariable', '   SELECT * FROM
      table1');
        !!!RESOLVE EWI!!! /*** SSC-EWI-0056 - CUSTOM TYPES ARE NOT SUPPORTED IN SNOWFLAKE BUT REFERENCES TO THIS CUSTOM TYPE WERE CHANGED TO OBJECT ***/!!!
           TYPE columnsRecordType IS RECORD (column1 dbms_sql.NUMBER_table, column2 dbms_sql.NUMBER_table);
           recordVariable OBJECT !!!RESOLVE EWI!!! /*** SSC-EWI-0036 - columnsRecordType DATA TYPE CONVERTED TO OBJECT ***/!!! := OBJECT_CONSTRUCT();
--        !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'PL COLLECTION TYPE DEFINITION' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
--           TYPE collectionTypeDefinition IS TABLE OF table1%ROWTYPE;
           collectionVariable VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-0062 - CUSTOM TYPE 'collectionTypeDefinition' USAGE CHANGED TO VARIANT ***/!!!;
           col1 VARIANT /*** SSC-FDM-0015 - REFERENCED CUSTOM TYPE 'dbms_sql.NUMBER_table' IN QUERY NOT FOUND, USAGES MAY BE AFFECTED ***/;
           col2 VARIANT /*** SSC-FDM-0015 - REFERENCED CUSTOM TYPE 'dbms_sql.NUMBER_table' IN QUERY NOT FOUND, USAGES MAY BE AFFECTED ***/;
        FORALL INTEGER;
    BEGIN
        cursorVariable := (
            CALL OPEN_BULK_CURSOR_UDF(:cursorVariable)
        );
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        cursorVariable := (
            CALL FETCH_BULK_COLLECTION_RECORDS_UDF(:cursorVariable, 2)
        );
        collectionVariable := :cursorVariable:RESULT;
        FORALL := ARRAY_SIZE(:collectionVariable);
        INSERT INTO table2(column1, column2)
        (
            SELECT
                :collectionVariable[forIndex]:column1,
                : collectionVariable[forIndex]:column2
            FROM
                (
                    SELECT
                        seq4() AS forIndex
                    FROM
                        TABLE(GENERATOR(ROWCOUNT => :FORALL))
                )
        );
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        cursorVariable := (
            CALL FETCH_BULK_COLLECTIONS_UDF(:cursorVariable, 2)
        );
        col1 := :cursorVariable:RESULT[0];
        col2 := :cursorVariable:RESULT[1];
        FORALL := ARRAY_SIZE(:col1);
        INSERT INTO table2(column1, column2)
        (
            SELECT
                :col1[forIndex],
                : col2[forIndex]
            FROM
                (
                    SELECT
                        seq4() AS forIndex
                    FROM
                        TABLE(GENERATOR(ROWCOUNT => :FORALL))
                )
        );
        LOOP
            --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
            --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
            cursorVariable := (
                CALL FETCH_BULK_RECORD_COLLECTIONS_UDF(:cursorVariable, 2)
            );
            recordVariable := :cursorVariable:RESULT;
            IF (ARRAY_SIZE(:recordVariable:column1) = 0) THEN
                EXIT;
            END IF;
            FORALL := ARRAY_SIZE(:recordVariable:column1);
            INSERT INTO table2(column1, column2)
            (
                SELECT
                    :recordVariable:column1[forIndex],
                    : recordVariable:column2[forIndex]
                FROM
                    (
                        SELECT
                            seq4() AS forIndex
                        FROM
                            TABLE(GENERATOR(ROWCOUNT => :FORALL))
                    )
            );
        END LOOP;
        cursorVariable := (
            CALL CLOSE_BULK_CURSOR_UDF(:cursorVariable)
        );
    END;
$$;
Copy
             COLUMN1|	             COLUMN2|
--------------------+-----------------------+
1.000000000000000000|	2.000000000000000000|
1.000000000000000000|	2.000000000000000000|
2.000000000000000000|	3.000000000000000000|
3.000000000000000000|	4.000000000000000000|
4.000000000000000000|	5.000000000000000000|
5.000000000000000000|	6.000000000000000000|

Copy

Bemerkung

Diese Transformation wird nur durchgeführt, wenn keine der zuvor genannten Transformationen möglich ist.

14. Multiple FORALL inside a LOOP clause

Bemerkung

Dieses Muster findet Anwendung, wenn es mehr als eine FORALL in derselben Prozedur gibt und diese die folgende Struktur aufweist.

Oracle
 CREATE OR REPLACE PROCEDURE myProcedure IS
    CURSOR cursorVariable IS
        SELECT * FROM table1;

    TYPE collectionTypeDefinition IS TABLE OF table1%ROWTYPE;
    collectionVariable collectionTypeDefinition;
BEGIN
    OPEN cursorVariable;
    LOOP
        FETCH cursorVariable BULK COLLECT INTO collectionVariable limit 20;
        EXIT WHEN collectionVariable.COUNT = 0;

        FORALL forIndex IN collectionVariable.FIRST..collectionVariable.LAST
            INSERT INTO table2 VALUES collectionVariable(forIndex);
        
        FORALL forIndex IN collectionVariable.FIRST..collectionVariable.LAST
            UPDATE table2 SET column1 = '54321' WHERE column2 = collectionVariable(forIndex).column2;

    END LOOP;
    CLOSE cursorVariable;
END;
Copy
 COLUMN1| COLUMN2|
--------+--------+
   54321|	2|
   54321|       2|
   54321|       3|
   54321|       4|
   54321|       5|
   54321|       6|

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        INSERT INTO table2
        (
            SELECT
                * FROM
                table1
        );
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        UPDATE table2
            SET column1 = '54321'
            FROM
                (
                    SELECT
                        * FROM
                        table1) AS collectionVariable
            WHERE
                column2 = collectionVariable.column2;
    END;
$$;
Copy
 COLUMN1| COLUMN2|
--------+--------+
   54321|	2|
   54321|       2|
   54321|       3|
   54321|       4|
   54321|       5|
   54321|       6|

Copy

15. Multiple FORALL inside different LOOP clauses

Bemerkung

Dieses Muster findet Anwendung, wenn es mehr als eine FORALL in derselben Prozedur gibt und diese die folgende Struktur aufweist.

Oracle
 CREATE OR REPLACE PROCEDURE myProcedure IS
    CURSOR cursorVariable IS
        SELECT * FROM table1;

    CURSOR cursorVariable2 IS
        SELECT * FROM table1;

    TYPE collectionTypeDefinition IS
        TABLE OF table1%ROWTYPE;
    collectionVariable collectionTypeDefinition;

    TYPE collectionTypeDefinition2 IS
        TABLE OF table1%ROWTYPE;
    collectionVariable2 collectionTypeDefinition2;
BEGIN
    OPEN cursorVariable;
    LOOP
        FETCH cursorVariable BULK COLLECT INTO collectionVariable limit 2;
        EXIT WHEN collectionVariable.COUNT = 0;
        FORALL forIndex IN collectionVariable.FIRST..collectionVariable.LAST
            INSERT INTO table2 VALUES collectionVariable(forIndex);
    END LOOP;
    CLOSE cursorVariable;

    OPEN cursorVariable2;
    LOOP
        FETCH cursorVariable2 BULK COLLECT INTO collectionVariable2 limit 2;
        EXIT WHEN collectionVariable2.COUNT = 0;
        FORALL forIndex IN collectionVariable2.FIRST..collectionVariable2.LAST
            UPDATE table2 SET column1 = '54321' WHERE column2 = collectionVariable2(forIndex).column2;
    END LOOP;
    CLOSE cursorVariable2;
END;
Copy
 COLUMN1| COLUMN2|
--------+--------+
   54321|	2|
   54321|       2|
   54321|       3|
   54321|       4|
   54321|       5|
   54321|       6|

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        INSERT INTO table2
        (
            SELECT
                * FROM
                table1
        );
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        UPDATE table2
            SET column1 = '54321'
            FROM
                (
                    SELECT
                        * FROM
                        table1) AS collectionVariable2
            WHERE
                column2 = collectionVariable2.column2;
    END;
$$;
Copy
 COLUMN1| COLUMN2|
--------+--------+
   54321|	2|
   54321|       2|
   54321|       3|
   54321|       4|
   54321|       5|
   54321|       6|

Copy

16. FORALL with MERGE INTO with LOG ERRORS

Warnung

Dieses Muster ist noch nicht implementiert

Oracle

 CREATE OR REPLACE PROCEDURE procedure_example (
    department_id_in   IN source_table.DepartmentID%TYPE)
IS
    TYPE employee_ids_t IS TABLE OF source_table%ROWTYPE
    INDEX BY PLS_INTEGER; 
    employee_list   employee_ids_t;
BEGIN
    SELECT *
        BULK COLLECT INTO employee_list
        FROM source_table
        WHERE DepartmentID = procedure_example.department_id_in;
    
    FORALL indx IN 1 .. employee_list.COUNT
      MERGE INTO target_table 
      USING (SELECT * FROM DUAL) src
      ON (id = employee_list(indx).id)
      WHEN MATCHED THEN
        UPDATE SET
          name = employee_list(indx).Name
      WHEN NOT MATCHED THEN
        INSERT (Id, Name, DepartmentID)
        VALUES (employee_list(indx).Id, employee_list(indx).Name, employee_list(indx).DepartmentID)
      LOG ERRORS INTO error_table('MERGE INTO ERROR') 
      REJECT LIMIT UNLIMITED;
        
END;

CALL procedure_example(10);

select * from target_table;
select * from error_table;
Copy
   ID|    NAME|	DEPARTMENTID|
-----+--------+-------------+
  101|	Anurag|	          10|


ORA_ERR_NUMBER$|                                                                        ORA_ERR_MESG$ |	    ORA_ERR_ROWID$| ORA_ERR_OPTYP$ |       ORA_ERR_TAG$ |
---------------+--------------------------------------------------------------------------------------+-------------------+----------------+--------------------+
          12899| ORA-12899: value too large for column "TARGET_TABLE"."NAME" (actual: 15, maximum: 10)|	AK6vdpADDAAABI7AAA|              U |.  MERGE INTO ERROR |


Copy
Snowflake
 --Generated by SnowConvert---------------
CREATE OR REPLACE TRANSIENT TABLE target_staging_table(
  Id INT PRIMARY KEY,
  Name VARCHAR2(10) NOT NULL,
  DepartmentID INT REFERENCES parent_table(Id)
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;
--Generated by SnowConvert---------------

CREATE OR REPLACE PROCEDURE procedure_example (DEPARTMENT_ID_IN INT /*** MSC-WARNING - MSCEWI3129 - TYPE ATTRIBUTE 'employees.DepartmentID%TYPE' COULD NOT BE RESOLVED, SO IT WAS TRANSFORMED TO VARIANT ***/)
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$  
    BEGIN
        CREATE OR REPLACE TEMP TABLE SOURCE_TEMPORAL AS
        WITH source_data as (
            SELECT *
            FROM source_table
            WHERE DEPARTMENTID =: DEPARTMENT_ID_IN
        )
        SELECT source_data.*, parent_table.id as PARENT_KEY 
        FROM source_data 
        left join parent_table on source_data.DepartmentID = parent_table.id;
        
        --All records violating foreign key integrity
        INSERT INTO error_table (ERROR, COLUMN_NAME, REJECTED_RECORD)
        SELECT 
            'Foreign Key Constraint Violated' ERROR,'KEY_COL' COLUMN_NAME, id
        FROM SOURCE_TEMPORAL 
        WHERE PARENT_KEY IS NULL;


        DELETE FROM SOURCE_TEMPORAL 
        WHERE PARENT_KEY IS NULL;

        BEGIN
            MERGE INTO target_table
            USING SOURCE_TEMPORAL SRC
            ON SRC.id = target_table.id
            WHEN MATCHED THEN
                UPDATE SET 
                    name = SRC.name
            WHEN NOT MATCHED THEN
               INSERT (Id, Name, DepartmentID)
               VALUES (SRC.Id, SRC.Name, SRC.DepartmentID);
        EXCEPTION
            WHEN OTHER THEN
                CREATE OR REPLACE TEMPORARY STAGE my_int_stage
                  COPY_OPTIONS = (ON_ERROR='continue');
                
                --Create my file and populate with data
                COPY INTO @my_int_stage/my_file FROM (
                SELECT  * exclude(PARENT_KEY) FROM SOURCE_TEMPORAL
                ) OVERWRITE = TRUE ;

                COPY INTO target_staging_table(id, name, DepartmentID) 
                FROM (
                  SELECT 
                    -- distinct
                    t.$1, t.$2, t.$3 
                  FROM @my_int_stage/my_file t
                  ) ON_ERROR = CONTINUE;

                INSERT INTO ERROR_TABLE (ERROR, FILE, LINE, CHARACTER, CATEGORY, CODE, SQL_STATE, COLUMN_NAME, ROW_NUMBER, REJECTED_RECORD)
                SELECT 
                    ERROR, FILE,LINE, CHARACTER, CATEGORY, CODE, SQL_STATE, COLUMN_NAME, ROW_NUMBER, REJECTED_RECORD
                FROM TABLE(VALIDATE(target_staging_table, JOB_ID => '_last')) order by line; --The last charge on the current session

                MERGE INTO target_table
                USING target_staging_table staging
                ON staging.id = target_table.id
                WHEN MATCHED THEN
                    UPDATE SET 
                        name = staging.name
                WHEN NOT MATCHED THEN
                INSERT (Id, Name, DepartmentID)
                VALUES (staging.Id, staging.Name, staging.DepartmentID);
        END;

        return 'Awesome!';
    END;
$$;

CALL procedure_example(10);

SELECT * FROM target_table;
SELECT * FROM error_table;
Copy
                                                                ERROR|	                FILE| LINE| CHARACTER|    CATEGORY|	CODE| SQL_STATE|	                    COLUMN_NAME| ROW_NUMBER|        REJECTED_RECORD|                   CREATE_TS|
---------------------------------------------------------------------+----------------------+-----+----------+------------+---------+----------+---------------------------------------------------+-----------------------+----------------------------+
User character length limit (10) exceeded by string 'Anurag111111111'|	my_file_0_0_0.csv.gz|	 1|	    5|	conversion|   100074|	  54000| """TARGET_STAGING_TABLE""[""NAME"":2]"|          1| 101,Anurag111111111,10|	2023-08-03T14:33:40.978Z|


Copy

17. FORALL with INSERT with LOG ERRORS

Warnung

Dieses Muster ist noch nicht implementiert

Oracle

 CREATE OR REPLACE PROCEDURE procedure_example (
    department_id_in   IN source_table.DepartmentID%TYPE)
IS
    TYPE employee_ids_t IS TABLE OF source_table%ROWTYPE
    INDEX BY PLS_INTEGER; 
    employee_list   employee_ids_t;
BEGIN
    SELECT *
        BULK COLLECT INTO employee_list
        FROM source_table
        WHERE DepartmentID = procedure_example.department_id_in;
    
    FORALL indx IN 1 .. employee_list.COUNT
        INSERT INTO target_table(Id, Name, DepartmentID)
        VALUES (employee_list(indx).Id, employee_list(indx).Name, employee_list(indx).DepartmentID)
        LOG ERRORS INTO error_table('MERGE INTO ERROR') 
        REJECT LIMIT UNLIMITED;
END;
Copy
   ID|    NAME|	DEPARTMENTID|
-----+--------+-------------+
  101|	Anurag|	          10|


ORA_ERR_NUMBER$|                                                                        ORA_ERR_MESG$ |	    ORA_ERR_ROWID$| ORA_ERR_OPTYP$ |       ORA_ERR_TAG$ |
---------------+--------------------------------------------------------------------------------------+-------------------+----------------+--------------------+
          12899| ORA-12899: value too large for column "TARGET_TABLE"."NAME" (actual: 15, maximum: 10)|	AK6vdpADDAAABI7AAA|              U |.  MERGE INTO ERROR |


Copy
Snowflake
 --Generated by SnowConvert---------------
CREATE OR REPLACE TRANSIENT TABLE target_staging_table(
  Id INT PRIMARY KEY,
  Name VARCHAR2(10) NOT NULL,
  DepartmentID INT REFERENCES parent_table(Id)
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;
--Generated by SnowConvert---------------

CREATE OR REPLACE PROCEDURE procedure_example (DEPARTMENT_ID_IN INT /*** MSC-WARNING - MSCEWI3129 - TYPE ATTRIBUTE 'employees.DepartmentID%TYPE' COULD NOT BE RESOLVED, SO IT WAS TRANSFORMED TO VARIANT ***/)
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$  
    BEGIN
        CREATE OR REPLACE TEMP TABLE SOURCE_TEMPORAL AS
        WITH source_data as (
            SELECT *
            FROM source_table
            WHERE DEPARTMENTID =: DEPARTMENT_ID_IN
        )
        SELECT source_data.*, parent_table.id as PARENT_KEY 
        FROM source_data 
        left join parent_table on source_data.DepartmentID = parent_table.id;
        
        --All records violating foreign key integrity
        INSERT INTO error_table (ERROR, COLUMN_NAME, REJECTED_RECORD)
        SELECT 
            'Foreign Key Constraint Violated' ERROR,'KEY_COL' COLUMN_NAME, id
        FROM SOURCE_TEMPORAL 
        WHERE PARENT_KEY IS NULL;


        DELETE FROM SOURCE_TEMPORAL 
        WHERE PARENT_KEY IS NULL;

        BEGIN
            INSERT INTO target_table (Id, Name, DepartmentID)
            SELECT SRC.Id, SRC.Name, SRC.DepartmentID FROM SOURCE_TEMPORAL SRC;
        EXCEPTION
            WHEN OTHER THEN
                CREATE OR REPLACE TEMPORARY STAGE my_int_stage
                  COPY_OPTIONS = (ON_ERROR='continue');
                
                --Create my file and populate with data
                COPY INTO @my_int_stage/my_file FROM (
                SELECT  * exclude(PARENT_KEY) FROM SOURCE_TEMPORAL
                ) OVERWRITE = TRUE ;

                COPY INTO target_staging_table(id, name, DepartmentID) 
                FROM (
                  SELECT 
                    -- distinct
                    t.$1, t.$2, t.$3 
                  FROM @my_int_stage/my_file t
                  ) ON_ERROR = CONTINUE;

                INSERT INTO ERROR_TABLE (ERROR, FILE, LINE, CHARACTER, CATEGORY, CODE, SQL_STATE, COLUMN_NAME, ROW_NUMBER, REJECTED_RECORD)
                SELECT 
                    ERROR, FILE,LINE, CHARACTER, CATEGORY, CODE, SQL_STATE, COLUMN_NAME, ROW_NUMBER, REJECTED_RECORD
                FROM TABLE(VALIDATE(target_staging_table, JOB_ID => '_last')) order by line; --The last charge on the current session

                INSERT INTO target_table (Id, Name, DepartmentID)
                SELECT staging.Id, staging.Name, staging.DepartmentID FROM target_staging_table staging;
        END;
    END;
$$;

CALL procedure_example(10);

SELECT * FROM target_table;
SELECT * FROM error_table;
Copy
                                                                ERROR|	                FILE| LINE| CHARACTER|    CATEGORY|	CODE| SQL_STATE|	                    COLUMN_NAME| ROW_NUMBER|        REJECTED_RECORD|                   CREATE_TS|
---------------------------------------------------------------------+----------------------+-----+----------+------------+---------+----------+---------------------------------------------------+-----------------------+----------------------------+
User character length limit (10) exceeded by string 'Anurag111111111'|	my_file_0_0_0.csv.gz|	 1|	    5|	conversion|   100074|	  54000| """TARGET_STAGING_TABLE""[""NAME"":2]"|          1| 101,Anurag111111111,10|	2023-08-03T14:33:40.978Z|


Copy

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIs

  1. [SSC-EWI-0030](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0030): Die nachstehende Anweisung enthält Verwendungen von dynamischen SQL.

  2. [SSC-EWI-0036](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0036): Datentyp in einen anderen Datentyp konvertiert.

  3. [SSC-EWI-0056](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0056): Typ erstellen wird nicht unterstützt.

  4. [SSC-EWI-0058](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0058): Die Funktionalität wird derzeit nicht von Snowflake Scripting unterstützt.

  5. [SSC-EWI-0062](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0062): Benutzerdefinierte Typverwendung auf Variante geändert.

  6. [SSC-EWI-OR0049](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0049): Paketkonstanten in zustandsabhängigen Paketen werden noch nicht unterstützt.

  7. [SSC-FDM-0006](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0006): Zahlentyp-Spalte verhält sich in Snowflake möglicherweise nicht ähnlich.

  8. [SSC-FDM-0015:](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0015) Referenzierter benutzerdefinierter Typ in Abfrage nicht gefunden.

  9. [SSC-PRF-0001](../../general/technical-documentation/issues-and-troubleshooting/performance-review/README. md#ssc-prf-0001): Diese Anweisung hat Verwendungen von Cursor-Massenabrufoperationen.

  10. [SSC-PRF-0003](../../general/technical-documentation/issues-and-troubleshooting/performance-review/README. md#ssc-prf-0003): Fetch innerhalb einer Schleife wird als komplexes Muster betrachtet, was die Leistung von Snowflake beeinträchtigen kann.

IF

Beschreibung

Die Anweisung IF führt eine Sequenz von einer oder mehreren Anweisungen aus oder überspringt sie, je nach dem Wert eines BOOLEAN-Ausdrucks. Weitere Informationen zu Oracle IF finden Sie hier.

 IF boolean_expression THEN 
    statement 
    [ statement ]...
[ 
ELSIF boolean_expression THEN 
    statement 
    [ statement ]... ]...
   [ 
ELSE 
statement [ statement ]... ] END IF ;
Copy
 IF ( <condition> ) THEN
    <statement>;
    [ <statement>; ... ]
[
ELSEIF ( <condition> ) THEN
    <statement>;
    [ <statement>; ... ]
]
[
ELSE
    <statement>;
    [ <statement>; ... ]
]
END IF;
Copy

Beispielhafte Quellcode-Muster

Beispiel einer Hilfstabelle

 CREATE TABLE if_table(col1 varchar(30));
Copy
 CREATE OR REPLACE TABLE PUBLIC.if_table (col1 varchar(30));
Copy

Mögliche IF Variationen

Oracle
 CREATE OR REPLACE PROCEDURE ifExample1 ( flag NUMBER )
IS
BEGIN
    IF flag = 1 THEN
        INSERT INTO if_table(col1) VALUES ('one');
    END IF;
END;

CALL ifExample1(1);
SELECT * FROM if_table;
Copy
 CREATE OR REPLACE PROCEDURE ifExample2 ( flag NUMBER )
IS
BEGIN
    IF flag = 1 THEN
        INSERT INTO if_table(col1) VALUES ('one');
    ELSE
        INSERT INTO if_table(col1) VALUES ('Unexpected input.');
    END IF;
END;

CALL ifExample2(2);
SELECT * FROM if_table;
Copy
 CREATE OR REPLACE PROCEDURE ifExample3 ( flag NUMBER )
IS
BEGIN
    IF flag = 1 THEN
        INSERT INTO if_table(col1) VALUES ('one');
    ELSIF flag = 2 THEN
        INSERT INTO if_table(col1) VALUES ('two');
    ELSIF flag = 3 THEN
        INSERT INTO if_table(col1) VALUES ('three');
    END IF;
END;

CALL ifExample3(3);
SELECT * FROM if_table;
Copy
 CREATE OR REPLACE PROCEDURE ifExample4 ( flag NUMBER )
IS
BEGIN
    IF flag = 1 THEN
        INSERT INTO if_table(col1) VALUES ('one');
    ELSIF flag = 2 THEN
        INSERT INTO if_table(col1) VALUES ('two');
    ELSIF flag = 3 THEN
        INSERT INTO if_table(col1) VALUES ('three');
    ELSE
        INSERT INTO if_table(col1) VALUES ('Unexpected input.');  
    END IF;
END;

CALL ifExample4(4);
SELECT * FROM if_table;
Copy
|COL1|
|----|
|one |


Copy
|COL1             |
|-----------------|
|Unexpected input.|


Copy
|COL1 |
|-----|
|three|


Copy
|COL1             |
|-----------------|
|Unexpected input.|


Copy
Snowflake Scripting
 CREATE OR REPLACE PROCEDURE ifExample1 (flag NUMBER(38, 18))
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        IF (:flag = 1) THEN
            INSERT INTO if_table(col1) VALUES ('one');
        END IF;
    END;
$$;

CALL ifExample1(1);

SELECT * FROM
    if_table;
Copy
 CREATE OR REPLACE PROCEDURE ifExample2 (flag NUMBER(38, 18))
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        IF (:flag = 1) THEN
            INSERT INTO if_table(col1) VALUES ('one');
        ELSE
            INSERT INTO if_table(col1) VALUES ('Unexpected input.');
        END IF;
    END;
$$;

CALL ifExample2(2);

SELECT * FROM
    if_table;
Copy
 CREATE OR REPLACE PROCEDURE ifExample3 (flag NUMBER(38, 18))
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        IF (:flag = 1) THEN
            INSERT INTO if_table(col1) VALUES ('one');
        ELSEIF (:flag = 2) THEN
            INSERT INTO if_table(col1) VALUES ('two');
        ELSEIF (:flag = 3) THEN
            INSERT INTO if_table(col1) VALUES ('three');
        END IF;
    END;
$$;

CALL ifExample3(3);

SELECT * FROM
    if_table;
Copy
 CREATE OR REPLACE PROCEDURE ifExample4 (flag NUMBER(38, 18))
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        IF (:flag = 1) THEN
            INSERT INTO if_table(col1) VALUES ('one');
        ELSEIF (:flag = 2) THEN
            INSERT INTO if_table(col1) VALUES ('two');
        ELSEIF (:flag = 3) THEN
            INSERT INTO if_table(col1) VALUES ('three');
        ELSE
            INSERT INTO if_table(col1) VALUES ('Unexpected input.');
        END IF;
    END;
$$;

CALL ifExample4(4);

SELECT * FROM if_table;
Copy
|COL1|
|----|
|one |


Copy
|COL1             |
|-----------------|
|Unexpected input.|


Copy
|COL1 |
|-----|
|three|


Copy
|COL1             |
|-----------------|
|Unexpected input.|


Copy

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIS

Keine zugehörigen EWIs.

IS EMPTY

Warnung

Dieser Abschnitt ist noch in Arbeit; die Informationen können sich in Zukunft ändern.

Beschreibung

Verwenden Sie die Bedingungen IS [NOT] EMPTY, um zu testen, ob eine angegebene verschachtelte Tabelle leer ist, unabhängig davon, ob irgendwelche Elemente der Sammlung NULL sind. (Dokumentation).

Oracle-Syntax

 nested_table IS [ NOT ] EMPTY
Copy

Beispielhafte Quellcode-Muster

Oracle

Das folgende Beispiel zeigt die Verwendung der Anweisung IS EMPTY. Die Anweisung wird auf eine verschachtelte Tabelle angewendet, die eine UDT als Definitionstyp verwendet. Die Ausgabe zeigt die Namen der Mitarbeiter an, die keine Telefonnummer haben.

 CREATE TYPE phone_number_type AS OBJECT (phone_number VARCHAR2(30));
/

CREATE TYPE phone_number_list AS TABLE OF phone_number_type;

CREATE TABLE employee (
    emp_id NUMBER,
    emp_name VARCHAR2(50),
    phone_numbers_col phone_number_list
) NESTED TABLE phone_numbers_col STORE AS nested_tab return as value;

INSERT INTO employee VALUES (
    1,
    'John Doe',
    phone_number_list(phone_number_type('1234567890'))
);
/

INSERT INTO employee VALUES (
    2,
    'Jane Smith',
    phone_number_list()
);

SELECT emp_name
FROM employee
WHERE phone_numbers_col IS EMPTY;
Copy

EMP_NAME

Jane Smith

Snowflake

Die unten gezeigte Snowflake-Abfrage ist die Entsprechung der Funktionalität der Anweisung IS EMPTY. Insbesondere die Anweisung IS EMPTY unterscheidet zwischen einem NULL- und einem EMPTY-Objekt.

Beachten Sie, dass die benutzerdefinierten Typen in VARIANT umgewandelt werden. Der Typ VARIANT in Snowflake ist in der Lage, Objekte und Arrays zu speichern. Da es sich bei einer verschachtelten Tabelle um eine Sequenz von Informationen handelt, ist der Typ ARRAY der geeignetste Typ, um sie neu zu definieren und zu überprüfen, ob das Objekt ARRAY leer ist.

Die ARRAY_SIZE äquivalente Lösung erlaubt auch die Frage nach der Nullbarkeit der verschachtelten Tabelle (transformiert in VARIANT). Mit anderen Worten, der Typ VARIANT kann auch NULLs und leere ARRAYs speichern.

 !!!RESOLVE EWI!!! /*** SSC-EWI-0056 - CUSTOM TYPES ARE NOT SUPPORTED IN SNOWFLAKE BUT REFERENCES TO THIS CUSTOM TYPE WERE CHANGED TO VARIANT ***/!!!
CREATE TYPE phone_number_type AS OBJECT (phone_number VARCHAR2(30))
;

!!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'NESTED TABLE' NODE ***/!!!

CREATE TYPE phone_number_list AS TABLE OF phone_number_type;

CREATE OR REPLACE TABLE employee (
    emp_id NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
    emp_name VARCHAR(50),
    phone_numbers_col VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-0062 - CUSTOM TYPE 'phone_number_list' USAGE CHANGED TO VARIANT ***/!!!
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE VIEW PUBLIC.employee_view
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "oracle",  "convertedOn": "" }}'
AS
SELECT
    emp_id,
    emp_name,
    phone_numbers_col
FROM
    employee;

INSERT INTO employee
VALUES (
    1,
    'John Doe',
    phone_number_list(phone_number_type('1234567890') !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'phone_number_type' NODE ***/!!!) !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'phone_number_list' NODE ***/!!!
);

INSERT INTO employee
VALUES (
    2,
    'Jane Smith',
    phone_number_list() !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'phone_number_list' NODE ***/!!!
);

SELECT emp_name
FROM
    employee
WHERE
    ARRAY_SIZE( phone_numbers_col) = 0;
Copy

EMP_NAME

Jane Smith

Andere mögliche Kombinationen

DescriptionOracleSnowflake
Ask for a IS NOT EMPTY
(...)
WHERE phone_numbers_col IS NOT EMPTY;
```
(...)
WHERE ARRAY_SIZE(phone_numbers_col) != 0;
```
Ask for NULL instead of EMPTY
(...)
WHERE phone_numbers_col IS NULL;
```
(...)
WHERE ARRAY_SIZE(phone_numbers_col) IS NULL;
```

Bekannte Probleme

1. User-defined types are being transformed into Variant.

Da benutzerdefinierte Typen nicht unterstützt werden, werden sie in Variantentypen umgewandelt, die unter Umständen manuellen Aufwand erfordern, um einige Funktionalitäten zu gewährleisten.

Auf der folgenden Seite finden Sie weitere Informationen:

create-type-statement

2. Nested tables are not supported.

Verschachtelte Tabellen werden derzeit nicht unterstützt. Der beste Ansatz auf der Grundlage dieser Äquivalenz ist, verschachtelte Tabellen als Variant zu behandeln, aber Arrays mit JSON-Daten darin zu deklarieren und die Snowflake-Funktion PARSE_JSON auszuführen, um die verschachtelten Informationen aufzufüllen.

Auf den folgenden Seiten finden Sie weitere Informationen:

nested-table-array-type-definition.md

nested-table-type-definition.md

3. Insert statements are not supported for User-defined types.

Da benutzerdefinierte Typen nicht unterstützt werden, werden auch die INSERT-Anweisungen für diese Typen nicht unterstützt. Speziell in verschachtelten Tabellen muss die Anweisung INSERT INTO... VALUES in INSERT INTO...SELECT geändert werden, da die Funktion ARRAY_CONSTRUCT in diesem Muster verwendet werden soll.

Auf der folgenden Seite finden Sie weitere Informationen:

object-type-definition.md

4. Logic should be adapted to ARRAY types.

Da die verschachtelten Tabellen gleichwertig in VARIANT umgewandelt werden und sich wie ARRAYsverhalten sollten, müssen die Funktionalität und Logik der Implementierung von Prozeduren und der Interaktion mit den Daten angepasst werden.

Sehen Sie sich die folgenden Beispiele an:

4.1 Gleichwertigkeit der Prozeduren
 create or replace procedure proc1
as
    col1 phone_number_list:= phone_number_list();
begin
   IF col1 IS EMPTY
   THEN
    dbms_output.put_line('IS EMPTY');
   END IF;
end;
Copy
 CREATE OR REPLACE PROCEDURE proc1 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
   DECLARE
      col1 VARIANT /*** SSC-FDM-0015 - REFERENCED CUSTOM TYPE 'phone_number_list' IN QUERY NOT FOUND, USAGES MAY BE AFFECTED ***/ := phone_number_list() !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'phone_number_list' NODE ***/!!!;
   BEGIN
      IF (ARRAY_SIZE(:col1) = 0) THEN
         --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
         CALL DBMS_OUTPUT.PUT_LINE_UDF('IS EMPTY');
      END IF;
   END;
$$;
Copy

PROC1

IS EMPTY

4.2 SELECT-Anweisungen

Die Ausgaben können von den Tabellen auf ARRAYs abweichen.

Oracle
 SELECT
    t.*
FROM
    employee e,
    table(e.phone_numbers_col) t
WHERE
    emp_id = 1;
Copy

PHONE_NUMBER

1234567890

Snowflake
 SELECT
    t.*
FROM
    employee e,
    !!!RESOLVE EWI!!! /*** SSC-EWI-OR0035 - TABLE FUNCTION IS NOT SUPPORTED WHEN IT IS USED AS A COLLECTION OF EXPRESSIONS ***/!!!
    table(e.phone_numbers_col) t
WHERE
    emp_id = 1;
Copy

PHONE_NUMBERS_COL

[ 1234567890 ]

Zugehörige EWIs

  1. [SSC-EWI-0056](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0056): Typ erstellen wird nicht unterstützt.

  2. [SSC-EWI-0062](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0062): Benutzerdefinierte Typverwendung auf Variante geändert.

  3. [SSC-EWI-0073](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0073): Überprüfung der Funktionsäquivalenz ausstehend.

  4. [SSC-EWI-OR0035](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0035): Die Tabellenfunktion wird nicht unterstützt, wenn sie als eine Sammlung von Ausdrücken verwendet wird.

  5. [SSC-FDM-0006](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0006): Zahlentyp-Spalte verhält sich in Snowflake möglicherweise nicht ähnlich.

  6. [SSC-FDM-0015:](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0015) Referenzierter benutzerdefinierter Typ in Abfrage nicht gefunden.

  7. [SSC-FDM-OR0035](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/oracleFDM. md#ssc-fdm-or0035): DBMS_OUTPUT.PUTLINE UDF Implementierung überprüfen.

LOCK TABLE

Bemerkung

Nicht relevante Anweisung.

Warnung

Beachten Sie, dass diese Anweisung aus der Migration entfernt wurde, da sie eine nicht relevante Syntax darstellt. Das bedeutet, dass sie in Snowflake nicht erforderlich ist.

Beschreibung

In Oracle ermöglicht die Anweisung LOCK TABLE den expliziten Erwerb einer gemeinsamen oder exklusiven Tabellensperre für die angegebene Tabelle. Die Sperre der Tabelle hält bis zum Ende der aktuellen Transaktion an. Weitere Informationen finden Sie hier.

Syntax

 LOCK TABLE tableName IN { SHARE | EXCLUSIVE } MODE
Copy

Beispielhafte Quellcode-Muster

Tabelle sperren

Beachten Sie, dass in diesem Beispiel die Anweisung LOCK TABLE gelöscht wurde. Das liegt daran, dass Snowflake Sperren auf eine andere Art und Weise durch Transaktionen handhabt.

 LOCK TABLE table1 IN EXCLUSIVE MODE;
Copy
 [Empty output]
Copy

LOG ERROR

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

Beschreibung

Die Anweisung FORALL führt eine Anweisung DML mehrfach aus, mit unterschiedlichen Werten in den VALUES- und WHERE-Klauseln. (Oracle PL/SQL Language Reference FORALL Statement).

FORALL index IN bounds_clause [ SAVE ] [ EXCEPTIONS ] dml_statement ;
Copy

Warnung

Snowflake Scripting ist nicht direkt gleichwertig mit der Anweisung FORALL, kann aber mit verschiedenen Umgehungsmöglichkeiten emuliert werden, um eine funktionale Gleichwertigkeit zu erreichen.

Beispielhafte Quellcode-Muster

Datenkonfiguration

Oracle
 CREATE TABLE error_table (
    ORA_ERR_NUMBER$ NUMBER,
    ORA_ERR_MESG$ VARCHAR2(2000),
    ORA_ERR_ROWID$ ROWID,
    ORA_ERR_OPTYP$ VARCHAR2(2),
    ORA_ERR_TAG$ VARCHAR2(2000)
);

--departments
CREATE TABLE parent_table(
    Id INT PRIMARY KEY,
    Name VARCHAR2(10)
);

INSERT INTO parent_table VALUES (10, 'IT');
INSERT INTO parent_table VALUES (20, 'HR');
INSERT INTO parent_table VALUES (30, 'INFRA');

--employees
CREATE TABLE source_table(
    Id INT PRIMARY KEY,
    Name VARCHAR2(20) NOT NULL,
    DepartmentID INT REFERENCES parent_table(Id)
);

INSERT INTO source_table VALUES (101, 'Anurag111111111', 10); 
INSERT INTO source_table VALUES (102, 'Pranaya11111111', 20); 
INSERT INTO source_table VALUES (103, 'Hina11111111111', 30);

--a copy of source
CREATE TABLE target_table(
    Id INT PRIMARY KEY,
    Name VARCHAR2(10) NOT NULL,
    DepartmentID INT REFERENCES parent_table(Id)
);

INSERT INTO target_table VALUES (101, 'Anurag', 10);
Copy
Snowflake
 CREATE OR REPLACE TABLE error_table (
    "ORA_ERR_NUMBER$" NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
    "ORA_ERR_MESG$" VARCHAR(2000),
    "ORA_ERR_ROWID$" VARCHAR(18) !!!RESOLVE EWI!!! /*** SSC-EWI-0036 - ROWID DATA TYPE CONVERTED TO VARCHAR ***/!!!,
    "ORA_ERR_OPTYP$" VARCHAR(2),
    "ORA_ERR_TAG$" VARCHAR(2000)
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

--departments
CREATE OR REPLACE TABLE parent_table (
        Id INT PRIMARY KEY,
        Name VARCHAR(10)
    )
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

INSERT INTO parent_table
VALUES (10, 'IT');

INSERT INTO parent_table
VALUES (20, 'HR');

INSERT INTO parent_table
VALUES (30, 'INFRA');

--employees
CREATE OR REPLACE TABLE source_table (
    Id INT PRIMARY KEY,
    Name VARCHAR(20) NOT NULL,
    DepartmentID INT REFERENCES parent_table (Id)
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

INSERT INTO source_table
VALUES (101, 'Anurag111111111', 10);

INSERT INTO source_table
VALUES (102, 'Pranaya11111111', 20);

INSERT INTO source_table
VALUES (103, 'Hina11111111111', 30);

--a copy of source
CREATE OR REPLACE TABLE target_table (
    Id INT PRIMARY KEY,
    Name VARCHAR(10) NOT NULL,
    DepartmentID INT REFERENCES parent_table (Id)
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

INSERT INTO target_table
VALUES (101, 'Anurag', 10);
Copy

1. MERGE INTO Inside a FORALL

Oracle

Die drei folgenden Fälle haben die gleiche Transformation zu Snowflake Scripting und sind funktional gleichwertig.

 CREATE OR REPLACE PROCEDURE procedure_example (
    department_id_in   IN source_table.DepartmentID%TYPE)
IS
    TYPE employee_ids_t IS TABLE OF source_table%ROWTYPE
    INDEX BY PLS_INTEGER; 
    employee_list   employee_ids_t;
BEGIN
    SELECT *
        BULK COLLECT INTO employee_list
        FROM source_table
        WHERE DepartmentID = procedure_example.department_id_in;
    
    FORALL indx IN 1 .. employee_list.COUNT
      MERGE INTO target_table 
      USING (SELECT * FROM DUAL) src
      ON (id = employee_list(indx).id)
      WHEN MATCHED THEN
        UPDATE SET
          name = employee_list(indx).Name
      WHEN NOT MATCHED THEN
        INSERT (Id, Name, DepartmentID)
        VALUES (employee_list(indx).Id, employee_list(indx).Name, employee_list(indx).DepartmentID)
      LOG ERRORS INTO error_table('MERGE INTO ERROR') 
      REJECT LIMIT UNLIMITED;
        
END;

CALL procedure_example(10);

select * from target_table;
select * from error_table;
Copy
   ID|    NAME|	DEPARTMENTID|
-----+--------+-------------+
  101|	Anurag|	          10|


ORA_ERR_NUMBER$|                                                                        ORA_ERR_MESG$ |	    ORA_ERR_ROWID$| ORA_ERR_OPTYP$ |       ORA_ERR_TAG$ |
---------------+--------------------------------------------------------------------------------------+-------------------+----------------+--------------------+
          12899| ORA-12899: value too large for column "TARGET_TABLE"."NAME" (actual: 15, maximum: 10)|	AK6vdpADDAAABI7AAA|              U |.  MERGE INTO ERROR |


Copy
Snowflake
 CREATE OR REPLACE PROCEDURE procedure_example (department_id_in VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-OR0129 - TYPE ATTRIBUTE 'source_table.DepartmentID%TYPE' COULD NOT BE RESOLVED, SO IT WAS TRANSFORMED TO VARIANT ***/!!!)
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 employee_ids_t IS TABLE OF source_table%ROWTYPE
--        INDEX BY PLS_INTEGER;
        employee_list VARIANT !!!RESOLVE EWI!!! /*** SSC-EWI-0062 - CUSTOM TYPE 'employee_ids_t' USAGE CHANGED TO VARIANT ***/!!!;
        FORALL INTEGER;
    BEGIN
        !!!RESOLVE EWI!!! /*** SSC-EWI-0058 - FUNCTIONALITY FOR 'RECORDS AND COLLECTIONS' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
        SELECT *
            BULK COLLECT INTO employee_list
            FROM source_table
            WHERE DepartmentID = procedure_example.department_id_in;
        FORALL := ARRAY_SIZE(:employee_list);
          MERGE INTO target_table
          USING (SELECT * FROM
                (
                    SELECT
                        seq4() AS indx
                    FROM
                        TABLE(GENERATOR(ROWCOUNT => :FORALL))
                )) src
          ON (id = : employee_list[indx]:id)
        WHEN MATCHED THEN
        UPDATE SET
          name = : employee_list[indx]:Name
        WHEN NOT MATCHED THEN
        INSERT (Id, Name, DepartmentID)
        VALUES (:employee_list[indx]:Id, : employee_list[indx]:Name, : employee_list[indx]:DepartmentID)
--        --** SSC-FDM-OR0031 - THE ERROR LOGGING CLAUSE IN DML STATEMENTS IS NOT SUPPORTED BY SNOWFLAKE **
--          LOG ERRORS INTO error_table('MERGE INTO ERROR')
--          REJECT LIMIT UNLIMITED
                                ;
    END;
$$;


CALL procedure_example(10);


select * from
    target_table;

select * from
    error_table;
Copy
             COLUMN1|	             COLUMN2|
--------------------+-----------------------+
1.000000000000000000|	2.000000000000000000|
1.000000000000000000|	2.000000000000000000|
2.000000000000000000|	3.000000000000000000|
3.000000000000000000|	4.000000000000000000|
4.000000000000000000|	5.000000000000000000|
5.000000000000000000|	6.000000000000000000|

Copy

Bemerkung

Die EWIs MSCCP0005 und SSC-PRF-0003 werden bei jedem Auftreten von FETCH BULK COLLECT in die FORALL -Anweisung eingefügt.

2. FORALL With INSERT INTO

Oracle
 CREATE OR REPLACE PROCEDURE myProcedure IS
    CURSOR cursorVariable IS
        SELECT * FROM table1;
    TYPE collectionTypeDefinition IS TABLE OF table1%ROWTYPE;
    collectionVariable collectionTypeDefinition;
BEGIN
    OPEN cursorVariable;
    LOOP
        FETCH cursorVariable BULK COLLECT INTO collectionVariable limit 2;
        EXIT WHEN collectionVariable.COUNT = 0;
        FORALL forIndex IN collectionVariable.FIRST..collectionVariable.LAST
            INSERT INTO table2 VALUES collectionVariable(forIndex);
        collectionVariable.DELETE;
    END LOOP;
    CLOSE cursorVariable;
END;
Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	2|
       1|       2|
       2|       3|
       3|       4|
       4|       5|
       5|       6|

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        INSERT INTO table2
        (
            SELECT
                * FROM
                table1
        );
    END;
$$;
Copy
             COLUMN1|	             COLUMN2|
--------------------+-----------------------+
1.000000000000000000|	2.000000000000000000|
1.000000000000000000|	2.000000000000000000|
2.000000000000000000|	3.000000000000000000|
3.000000000000000000|	4.000000000000000000|
4.000000000000000000|	5.000000000000000000|
5.000000000000000000|	6.000000000000000000|

Copy

3. FORALL With Multiple Fetched Collections

Oracle
 CREATE OR REPLACE PROCEDURE myProcedure IS
    CURSOR cursorVariable IS
        SELECT * FROM table1;
    column1Collection dbms_sql.NUMBER_table;
    column2Collection dbms_sql.NUMBER_table;
BEGIN
    OPEN cursorVariable;
    LOOP
        FETCH cursorVariable BULK COLLECT INTO column1Collection, column2Collection limit 20;
        EXIT WHEN column1Collection.COUNT = 0;
        FORALL forIndex IN 1..column1Collection.COUNT
            INSERT INTO table2 VALUES (
                column1Collection(forIndex),
                column2Collection(forIndex)
            );
    END LOOP;
    CLOSE cursorVariable;
END;
Copy
 CREATE OR REPLACE PROCEDURE myProcedure IS
    CURSOR cursorVariable IS
        SELECT * FROM table1;
    column1Collection dbms_sql.NUMBER_table;
    column2Collection dbms_sql.NUMBER_table;
BEGIN
    OPEN cursorVariable;
    LOOP
        FETCH cursorVariable BULK COLLECT INTO column1Collection, column2Collection limit 2;
        EXIT WHEN column1Collection.COUNT = 0;
        FORALL forIndex IN 1..column1Collection.COUNT
            UPDATE table2 SET column2 = column2Collection(forIndex)
            WHERE column1 = column1Collection(forIndex);
    END LOOP;
    CLOSE cursorVariable;
END;
Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	2|
       2|       3|
       3|       4|
       4|       5|
       5|       6|
       1|       2|

Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	2|

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        INSERT INTO table2
        (
            SELECT
                $1,
                $2
            FROM
                table1
        );
    END;
$$;
Copy
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        UPDATE table2
            SET column2 = column1Collection.$2
            FROM
                (
                    SELECT
                        * FROM
                        table1) AS column1Collection
            WHERE
                column1 = column1Collection.$1;
    END;
$$;
Copy
             COLUMN1|	             COLUMN2|
--------------------+-----------------------+
1.000000000000000000|	2.000000000000000000|
1.000000000000000000|	2.000000000000000000|
2.000000000000000000|	3.000000000000000000|
3.000000000000000000|	4.000000000000000000|
4.000000000000000000|	5.000000000000000000|
5.000000000000000000|	6.000000000000000000|

Copy
             COLUMN1|	             COLUMN2|
--------------------+-----------------------+
1.000000000000000000|	2.000000000000000000|

Copy

4. FORALL With Record of Collections

Oracle
 CREATE OR REPLACE PROCEDURE myProcedure IS
    CURSOR cursorVariable IS
        SELECT * FROM table1;
    TYPE recordType IS RECORD(
        column1Collection dbms_sql.NUMBER_table,
        column2Collection dbms_sql.NUMBER_table
    );
    columnRecord recordType;
BEGIN
    OPEN cursorVariable;
    LOOP
        FETCH cursorVariable BULK COLLECT INTO columnRecord.column1Collection, columnRecord.column2Collection limit 20;
        FORALL forIndex IN 1..columnRecord.column1Collection.COUNT
            INSERT INTO table2 VALUES (
                columnRecord.column1Collection(forIndex),
                columnRecord.column2Collection(forIndex)
            );
        EXIT WHEN cursorVariable%NOTFOUND;
    END LOOP;
    CLOSE cursorVariable;
END;
Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	2|
       1|       2|
       2|       3|
       3|       4|
       4|       5|
       5|       6|

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        INSERT INTO table2
        (
            SELECT
                $1,
                $2
            FROM
                table1
        );
    END;
$$;
Copy
             COLUMN1|	             COLUMN2|
--------------------+-----------------------+
1.000000000000000000|	2.000000000000000000|
1.000000000000000000|	2.000000000000000000|
2.000000000000000000|	3.000000000000000000|
3.000000000000000000|	4.000000000000000000|
4.000000000000000000|	5.000000000000000000|
5.000000000000000000|	6.000000000000000000|

Copy

5. FORALL With Dynamic SQL

Oracle
 CREATE OR REPLACE PROCEDURE myProcedure IS
    cursorVariable SYS_REFCURSOR;
    TYPE collectionTypeDefinition IS
        TABLE OF table1%ROWTYPE;
    collectionVariable collectionTypeDefinition;
    query VARCHAR(200) := 'SELECT * FROM table1';
BEGIN
    OPEN cursorVariable FOR query;
    LOOP
        FETCH cursorVariable BULK COLLECT INTO collectionVariable;
        EXIT WHEN collectionVariable.COUNT = 0;
        FORALL forIndex IN collectionVariable.FIRST..collectionVariable.LAST
            INSERT INTO table2 VALUES collectionVariable(forIndex);
        collectionVariable.DELETE;
    END LOOP;
    CLOSE cursorVariable;
END;
Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	2|
       1|       2|
       2|       3|
       3|       4|
       4|       5|
       5|       6|

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        query VARCHAR(200) := 'SELECT * FROM
   table1';
    BEGIN
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
        EXECUTE IMMEDIATE 'CREATE OR REPLACE TEMPORARY TABLE query AS ' || :query;
        INSERT INTO table2
        (
            SELECT
                *
            FROM
                query
        );
    END;
$$;
Copy
             COLUMN1|	             COLUMN2|
--------------------+-----------------------+
1.000000000000000000|	2.000000000000000000|
1.000000000000000000|	2.000000000000000000|
2.000000000000000000|	3.000000000000000000|
3.000000000000000000|	4.000000000000000000|
4.000000000000000000|	5.000000000000000000|
5.000000000000000000|	6.000

Copy

6. FORALL Without LOOPS

Oracle
 CREATE OR REPLACE PROCEDURE  myProcedure IS
    TYPE collectionTypeDefinition IS TABLE OF table1%ROWTYPE;
    collectionVariable collectionTypeDefinition;
BEGIN
    SELECT * BULK COLLECT INTO collectionVariable FROM table1;
        FORALL forIndex IN 1..collectionVariable.COUNT
            INSERT INTO table2 VALUES (
                collectionVariable (forIndex).column1,
                collectionVariable (forIndex).column2
            );
        collectionVariable.DELETE;
END;
Copy
 COLUMN1| COLUMN2|
--------+--------+
       1|	2|
       1|       2|
       2|       3|
       3|       4|
       4|       5|
       5|       6|

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        INSERT INTO table2
        (
            SELECT
                column1,
                column2
            FROM
                table1
        );
    END;
$$;
Copy
             COLUMN1|	             COLUMN2|
--------------------+-----------------------+
1.000000000000000000|	2.000000000000000000|
1.000000000000000000|	2.000000000000000000|
2.000000000000000000|	3.000000000000000000|
3.000000000000000000|	4.000000000000000000|
4.000000000000000000|	5.000000000000000000|
5.000000000000000000|	6.000000000000000000|

Copy

7. FORALL With UPDATE Statements

Oracle
 CREATE OR REPLACE PROCEDURE myProcedure IS
    CURSOR cursorVariable IS
        SELECT * FROM table1;
    TYPE collectionTypeDefinition IS TABLE OF table1%ROWTYPE;
    collectionVariable collectionTypeDefinition;
BEGIN
    OPEN cursorVariable;
    LOOP
        FETCH cursorVariable BULK COLLECT INTO collectionVariable limit 2;
        EXIT WHEN collectionVariable.COUNT = 0;
        FORALL forIndex IN collectionVariable.FIRST..collectionVariable.LAST
            UPDATE table2 SET column1 = '54321' WHERE column2 = collectionVariable(forIndex).column2;
        collectionVariable.DELETE;
    END LOOP;
    CLOSE cursorVariable;
END;
Copy
 COLUMN1| COLUMN2|
--------+--------+
   54321|	2|

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        UPDATE table2
            SET column1 = '54321'
            FROM
                (
                    SELECT
                        * FROM
                        table1) AS collectionVariable
            WHERE
                column2 = collectionVariable.column2;
    END;
$$;
Copy
ambiguous column name 'COLUMN2'

Copy

8. FORALL With DELETE Statements

Oracle
 CREATE OR REPLACE PROCEDURE myProcedure IS
    CURSOR cursorVariable IS
        SELECT * FROM table1;
    TYPE collectionTypeDefinition IS TABLE OF table1%ROWTYPE;
    collectionVariable collectionTypeDefinition;
BEGIN
    OPEN cursorVariable;
    LOOP
        FETCH cursorVariable BULK COLLECT INTO collectionVariable limit 2;
        EXIT WHEN collectionVariable.COUNT = 0;
        FORALL forIndex IN collectionVariable.FIRST..collectionVariable.LAST
            DELETE FROM table2 WHERE column2 = collectionVariable(forIndex).column2;
        collectionVariable.DELETE;
    END LOOP;
    CLOSE cursorVariable;
END;
Copy
no data found

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE myProcedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$

    BEGIN
        --** SSC-PRF-0001 - THIS STATEMENT HAS USAGES OF CURSOR FETCH BULK OPERATIONS **
        --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
        DELETE FROM
            table2
        USING (
            SELECT
                * FROM
                table1) collectionVariable
                WHERE
            table2.column2 = collectionVariable.column2;
    END;
$$;
Copy
Query produced no results

Copy

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIs

  1. [SSC-EWI-0030](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0030): Die nachstehende Anweisung enthält Verwendungen von dynamischen SQL.

  2. [SSC-EWI-0036](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0036): Datentyp in einen anderen Datentyp konvertiert.

  3. [SSC-EWI-0058](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0058): Die Funktionalität wird derzeit nicht von Snowflake Scripting unterstützt.

  4. [SSC-EWI-0062](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0062): Benutzerdefinierte Typverwendung auf Variante geändert.

  5. [SSC-EWI-OR0129](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0129): TYPE-Attribut konnte nicht aufgelöst werden.

  6. [SSC-FDM-0006](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0006): Zahlentyp-Spalte verhält sich in Snowflake möglicherweise nicht ähnlich.

  7. [SSC-FDM-OR0031: ](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/oracleFDM. md#ssc-fdm-or0031) Die Fehlerprotokollierungsklausel in DML Anweisungen wird von Snowflake nicht unterstützt.

  8. [SSC-PRF-0001](../../general/technical-documentation/issues-and-troubleshooting/performance-review/README. md#ssc-prf-0001): Diese Anweisung hat Verwendungen von Cursor-Massenabrufoperationen.

  9. [SSC-PRF-0003](../../general/technical-documentation/issues-and-troubleshooting/performance-review/README. md#ssc-prf-0003): Fetch innerhalb einer Schleife wird als komplexes Muster betrachtet, was die Leistung von Snowflake beeinträchtigen kann.

LOOP

Beschreibung

Bei jeder Iteration der grundlegenden Anweisung LOOP werden die Anweisungen ausgeführt und die Kontrolle kehrt an den Anfang der Schleife zurück. Die Anweisung LOOP endet, wenn eine Anweisung innerhalb der Schleife die Kontrolle an eine andere Stelle überträgt oder eine Ausnahme auslöst.\ (Oracle PL/SQL Language Reference BASIC LOOP Statement)

 LOOP statement... END LOOP [ label ] ;
Copy
 LOOP
  <statement>;
  [ <statement>; ... ]
END LOOP [ <label> ] ;
Copy

Die Verhaltensweise von Oracle BASIC LOOP kann auch durch die Verwendung der Anweisungen geändert werden:

Beispielhafte Quellcode-Muster

Simple Loop-Case

Dieser Fall ist funktionell gleichwertig.

Oracle
 CREATE TABLE loop_testing_table
(
    iterator VARCHAR2(5)
);

CREATE OR REPLACE PROCEDURE loop_procedure 
IS
I NUMBER := 1;
J NUMBER := 10;
BEGIN  
  LOOP
    EXIT WHEN I = J;
    INSERT INTO loop_testing_table VALUES(TO_CHAR(I));
    I := I+1;
  END LOOP;
END;

CALL loop_procedure();
SELECT * FROM loop_testing_table;
Copy
ITERATOR|
--------+
1       |
2       |
3       |
4       |
5       |
6       |
7       |
8       |
9       |

Copy
Snowflake Scripting
 CREATE OR REPLACE TABLE loop_testing_table
(
    iterator VARCHAR(5)
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE PROCEDURE loop_procedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
DECLARE
    I NUMBER(38, 18) := 1;
    J NUMBER(38, 18) := 10;
BEGIN
    LOOP
      IF (:I = :J) THEN
        EXIT;
      END IF;
      INSERT INTO loop_testing_table
      VALUES(TO_CHAR(:I));
      I := :I +1;
    END LOOP;
END;
$$;

CALL loop_procedure();

SELECT * FROM
loop_testing_table;
Copy
ITERATOR|
--------+
1       |
2       |
3       |
4       |
5       |
6       |
7       |
8       |
9       |

Copy

Known Issues

Es wurden keine Probleme gefunden.

Related EWIs

Keine zugehörigen EWIs.

OUTPUT PARAMETERS

Description

Ein Ausgabeparameter ist ein Parameter, dessen Wert aus der gespeicherten Prozedur/dem Funktionsmodul zurück an den aufrufenden PL/SQL-Block übergeben wird. Da die Ausgabeparameter von Snowflake Scripting nicht unterstützt werden, wurde eine Lösung implementiert, um ihre Funktionalität zu emulieren.

Sample Source Patterns

Beispiel einer Hilfstabelle

 CREATE TABLE table01 (col1 NUMBER, col2 NUMBER);
Copy
 CREATE OR REPLACE TABLE table01 (col1 NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
col2 NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;
Copy

In der Deklaration werden die Schlüsselwörter OUT oder IN OUT entfernt. Die Zuweisung wird genauso ausgegeben wie die Eingabe, aber um die Funktionalität des Ausgabeparameters zu emulieren, wurden einige Anweisungen hinzugefügt.

Wenn eine Prozedur mit Ausgabeparametern in einer anderen Prozedur aufgerufen wird, werden einige Anweisungen hinzugefügt, um den Wert/die Werte für das/die jeweilige(n) Argument(e) zu erhalten und zuzuweisen.

Einzelner Out-Parameter

Oracle
 -- Procedure with output parameter declaration
CREATE OR REPLACE PROCEDURE proc_with_single_output_parameters(
    param1 OUT NUMBER
)
IS
BEGIN
    param1 := 123;
END;

-- Procedure with output parameter being called
CREATE OR REPLACE PROCEDURE proc_calling_proc_with_single_output_parameters
IS
    var1 NUMBER;
BEGIN
    proc_with_single_output_parameters(var1);
    INSERT INTO TABLE01 VALUES(var1, -1);
END;
Copy
Snowflake Scripting
 -- Procedure with output parameter declaration
CREATE OR REPLACE PROCEDURE proc_with_single_output_parameters (param1 NUMBER(38, 18)
)
RETURNS VARIANT
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        param1 := 123;
        RETURN param1;
    END;
$$;

-- Procedure with output parameter being called
CREATE OR REPLACE PROCEDURE proc_calling_proc_with_single_output_parameters ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        var1 NUMBER(38, 18);
        call_results VARIANT;
    BEGIN
        call_results := (
            CALL
            proc_with_single_output_parameters(:var1)
        );
        var1 := :call_results;
        INSERT INTO TABLE01
        VALUES(:var1, -1);
    END;
$$;
Copy

Mehrere Out-Parameter

Oracle
 -- Procedure with output parameters declaration
CREATE OR REPLACE PROCEDURE proc_with_multiple_output_parameters(
    param1 OUT NUMBER,
    param2 IN OUT NUMBER
)
IS
BEGIN
    param1 := 123;
    param2 := 456;
END;

-- Procedure with output parameters being called
CREATE OR REPLACE PROCEDURE proc_calling_proc_with_multiple_output_parameters
IS
    var1 NUMBER;
    var2 NUMBER;
BEGIN
    proc_with_multiple_output_parameters(var1, var2);
    INSERT INTO TABLE01 VALUES(var1, var2);
END;
Copy
Snowflake Scripting
 -- Procedure with output parameters declaration
CREATE OR REPLACE PROCEDURE proc_with_multiple_output_parameters (param1 NUMBER(38, 18), param2 NUMBER(38, 18)
)
RETURNS VARIANT
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        param1 := 123;
        param2 := 456;
        RETURN OBJECT_CONSTRUCT('param1', :param1, 'param2', :param2);
    END;
$$;

-- Procedure with output parameters being called
--** SSC-FDM-0007 - MISSING DEPENDENT OBJECT "TABLE01" **
CREATE OR REPLACE PROCEDURE proc_calling_proc_with_multiple_output_parameters ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        var1 NUMBER(38, 18);
        var2 NUMBER(38, 18);
        call_results VARIANT;
    BEGIN
        call_results := (
            CALL
            proc_with_multiple_output_parameters(:var1, :var2)
        );
        var1 := :call_results:param1;
        var2 := :call_results:param2;
        INSERT INTO TABLE01
        VALUES(:var1, :var2);
    END;
$$;
Copy

Um zu überprüfen, ob die Funktionalität korrekt emuliert wird, führt die folgende Abfrage die Prozedur und SELECT aus der zuvor erwähnten Tabelle aus.

Oracle
 CALL proc_with_single_output_parameters();
CALL proc_with_multiple_output_parameters();

SELECT * FROM table01;
Copy
COL1|COL2
----+----
123 |-1
123 |456


Copy
Snowflake Scripting
 CALL proc_with_single_output_parameters();
CALL proc_with_multiple_output_parameters();

SELECT * FROM table01;
Copy
COL1                   | COL2
-----------------------+-----------------------
123.000000000000000000 | -1
123.000000000000000000 | 456.000000000000000000

Copy

Kundendatentyp OUT-Parameter

Wenn der Ausgabeparameter ein Kundentyp ist, ist der Prozess ähnlich wie bei einem regulären Datentyp.

Oracle
 CREATE OR REPLACE PROCEDURE procedure_udtype_out_params (
    p_employee_id NUMBER,
    p_address OUT address_type
)
AS
BEGIN
    -- Retrieve the employee's address based on the employee ID.
    SELECT home_address INTO p_address
    FROM employees
    WHERE employee_id = p_employee_id;
END;
Copy
Snowflake Scripting
 CREATE OR REPLACE PROCEDURE procedure_udtype_out_params (p_employee_id NUMBER(38, 18), p_address VARIANT /*** SSC-FDM-0015 - REFERENCED CUSTOM TYPE 'address_type' IN QUERY NOT FOUND, USAGES MAY BE AFFECTED ***/
)
RETURNS VARIANT
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        -- Retrieve the employee's address based on the employee ID.
        SELECT home_address INTO
            :p_address
        FROM
            employees
        WHERE employee_id = :p_employee_id;
        RETURN p_address;
    END;
$$;
Copy

Known Issues

1. Procedures with output parameters inside packages may not work correctly

Derzeit gibt es ein Problem bei der Erfassung der semantischen Informationen von Prozeduren, die sich innerhalb von Paketen befinden. Aus diesem Grund kann die Transformation für Ausgabeparameter nur teilweise oder gar nicht funktionieren. Es wird bereits daran gearbeitet, dieses Problem zu lösen.

2. Some data types may not work properly

Wie in der Transformation zu sehen ist, wird beim Abrufen des Wertes aus den aufgerufenen Prozeduren eine implizite Transformation von VARIANT auf den von der Variablen angegebenen Typ durchgeführt. Da es viele mögliche Datentypen gibt, können einige Übertragungen fehlschlagen oder andere Daten enthalten.

Related EWIs

  1. [SSC-FDM-0006](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0006): Zahlentyp-Spalte verhält sich in Snowflake möglicherweise nicht ähnlich.

  2. [SSC-FDM-0007](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0007): Element mit fehlenden Abhängigkeiten.

  3. [SSC-FDM-0015](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0015): Datentyp wird nicht erkannt.

PROCEDURE CALL

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

Beschreibung

Dieser Abschnitt beschreibt die Syntax für Unterprogrammaufrufe innerhalb von PL-Blöcken, wie Prozeduren oder anonymen Blöcken.

Weitere Informationen zu diesem Thema finden Sie in der Dokumentation zu Unterprogrammen von Oracle: (Oracle PL/SQL Language Reference Subprogram Invocation Statement)

Prozeduraufrufe können nach Snowflake migriert werden, solange es keine optionalen Parameter gibt und ihre Reihenfolge mit den formalen Parametern übereinstimmt. Bitte beachten Sie, dass Prozeduraufrufe in eine CALL-Anweisung umgewandelt werden.

 <subprogram invocation> := subprogram_name [ ( [ parameter [, parameter]... ] ) ]

<parameter> := {
  <actual parameter>
  | <formal parameter name> => <actual parameter>
  }
Copy

Snowflake Scripting unterstützt diese Anweisung, wenn auch mit einigen funktionalen Unterschieden.

 <subprogram invocation> := CALL subprogram_name [ ( [ parameter [, parameter]... ] ) ]

<parameter> := {
  <actual parameter>
  | <formal parameter name> => <actual parameter>
  }
Copy

Beispielhafte Quellcode-Muster

Bemerkung

Betrachten Sie die nächste Tabelle und die Vorgehensweise für die folgenden Beispiele.

 CREATE TABLE procedure_call_test_table(
    col1 INTEGER
);

-- Simple Called procedure
CREATE OR REPLACE PROCEDURE called_procedure (param1 INTEGER)
AS
BEGIN
    INSERT INTO procedure_call_test_table VALUES (param1);
END;
Copy
 CREATE OR REPLACE TABLE procedure_call_test_table (
        col1 INTEGER
    )
    COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
    ;

    -- Simple Called procedure
CREATE OR REPLACE PROCEDURE called_procedure (param1 INTEGER)
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        INSERT INTO procedure_call_test_table
        VALUES (:param1);
    END;
$$;
Copy

Einfacher Call

Oracle
 CREATE OR REPLACE PROCEDURE simple_calling_procedure
AS
BEGIN
    called_procedure(1);
END;

CALL simple_calling_procedure();

SELECT * FROM procedure_call_test_table;
Copy
COL1|
----+
   1|

Copy
Snowflake Scripting
 CREATE OR REPLACE PROCEDURE simple_calling_procedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        CALL
        called_procedure(1);
    END;
$$;

CALL simple_calling_procedure();

--** SSC-FDM-0007 - MISSING DEPENDENT OBJECT "procedure_call_test_table" **

SELECT * FROM
    procedure_call_test_table;
Copy
COL1|
----+
   1|

Copy

Aufrufen einer Prozedur mit einem optionalen Parameter

Warnung

Dieses Beispiel enthält manuelle Eingriffe für einige funktionale Unterschiede und dient dazu, diese zu erklären. Weitere Informationen zu diesen Unterschieden finden Sie im Abschnitt „Bekannte Probleme“ weiter unten.

Oracle
 -- Procedure with optional parameters
CREATE OR REPLACE PROCEDURE proc_optional_parameters (param1 INTEGER, param2 INTEGER := 8, param3 INTEGER)
AS
BEGIN
    INSERT INTO procedure_call_test_table VALUES (param1);
    INSERT INTO procedure_call_test_table VALUES (param2);
    INSERT INTO procedure_call_test_table VALUES (param3);
END;

CREATE OR REPLACE PROCEDURE calling_procedure
AS
BEGIN
    -- positional convention
    proc_optional_parameters(1, 2, 3);
    
    -- named convention
    proc_optional_parameters(param1 => 4, param2 => 5, param3 => 6);
    
    -- named convention, second gets ommited
    proc_optional_parameters(param1 => 7, param3 => 9);
    
    -- named convention, different order
    proc_optional_parameters(param3 => 12, param1 => 10, param2 => 11);
END;

CALL calling_procedure();

SELECT * FROM procedure_call_test_table;
Copy
COL1|
----+
   1|
   2|
   3|
   4|
   5|
   6|
   7|
   8|
   9|
  10|
  11|
  12|

Copy
Snowflake Scripting
 -- Procedure with optional parameters
CREATE OR REPLACE PROCEDURE proc_optional_parameters
                                                     !!!RESOLVE EWI!!! /*** SSC-EWI-0002 - DEFAULT PARAMETERS MAY NEED TO BE REORDERED. SNOWFLAKE ONLY SUPPORTS DEFAULT PARAMETERS AT THE END OF THE PARAMETERS DECLARATIONS ***/!!!
                                                     (param1 INTEGER, param2 INTEGER DEFAULT 8, param3 INTEGER)
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        INSERT INTO procedure_call_test_table
        VALUES (:param1);
        INSERT INTO procedure_call_test_table
        VALUES (:param2);
        INSERT INTO procedure_call_test_table
        VALUES (:param3);
    END;
$$;

CREATE OR REPLACE PROCEDURE calling_procedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        CALL
        -- positional convention
        proc_optional_parameters(1, 2, 3);
        CALL

        -- named convention
        proc_optional_parameters(param1 => 4, param2 => 5, param3 => 6);
        CALL

        -- named convention, second gets ommited
        proc_optional_parameters(param1 => 7, param3 => 9);
        CALL

        -- named convention, different order
        proc_optional_parameters(param1 => 10, param2 => 11, param3 => 12);
    END;
$$;

CALL calling_procedure();


SELECT * FROM
    procedure_call_test_table;
Copy
COL1|
----+
   1|
   2|
   3|
   4|
   5|
   6|
   7|
   8|
   9|
  10|
  11|
  12|

Copy

Bekannte Probleme

1. Calling Subprograms with default values is not supported

Snowflake unterstützt nicht die Einstellung von Standardwerten für Parameter. Diese müssen also bei jedem Call eingegeben werden.

2. Named parameters are accepted, but not functionally equivalent

Diese Parameter verursachen keine Kompilierungsfehler, wenn sie in Snowflake ausgeführt werden; allerdings werden sie bei Aufrufen immer noch positioniert. Aus diesem Grund muss die Reihenfolge dieser Parameter überprüft werden. SnowConvert unterstützt weder die Überprüfung noch die Neuordnung dieser Parameter.

3. Calling Subprograms with Out Parameters is not supported

Snowflake bietet keine Unterstützung für Parametermodi, aber es wird eine Lösung implementiert, um deren Funktionalität zu emulieren. Weitere Informationen über die Transformation von Ausgabeparametern finden Sie im folgenden Artikel Ausgabeparameter.

Zugehörige EWIs

  1. [SSC-EWI-0002](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0002): Die Standardparameter müssen möglicherweise neu geordnet werden.

  2. [SSC-FDM-0007](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0007): Element mit fehlenden Abhängigkeiten.

RAISE

Beschreibung

Die Anweisung RAISE löst ausdrücklich eine Ausnahme aus.

Außerhalb eines Ausnahme-Handlers müssen Sie den Namen der Ausnahme angeben. Wenn Sie innerhalb eines Ausnahme-Handlers den Ausnahme-Namen weglassen, löst die Anweisung RAISE die aktuelle Ausnahme erneut aus. (Oracle PL/SQL Language Reference Raise Statement)

Die Anweisung wird von Snowflake Scripting vollständig unterstützt, aber bitte beachten Sie, dass es bei einigen COMMIT- und ROLLBACK-Anweisungen zu Unterschieden kommen kann.

 RAISE <exception_name> ;
Copy

Snowflake Scripting bietet Unterstützung für diese Anweisung.

 RAISE <exception_name> ;
Copy

Beispielhafte Quellcode-Muster

Einfache Ausnahme auslösen

Oracle
 CREATE OR REPLACE PROCEDURE simple_exception_throw_handle(param1 INTEGER)
IS
    my_exception EXCEPTION;
    my_other_exception EXCEPTION;
BEGIN
    IF param1 > 0
        THEN RAISE my_exception;
    END IF;
EXCEPTION
    WHEN my_exception THEN
        IF param1 = 1
            THEN RAISE;
        END IF;
        RAISE my_other_exception;
END;

--Completes without issue
CALL simple_exception_throw_handle(0);
--Throws my_exception
CALL simple_exception_throw_handle(1);
--Throws my_exception, catches then raises second my_other_exception
CALL simple_exception_throw_handle(2);
Copy
Call completed.
-----------------------------------------------------------------------
Error starting at line : 31 in command -
CALL simple_exception_throw_handle(1)
Error report -
ORA-06510: PL/SQL: unhandled user-defined exception
ORA-06512: at "SYSTEM.SIMPLE_EXCEPTION_THROW_HANDLE", line 12
ORA-06512: at "SYSTEM.SIMPLE_EXCEPTION_THROW_HANDLE", line 7
ORA-06512: at line 1
06510. 00000 -  "PL/SQL: unhandled user-defined exception"
*Cause:    A user-defined exception was raised by PL/SQL code, but
           not handled.
*Action:   Fix the problem causing the exception or write an exception
           handler for this condition. Or you may need to contact your
           application administrator or DBA.
-----------------------------------------------------------------------
Error starting at line : 33 in command -
CALL simple_exception_throw_handle(2)
Error report -
ORA-06510: PL/SQL: unhandled user-defined exception
ORA-06512: at "SYSTEM.SIMPLE_EXCEPTION_THROW_HANDLE", line 14
ORA-06510: PL/SQL: unhandled user-defined exception
ORA-06512: at "SYSTEM.SIMPLE_EXCEPTION_THROW_HANDLE", line 7
ORA-06512: at line 1
06510. 00000 -  "PL/SQL: unhandled user-defined exception"
*Cause:    A user-defined exception was raised by PL/SQL code, but
           not handled.
*Action:   Fix the problem causing the exception or write an exception
           handler for this condition. Or you may need to contact your
           application administrator or DBA.

Copy
Snowflake Scripting
 CREATE OR REPLACE PROCEDURE simple_exception_throw_handle (param1 INTEGER)
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        my_exception EXCEPTION;
        my_other_exception EXCEPTION;
    BEGIN
        IF (:param1 > 0) THEN
            RAISE my_exception;
        END IF;
        EXCEPTION
            WHEN my_exception THEN
            IF (:param1 = 1) THEN
                    RAISE;
            END IF;
                RAISE my_other_exception;
        END;
$$;

--Completes without issue
CALL simple_exception_throw_handle(0);

--Throws my_exception
CALL simple_exception_throw_handle(1);

--Throws my_exception, catches then raises second my_other_exception
CALL simple_exception_throw_handle(2);
Copy
Call Completed
-----------------------------------------------------------------------
Uncaught exception of type 'MY_EXCEPTION' on line 7 at position 9
-----------------------------------------------------------------------
Uncaught exception of type 'MY_OTHER_EXCEPTION' on line 14 at position 9

Copy

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIs

Keine zugehörigen EWIs.

RAISE_APPICATION_ERROR

Allgemeine Beschreibung

Mit der Prozedur RAISE_APPLICATION_ERROR können Sie benutzerdefinierte ORA- Fehlermeldungen aus gespeicherten Unterprogrammen ausgeben. Auf diese Weise können Sie Fehler an Ihre Anwendung melden und vermeiden, dass unbehandelte Ausnahmen zurückgegeben werden (Oracle-Dokumentation).

Oracle-Syntax

 raise_application_error(
      error_number, message[, {TRUE | FALSE}]);
Copy

Bemerkung

Die error_number ist eine negative Ganzzahl im Bereich -20000 … -20999 und message ist eine Zeichenfolge mit einer Länge von bis zu 2048 Bytes.

Wenn der optionale dritte Parameter TRUE lautet, wird der Fehler auf dem Stapel der vorherigen Fehler abgelegt. Wenn der Parameter FALSE lautet (die Vorgabe), ersetzt der Fehler alle vorherigen Fehler.

Die entsprechende Anweisung in Snowflake ist die RAISE-Klausel. Dennoch ist es erforderlich, die benutzerdefinierte Ausnahme als Variable zu deklarieren, bevor Sie die RAISE-Anweisung dafür aufrufen.

Snowflake-Syntax

 <exception_name> EXCEPTION [ ( <exception_number> , '<exception_message>' ) ] ;
Copy

Bemerkung

Weitere Informationen finden Sie in der folgenden Snowflake-Dokumentation.

Beispielhafte Quellcode-Muster

1. Exception in functions without declaring section

In diesem Szenario wird die Funktion ohne einen deklarierenden Abschnitt in eine Prozedur mit der Ausnahmedeklaration übersetzt. Bitte beachten Sie das:

  • Der Name der Ausnahmevariablen wird in Großbuchstaben angegeben.

  • Der Name der Ausnahmevariable basiert auf der Beschreibung und eine Endung besteht aus einem Ausnahmecodenamen gefolgt von einer fortlaufenden Nummer.

  • Der Deklarationsabschnitt wird erstellt, auch wenn die ursprüngliche Funktion oder Prozedur ihn nicht enthält.

Oracle

 CREATE OR REPLACE FUNCTION TEST(
    SAMPLE_A IN NUMBER DEFAULT NULL,
    SAMPLE_B IN NUMBER DEFAULT NULL
)
RETURN NUMBER
AS
BEGIN
    raise_application_error(-20001, 'First exception message', FALSE);
    raise_application_error(-20002, 'Second exception message');
  RETURN 1;
END TEST;
Copy
ORA-20001: First exception message

Copy

Snowflake

 --** SSC-FDM-0029 - USER DEFINED FUNCTION WAS TRANSFORMED TO SNOWFLAKE PROCEDURE **
CREATE OR REPLACE PROCEDURE TEST(
   SAMPLE_A NUMBER(38, 18) DEFAULT NULL,
   SAMPLE_B NUMBER(38, 18) DEFAULT NULL
)
RETURNS NUMBER(38, 18)
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
  DECLARE
    FIRST_EXCEPTION_MESSAGE_EXCEPTION_CODE_0 EXCEPTION (-20001, 'FIRST EXCEPTION MESSAGE');
    SECOND_EXCEPTION_MESSAGE_EXCEPTION_CODE_1 EXCEPTION (-20002, 'SECOND EXCEPTION MESSAGE');
  BEGIN
    --** SSC-FDM-OR0011 - ADD TO STACK OF ERRORS IS NOT SUPPORTED, BOOLEAN ARGUMENT FALSE WAS REMOVED. **
    RAISE FIRST_EXCEPTION_MESSAGE_EXCEPTION_CODE_0;
    RAISE SECOND_EXCEPTION_MESSAGE_EXCEPTION_CODE_1;
    RETURN 1;
  END;
$$;
Copy
FIRST EXCEPTION MESSAGE

Copy

2. Exception code number outside limits

Im folgenden Beispiel ist die Übersetzung im Body der Prozedur auskommentiert. Das liegt daran, dass der Code außerhalb der in Snowflake geltenden Grenzwerte liegt. Die Lösung besteht darin, den Ausnahmecode für einen verfügbaren Code im Abschnitt Abfrage zu ändern.

Oracle

 CREATE OR REPLACE FUNCTION TEST(
    SAMPLE_A IN NUMBER DEFAULT NULL,
    SAMPLE_B IN NUMBER DEFAULT NULL
)
RETURN NUMBER
AS
BEGIN
    raise_application_error(-20000, 'My exception message');
    RETURN 1;
END TEST;
Copy
ORA-20000: My exception message

Copy

Snowflake

 --** SSC-FDM-0029 - USER DEFINED FUNCTION WAS TRANSFORMED TO SNOWFLAKE PROCEDURE **
CREATE OR REPLACE PROCEDURE TEST(
   SAMPLE_A NUMBER(38, 18) DEFAULT NULL,
   SAMPLE_B NUMBER(38, 18) DEFAULT NULL
)
RETURNS NUMBER(38, 18)
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        MY_EXCEPTION_MESSAGE_EXCEPTION_CODE_0 EXCEPTION (-20000, 'MY EXCEPTION MESSAGE');
    BEGIN
        !!!RESOLVE EWI!!! /*** SSC-EWI-OR0099 - EXCEPTION CODE NUMBER EXCEEDS SNOWFLAKE SCRIPTING LIMITS ***/!!!
        RAISE MY_EXCEPTION_MESSAGE_EXCEPTION_CODE_0;
        RETURN 1;
    END;
$$;
Copy
 Invalid error code '-20,000'. Must be between -20,999 and -20,000

Copy

3. Exception stack functionality

Die Funktionalität des Ausnahmestapels wird in Snowflake nicht unterstützt und wurde aus der Ausnahmedeklaration entfernt.

Oracle

 CREATE OR REPLACE FUNCTION TEST(
    SAMPLE_A IN NUMBER DEFAULT NULL,
    SAMPLE_B IN NUMBER DEFAULT NULL
)
RETURN NUMBER
AS
BEGIN
    raise_application_error(-20001, 'My exception message', TRUE);
    RETURN 1;
END TEST;
Copy
ORA-20001: My exception message

Copy

Snowflake

 --** SSC-FDM-0029 - USER DEFINED FUNCTION WAS TRANSFORMED TO SNOWFLAKE PROCEDURE **
CREATE OR REPLACE PROCEDURE TEST(
   SAMPLE_A NUMBER(38, 18) DEFAULT NULL,
   SAMPLE_B NUMBER(38, 18) DEFAULT NULL
)
RETURNS NUMBER(38, 18)
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        MY_EXCEPTION_MESSAGE_EXCEPTION_CODE_0 EXCEPTION (-20001, 'MY EXCEPTION MESSAGE');
    BEGIN
        --** SSC-FDM-OR0011 - ADD TO STACK OF ERRORS IS NOT SUPPORTED, BOOLEAN ARGUMENT TRUE WAS REMOVED. **
        RAISE MY_EXCEPTION_MESSAGE_EXCEPTION_CODE_0;
        RETURN 1;
    END;
$$;
Copy
MY EXCEPTION MESSAGE

Copy

4. Multiple exceptions with the same exception code

Mehrere Ausnahmen mit der gleichen können im deklarierenden Abschnitt und in den RAISE-Anweisungen nebeneinander bestehen.

Oracle

 CREATE OR REPLACE FUNCTION TEST(
    SAMPLE_A IN NUMBER DEFAULT NULL,
    SAMPLE_B IN NUMBER DEFAULT NULL
)
RETURN NUMBER
AS
BEGIN
    IF TRUE THEN 
        raise_application_error(-20001, 'The first exception');
    ELSE 
        raise_application_error(-20001, 'Other exception inside');
    END IF;
    RETURN 1;
END TEST;
Copy
ORA-20000: The first exception

Copy

Snowflake

 --** SSC-FDM-0029 - USER DEFINED FUNCTION WAS TRANSFORMED TO SNOWFLAKE PROCEDURE **
CREATE OR REPLACE PROCEDURE TEST(
   SAMPLE_A NUMBER(38, 18) DEFAULT NULL,
   SAMPLE_B NUMBER(38, 18) DEFAULT NULL
)
RETURNS NUMBER(38, 18)
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        THE_FIRST_EXCEPTION_EXCEPTION_CODE_0 EXCEPTION (-20001, 'THE FIRST EXCEPTION');
        OTHER_EXCEPTION_INSIDE_EXCEPTION_CODE_1 EXCEPTION (-20001, 'OTHER EXCEPTION INSIDE');
    BEGIN
        IF (TRUE) THEN
            RAISE THE_FIRST_EXCEPTION_EXCEPTION_CODE_0;
            ELSE
            RAISE OTHER_EXCEPTION_INSIDE_EXCEPTION_CODE_1;
            END IF;
            RETURN 1;
    END;
$$;
Copy
THE FIRST EXCEPTION

Copy

Bekannte Probleme

  1. SQLREM-Funktion überprüft werden kann.

  2. Die Ausnahmecode-Nummer außerhalb der geltenden Grenzen in Snowflake muss in eine verfügbare Code-Ausnahme geändert werden.

  3. „Zu einem Fehlerstapel hinzufügen“ wird nicht unterstützt.

Zugehörige EWIs

  1. [SSC-EWI-OR0099](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0099): Der Ausnahmecode überschreitet das Snowflake Scripting-Limit.

  2. [SSC-FDM-0029](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0029): Eine benutzerdefinierte Funktion wurde in eine Snowflake-Prozedur umgewandelt.

  3. [SSC-FDM-OR0011](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/oracleFDM. md#ssc-fdm-or0011): Das boolesche Argument wurde entfernt, da die Option „zum Stapel hinzufügen“ nicht unterstützt wird.

UDF CALL

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

Beschreibung

Wie allgemein bekannt, werden nicht-skalare benutzerdefinierte Funktionen (UDFs) in Oracle in gespeicherte Prozeduren von Snowflake umgewandelt, um kompliziertere Funktionalitäten zu ermöglichen.

Diese Transformation ändert auch die Art und Weise, wie die Funktion aufgerufen wird, indem sie von einem traditionellen Funktionsaufruf zu einem Aufruf einer gespeicherten Prozedur übergeht.

Weitere Einzelheiten zum Aufruf von gespeicherten Prozeduren finden Sie in der hier verfügbaren Dokumentation: PROCEDURE CALL.

Beispielhafte Quellcode-Muster

Bemerkung

Betrachten Sie die nächste Funktion und die Tabellen für die folgenden Beispiele.

CREATE OR REPLACE FUNCTION sum_to_varchar_function(p_number1 IN NUMBER, p_number2 IN NUMBER)
RETURN VARCHAR
IS
    result VARCHAR(100);
BEGIN
    result := TO_CHAR(p_number1 + p_number2);
    RETURN result;
END sum_to_varchar_function;

CREATE TABLE example_table (
    id NUMBER,
    column1 NUMBER
);
INSERT INTO example_table VALUES (1, 15);

CREATE TABLE result_table (
    id NUMBER,
    result_col VARCHAR(100)
);
Copy
 CREATE OR REPLACE FUNCTION sum_to_varchar_function (p_number1 NUMBER(38, 18), p_number2 NUMBER(38, 18))
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "oracle",  "convertedOn": "11/14/2024",  "domain": "test" }}'
AS
$$
    WITH declaration_variables_cte1 AS
    (
        SELECT
            TO_CHAR(p_number1 + p_number2) AS
            result
    )
    SELECT
        result
    FROM
        declaration_variables_cte1
$$;

CREATE OR REPLACE TABLE example_table (
       id NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
       column1 NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/
   )
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "oracle",  "convertedOn": "11/14/2024",  "domain": "test" }}'
;

INSERT INTO example_table
VALUES (1, 15);

CREATE OR REPLACE TABLE result_table (
    id NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
       result_col VARCHAR(100)
   )
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "oracle",  "convertedOn": "11/14/2024",  "domain": "test" }}'
;
Copy

UDF-Aufruf

Oracle
 CREATE OR REPLACE PROCEDURE procedure_calling_function(param1 IN NUMBER)
IS
    result_value VARCHAR(200);
BEGIN 
    result_value := sum_to_varchar_function(3, param1);
    INSERT INTO result_table VALUES (1, result_value);
END;

BEGIN
    procedure_calling_function(5);
END;
Copy
ID	RESULT_COL
1	8

Copy
Snowflake Scripting
 CREATE OR REPLACE PROCEDURE procedure_calling_function (param1 NUMBER(38, 18))
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        result_value VARCHAR(200);
    BEGIN
        result_value := sum_to_varchar_function(3, :param1) !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'sum_to_varchar_function' NODE ***/!!!;
        INSERT INTO result_table
        VALUES (1, :result_value);
    END;
$$;

DECLARE
    call_results VARIANT;

    BEGIN
    CALL
    procedure_calling_function(5);
    RETURN call_results;
    END;
Copy
ID	RESULT_COL
1	8

Copy

UDF-Aufruf innerhalb einer Abfrage

Wenn ein Funktionsaufruf in eine Abfrage eingebettet ist, wird der Aufrufprozess komplizierter, da Snowflake nicht in der Lage ist, Prozeduren direkt in Abfragen aufzurufen. Um diese Beschränkung zu überwinden, wird der Aufruf der Prozedur außerhalb der Abfrage verschoben und das Ergebnis einer Variablen zugewiesen. Diese Variable wird dann in der Abfrage referenziert, wodurch eine Funktionsäquivalenz erreicht wird. Dieser Ansatz ermöglicht die Ausführung komplexerer Verhaltensweisen innerhalb von Snowflake-Abfragen unter Einhaltung der prozeduralen Einschränkungen.

Oracle
 CREATE OR REPLACE PROCEDURE procedure_calling_function(param1 IN NUMBER)
IS
    result_value VARCHAR(200);
    result_value2 VARCHAR(200);
BEGIN 
    SELECT
        sum_to_varchar_function(1, param1) AS result_column,
        sum_to_varchar_function(2, param1) AS result_column2
    INTO result_value, result_value2
    FROM example_table ext;

    INSERT INTO result_table VALUES (1, result_value);
    INSERT INTO result_table VALUES (2, result_value2);
END;

BEGIN
    procedure_calling_function(5);
END;
Copy
ID	RESULT_COL
1	6
2       7

Copy
Snowflake Scripting
 CREATE OR REPLACE PROCEDURE procedure_calling_function (param1 NUMBER(38, 18))
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        result_value VARCHAR(200);
        result_value2 VARCHAR(200);
    BEGIN
        SELECT
            sum_to_varchar_function(1, :param1) !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'sum_to_varchar_function' NODE ***/!!! AS result_column,
            sum_to_varchar_function(2, :param1) !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'sum_to_varchar_function' NODE ***/!!! AS result_column2
        INTO
            :result_value,
            :result_value2
        FROM
            example_table ext;

        INSERT INTO result_table
        VALUES (1, :result_value);
        INSERT INTO result_table
        VALUES (2, :result_value2);
    END;
$$;

DECLARE
    call_results VARIANT;

    BEGIN
    CALL
    procedure_calling_function(5);
    RETURN call_results;
    END;
Copy
ID	RESULT_COL
1	6
2       7

Copy

Bekannte Probleme

1. Unsupported Usage of UDFs in Queries with Query Dependencies

Beim Aufruf von benutzerdefinierten Funktionen (UDFs) innerhalb von Abfragen mit Abfrageabhängigkeiten werden Szenarien mit eingebetteten Funktionen mit Spalten als Argumente nicht unterstützt. Diese Beschränkung ergibt sich, weil auf die Spaltenwerte nicht von außerhalb der Abfrage zugegriffen werden kann. Beispiele für nicht unterstützte Szenarien sind:

 BEGIN
    SELECT
        sum_to_varchar_function(ext.col1, ext.col2) -- columns as arguments not supported
    INTO
        result_value
    FROM example_table ext;
END;
Copy

\ Die unterstützten Szenarien umfassen Funktionsaufrufe mit anderen Arten von Argumenten, wie z. B. Literalwerte, externe Variablen oder Parameter. Zum Beispiel:

 BEGIN
    SELECT
        sum_to_varchar_function(100, param1)
    INTO
        result_value
    FROM example_table ext;
END;
Copy

In den unterstützten Szenarien kann die Funktion effektiv migriert werden.

Zugehörige EWIs

  1. [SSC-EWI-0073](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0073): Überprüfung der Funktionsäquivalenz ausstehend.

  2. [SSC-FDM-0006](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0006): Zahlentyp-Spalte verhält sich in Snowflake möglicherweise nicht ähnlich.

  3. [SSC-FDM-0029](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0029): Eine benutzerdefinierte Funktion wurde in eine Snowflake-Prozedur umgewandelt.

WHILE

Beschreibung

Die Anweisung WHILE LOOP führt eine oder mehrere Anweisungen aus, während eine Bedingung erfüllt ist TRUE. \ (Oracle PL/SQL Language Reference WHILE Statement)

 WHILE boolean_expression
  LOOP statement... END LOOP [ label ] ;
Copy
 WHILE ( <condition> ) { DO | LOOP }
  <statement>;
  [ <statement>; ... ]
END { WHILE | LOOP } [ <label> ] ;
Copy

Die Verhaltensweise von Oracle WHILE kann auch durch die Verwendung der Anweisungen geändert werden:

Beispielhafte Quellcode-Muster

Simple While-Case

Dieser Fall ist funktionell gleichwertig.

Oracle
 CREATE TABLE while_testing_table
(
    iterator VARCHAR2(5)
);

CREATE OR REPLACE PROCEDURE while_procedure 
IS
I NUMBER := 1;
J NUMBER := 10;
BEGIN  
  WHILE I <> J LOOP
    INSERT INTO while_testing_table VALUES(TO_CHAR(I));
    I := I+1;    
  END LOOP;
END;

CALL while_procedure();
SELECT * FROM while_testing_table;
Copy
ITERATOR|
--------+
1       |
2       |
3       |
4       |
5       |
6       |
7       |
8       |
9       |

Copy
Snowflake Scripting
 CREATE OR REPLACE TABLE while_testing_table
(
    iterator VARCHAR(5)
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE PROCEDURE while_procedure ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
DECLARE
    I NUMBER(38, 18) := 1;
    J NUMBER(38, 18) := 10;
BEGIN
    WHILE (:I <> :J) LOOP
      INSERT INTO while_testing_table
      VALUES(TO_CHAR(:I));
      I := :I +1;
    END LOOP;
END;
$$;

CALL while_procedure();

SELECT * FROM
while_testing_table;
Copy
ITERATOR|
--------+
1       |
2       |
3       |
4       |
5       |
6       |
7       |
8       |
9       |

Copy

Known Issues

Es wurden keine Probleme gefunden.

Related EWIs

Keine zugehörigen EWIs.

CURSOR

Description

Bemerkung

Weitere Informationen über die Cursor-Deklaration finden Sie unter hier.

Dieser Abschnitt behandelt die Übersetzungsreferenz für Oracle Expliziter Cursor. Für Oracle Cursorvariablen gibt es keine Entsprechung in Snowflake Scripting.

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

Cursors sind Zeiger, mit denen Benutzer durch Abfrageergebnisse iterieren können. Weitere Informationen zu Oracle-Cursors finden Sie hier.

Cursordefinition

 CURSOR cursor
 [ ( cursor_parameter_dec [, cursor_parameter_dec ]... )]
   [ RETURN rowtype] IS select_statement ;
Copy

Cursor Open

 OPEN cursor [ ( cursor_parameter [ [,] actual_cursor_parameter ]... ) ] ;
Copy

Cursor Fetch

 FETCH { cursor | cursor_variable | :host_cursor_variable }
  { into_clause | bulk_collect_into_clause [ LIMIT numeric_expression ] } ;
Copy

Cursor Close

 CLOSE { cursor | cursor_variable | :host_cursor_variable } ;
Copy

Cursorattribute

 named_cursor%{ ISOPEN | FOUND | NOTFOUND | ROWCOUNT }
Copy

Cursor-FOR-Schleife

 [ FOR record IN
  { cursor [ ( cursor_parameter_dec
               [ [,] cursor_parameter_dec ]... )]
  | ( select_statement )
  }
    LOOP statement... END LOOP [label] ;
Copy

Snowflake Scripting bietet Unterstützung für Cursors, hat aber im Vergleich zu Oracle weniger Funktionen. Weitere Informationen zu diesen Cursors finden Sie hier.

Cursordeklaration

 <cursor_name> CURSOR FOR <query>
Copy

Cursor Open

 OPEN <cursor_name> [ USING (bind_variable_1 [, bind_variable_2 ...] ) ] ;
Copy

Cursor Fetch

 FETCH <cursor_name> INTO <variable> [, <variable> ... ] ;
Copy

Cursor Close

 CLOSE <cursor_name> ;
Copy

Cursor-FOR-Schleife

 FOR <row_variable> IN <cursor_name> DO
    statement;
    [ statement; ... ]
END FOR [ <label> ] ;
Copy

Beispielhafte Quellcode-Muster

1. Basic cursor example

 CREATE OR REPLACE PROCEDURE basic_cursor_sample AS
    var1 VARCHAR(20);
    CURSOR cursor1 IS SELECT region_name FROM hr.regions ORDER BY region_name;
BEGIN
    OPEN cursor1;
    FETCH cursor1 INTO var1;
    CLOSE cursor1;
END;
Copy
 CREATE OR REPLACE PROCEDURE basic_cursor_sample ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        var1 VARCHAR(20);
        cursor1 CURSOR
        FOR
            SELECT region_name FROM
                hr.regions
            ORDER BY region_name;
    BEGIN
        OPEN cursor1;
        FETCH cursor1 INTO
            :var1;
    CLOSE cursor1;
    END;
$$;
Copy

2. Explicit Cursor For Loop

 CREATE OR REPLACE PROCEDURE explicit_cursor_for_sample AS
    CURSOR cursor1 IS SELECT region_name FROM hr.regions ORDER BY region_name;
BEGIN
    FOR r1 IN cursor1 LOOP
        NULL;
    END LOOP;
END;
Copy
 CREATE OR REPLACE PROCEDURE explicit_cursor_for_sample ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        cursor1 CURSOR
        FOR
            SELECT region_name FROM
                hr.regions
            ORDER BY region_name;
    BEGIN
                OPEN cursor1;
                --** SSC-PRF-0004 - THIS STATEMENT HAS USAGES OF CURSOR FOR LOOP **
                FOR r1 IN cursor1 DO
            NULL;
                END FOR;
                CLOSE cursor1;
    END;
$$;
Copy

3. Implicit Cursor For Loop

 CREATE OR REPLACE PROCEDURE implicit_cursor_for_sample AS
BEGIN
    FOR r1 IN (SELECT region_name FROM hr.regions ORDER BY region_name) LOOP
        NULL;
    END LOOP;
END;
Copy
 CREATE OR REPLACE PROCEDURE implicit_cursor_for_sample ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        LET temporary_for_cursor_0 CURSOR
        FOR
            (SELECT region_name FROM
                    hr.regions
                ORDER BY region_name);
        --** SSC-PRF-0004 - THIS STATEMENT HAS USAGES OF CURSOR FOR LOOP **
        FOR r1 IN temporary_for_cursor_0 DO
            NULL;
        END FOR;
    END;
$$;
Copy

4. Parameterized Cursor

Sie können „?“ verwenden. In der Filterbedingung des Cursors im Deklarationsabschnitt definieren Sie die Bindungsvariable. Beim Öffnen des Cursors können wir die zusätzliche Syntax „USING <bind_variable\_1 >“ hinzufügen, um die Bindungsvariable zu übergeben.

Im Folgenden finden Sie einige Beispiele für Szenarien, die bei der Verwendung von Parametern in Cursors auftreten können:

4.1 Grundlegendes Beispiel für einen parametrisierten Cursor
 CREATE OR REPLACE PROCEDURE parameterized_cursor_for_sample AS
    CURSOR cursor1 (low number, high IN number) IS
        SELECT region_name FROM hr.regions WHERE region_id BETWEEN low AND high;
BEGIN
    OPEN cursor1(3,5);
    CLOSE cursor1;
END;
Copy
 CREATE OR REPLACE PROCEDURE parameterized_cursor_for_sample ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        cursor1 CURSOR
        FOR
            SELECT region_name FROM
                hr.regions
            WHERE region_id BETWEEN ? AND ?;
    BEGIN
                OPEN cursor1 USING (3, 5);
                CLOSE cursor1;
    END;
$$;
Copy
4.2 Parametrisierte Cursor mit mehreren Sendeparametern
 CREATE OR REPLACE PROCEDURE parameterized_cursor_for_sample AS
    CURSOR cursor1 (low number DEFAULT 2, high IN number DEFAULT 7) IS
        SELECT region_name FROM hr.regions 
        WHERE region_id BETWEEN low AND high OR low < 0;
BEGIN
    OPEN cursor1(3,5);
    OPEN cursor1(3);
    OPEN cursor1;
    OPEN cursor1(high => 15, low => 5);
    OPEN cursor1(high => 15);
    CLOSE cursor1;
END;
Copy
 CREATE OR REPLACE PROCEDURE parameterized_cursor_for_sample ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        cursor1 CURSOR
        FOR
            SELECT region_name FROM
                hr.regions
            WHERE region_id BETWEEN ? AND ?
                OR ? < 0;
    BEGIN
                OPEN cursor1 USING (3, 5, 3);
                OPEN cursor1 USING (3, 7, 3);
                OPEN cursor1 USING (2, 7, 2);
                OPEN cursor1 USING (5, 15, 5);
                OPEN cursor1 USING (2, 15, 2);
                CLOSE cursor1;
    END;
$$;
Copy
4.3 Parametrisierte Cursor mit Verwendung von Prozedurparametern in Abfragen
 CREATE OR REPLACE PROCEDURE parameterized_cursor_for_sample (high_param number) AS
    CURSOR cursor1 (low number DEFAULT 2) IS
        SELECT region_name FROM hr.regions 
        WHERE region_id BETWEEN low AND high_param;
BEGIN
    OPEN cursor1(3);
    CLOSE cursor1;
END;
CALL parameterized_cursor_for_sample(5);
Copy
 CREATE OR REPLACE PROCEDURE parameterized_cursor_for_sample (high_param NUMBER(38, 18))
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        cursor1 CURSOR
        FOR
            SELECT region_name FROM
                hr.regions
            WHERE region_id BETWEEN ? AND ?;
    BEGIN
                OPEN cursor1 USING (3, high_param);
                CLOSE cursor1;
    END;
$$;

CALL parameterized_cursor_for_sample(5);
Copy

5. Using Cursors In Fetch And For Loop

Cursor können mit der Anweisung FOR gesteuert werden, die es ermöglicht, jeden einzelnen Datensatz eines Cursors zu verarbeiten, während die Anweisung FETCH die vom Cursor zurückgegebenen Werte Datensatz für Datensatz in eine Reihe von Variablen schreibt, die PLSQL-Datensätze sein können

5.1 Cursors-FOR-Schleife
 CREATE OR REPLACE PROCEDURE p_cursors_for_loop AS
 datePlusOne TIMESTAMP;
 CURSOR c_product(low number, high number) IS 
    SELECT name, price, create_on FROM products WHERE price BETWEEN low AND high;
BEGIN
    FOR record_product IN c_product(3,5)
    LOOP
      datePlusOne := record_product.create_on + 1;
      INSERT INTO sold_items values(record_product.name, record_product.price, datePlusOne);
    END LOOP;
END;
Copy
 CREATE OR REPLACE PROCEDURE p_cursors_for_loop ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
 DECLARE
  datePlusOne TIMESTAMP(6);
  c_product CURSOR
  FOR
     SELECT
      OBJECT_CONSTRUCT('NAME', name, 'PRICE', price, 'CREATE_ON', create_on) sc_cursor_record FROM
      products
     WHERE price BETWEEN ? AND ?;
 BEGIN
  OPEN c_product USING (3, 5);
  --** SSC-PRF-0004 - THIS STATEMENT HAS USAGES OF CURSOR FOR LOOP **
  FOR record_product IN c_product DO
     LET record_product OBJECT := record_product.sc_cursor_record;
     datePlusOne :=
                    !!!RESOLVE EWI!!! /*** SSC-EWI-OR0036 - TYPES RESOLUTION ISSUES, ARITHMETIC OPERATION '+' MAY NOT BEHAVE CORRECTLY BETWEEN unknown AND Number ***/!!!
                    record_product.CREATE_ON + 1;
                    INSERT INTO sold_items
                    SELECT
      :record_product:NAME,
      :record_product:PRICE,
      :datePlusOne;
  END FOR;
  CLOSE c_product;
 END;
$$;
Copy
5.2 Cursors Fetch
CREATE OR REPLACE PROCEDURE p_cursors_fetch AS
 record_product products%rowtype;
 CURSOR c_product(low number, high number) IS 
    SELECT * FROM products WHERE price BETWEEN low AND high;
BEGIN
    OPEN c_product(3,5);
    LOOP
        FETCH c_product INTO record_product;
        EXIT WHEN c_product%notfound;
        INSERT INTO sold_items VALUES (record_product.name, record_product.price);
        INSERT INTO sold_items VALUES record_product;
    END LOOP;
    CLOSE c_product;
END;
Copy
 CREATE OR REPLACE PROCEDURE p_cursors_fetch ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
 DECLARE
  record_product OBJECT !!!RESOLVE EWI!!! /*** SSC-EWI-0036 - ROWTYPE DATA TYPE CONVERTED TO OBJECT ***/!!! := OBJECT_CONSTRUCT();
  c_product CURSOR
  FOR
     SELECT
      OBJECT_CONSTRUCT( *) sc_cursor_record FROM
      products
     WHERE price BETWEEN ? AND ?;
 BEGIN
  OPEN c_product USING (3, 5);
  LOOP
     --** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
     FETCH c_product INTO
      :record_product;
     IF (record_product IS NULL) THEN
      EXIT;
     END IF;
     INSERT INTO sold_items
     SELECT
      :record_product:NAME,
      :record_product:PRICE;
     INSERT INTO sold_items
     SELECT
      null !!!RESOLVE EWI!!! /*** SSC-EWI-OR0002 - COLUMNS FROM EXPRESSION products%rowtype NOT FOUND ***/!!!;
  END LOOP;
  CLOSE c_product;
 END;
$$;
Copy

Bekannte Probleme

1. RETURN clause is not supported in Snowflake Scripting Cursor Declaration

Die Cursordeklaration für Snowflake Scripting enthält diese Klausel nicht. Er kann aus der Oracle Cursordefinition entfernt werden, um eine Funktionsäquivalenz zu erhalten.

2. OPEN statement cannot pass values for declared arguments

Auch wenn Argumente für einen Cursor deklariert werden können, können ihre Werte in Snowflake Scripting nicht zugewiesen werden. Die beste Alternative ist die Verwendung der USING-Klausel mit Bindungsvariablen.

3. FETCH statement cannot use records

Snowflake Scripting unterstützt keine Datensätze. Es ist jedoch möglich, sie mithilfe des Datentyps OBJECT und der Methode OBJECT_CONSTRUCT() zu migrieren. Weitere Informationen finden Sie im Abschnitt Definition Datensatztyp.

4. FETCH BULK COLLECT INTO clause is not supported in Snowflake Scripting

Snowflake Scripting unterstützt die BULK COLLECTINTO -Klausel nicht. Es ist jedoch möglich, ARRAY_AGG zusammen mit einer zeitlichen Tabelle zu verwenden, um eine neue Variable mit den Daten zu konstruieren, die den Cursorinformationen entsprechen. Weitere Informationen finden Sie im Abschnitt Sammlung Bulk-Operationen.

5. Cursor attributes do not exist in Snowflake Scripting

Oracle-Cursor haben verschiedene Attribute, mit denen der Benutzer ihren Status überprüfen kann, z. B. ob sie geöffnet sind oder wie viele Zeilen abgerufen wurden. Diese Attribute zum Cursorstatus gibt es in Snowflake Scripting jedoch nicht.

6. The cursor’s query does not have access to the procedure’s variables and parameters

In Oracle hat die Abfrage in der Cursordeklaration Zugriff auf Prozedurvariablen und Parameter, in Snowflake Scripting jedoch nicht. Die Alternative dazu ist die Verwendung der USING-Klausel mit Bindungsvariablen. Weitere Informationen finden Sie unter diesem Abschnitt.

7. %NOTFOUND attribute is not supported in Snowflake Scripting Cursor

In Oracle kann vor dem ersten Abruf von einem geöffneten Cursor cursor_name%NOTFOUND verwendet werden, das TRUE zurückgibt, wenn der letzte Abruf keine Zeile geliefert hat, oder FALSE, wenn der letzte Abruf eine Zeile geliefert hat. Snowflake Scripting unterstützt die Verwendung dieses Attributs nicht. Stattdessen kann es validiert werden, wenn die dem Cursorergebnis zugewiesene Variable Werte enthält

Zugehörige EWIs

  1. [SSC-EWI-0036](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0036): Datentyp in einen anderen Datentyp konvertiert.

  2. [SSC-EWI-OR0002](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0002): Spalten aus Ausdruck nicht gefunden.

  3. [SSC-EWI-OR0036](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0036): Probleme bei der Auflösung von Typen, die arithmetische Operation verhält sich möglicherweise nicht korrekt zwischen Zeichenfolge und Datum.

  4. [SSC-PRF-0003](../../general/technical-documentation/issues-and-troubleshooting/performance-review/README. md#ssc-prf-0003): Fetch innerhalb einer Schleife wird als komplexes Muster betrachtet, was die Leistung von Snowflake beeinträchtigen kann.

  5. [SSC-PRF-0004](../../general/technical-documentation/issues-and-troubleshooting/performance-review/README. md#ssc-prf-0004): In dieser Anweisung wird eine Cursor-FOR-Schleife verwendet.

CURSOR DECLARATION

Bemerkung

Nicht relevante Anweisung.

Warnung

Beachten Sie, dass diese Anweisung aus der Migration entfernt wurde, da sie eine nicht relevante Syntax darstellt. Das bedeutet, dass sie in Snowflake nicht erforderlich ist.

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

Beschreibung

Dieser Abschnitt erklärt die Übersetzung der Cursordeklaration in Oracle. Weitere Informationen finden Sie in der folgenden Dokumentation zu Prozeduren und Cursors in Oracle.

Beispielhafte Quellcode-Muster

CURSOR DECLARATION

Beachten Sie, dass in diesem Beispiel die Anweisung CURSOR gelöscht wurde. Dies ist eine nicht relevante Syntax in der auf Snowflake ausgerichteten Transformation.

 CREATE PROCEDURE PROC_COLLECTIONS
AS
CURSOR C2 RETURN T1%TYPE;
BEGIN
    NULL;
END
Copy
 CREATE OR REPLACE PROCEDURE PROC_COLLECTIONS ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        NULL;
    END;
$$;
Copy

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIs

Keine zugehörigen EWIs.

Cursorvariablen

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

Beschreibung

Eine Cursor-Variable ist wie ein expliziter Cursor, der nicht auf eine Abfrage beschränkt ist.

(Oracle PL/SQL Language Reference Cursor-Variable Declaration)

Definition des Typs des Referenz-Cursors

 TYPE type IS REF CURSOR
  [ RETURN
    { {db_table_or_view | cursor | cursor_variable}%ROWTYPE
    | record%TYPE
    | record_type
    | ref_cursor_type
    }
  ] ;
Copy

Deklaration der Cursorvariablen

 cursor_variable type;
Copy

OPENFOR-Anweisung

 OPEN { cursor_variable | :host_cursor_variable}
  FOR select_statement [ using_clause ] ;
Copy

Warnung

Snowflake Scripting hat keine direkte Entsprechung zu Cursor-Variablen und der Anweisung OPEN FOR. Sie können jedoch mit verschiedenen Umgehungsmöglichkeiten emuliert werden, um eine funktionale Entsprechung zu erhalten.

Beispielhafte Quellcode-Muster

1. OPEN FOR statement with dynamic SQL inside a VARCHAR variable

 CREATE OR REPLACE PROCEDURE procedure1
AS
	query1 VARCHAR(200) := 'SELECT 123 FROM dual';
	cursor_var SYS_REFCURSOR;
BEGIN 
	OPEN cursor_var FOR query1;
	CLOSE cursor_var;
END;
Copy
 CREATE OR REPLACE PROCEDURE procedure1 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
	DECLARE
		query1 VARCHAR(200) := 'SELECT 123 FROM dual';
		cursor_var_res RESULTSET;
	BEGIN
		!!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
		cursor_var_res := (
			EXECUTE IMMEDIATE :query1
		);
		LET cursor_var CURSOR
		FOR
			cursor_var_res;
		OPEN cursor_var;
		CLOSE cursor_var;
	END;
$$;
Copy

2. OPEN FOR statement with dynamic SQL inside a string literal.

 CREATE OR REPLACE PROCEDURE procedure2
AS
    cursor_var SYS_REFCURSOR;
BEGIN
    OPEN cursor_var FOR 'SELECT 123 FROM dual';
    CLOSE cursor_var;
END;
Copy
 CREATE OR REPLACE PROCEDURE procedure2 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        cursor_var_res RESULTSET;
    BEGIN
        !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
        cursor_var_res := (
            EXECUTE IMMEDIATE 'SELECT 123 FROM dual'
        );
        LET cursor_var CURSOR
        FOR
            cursor_var_res;
        OPEN cursor_var;
        CLOSE cursor_var;
    END;
$$;
Copy

3. OPEN FOR statement with SELECT statement

 CREATE OR REPLACE PROCEDURE procedure3
AS
	cursor_var SYS_REFCURSOR;
BEGIN
	OPEN cursor_var FOR SELECT 123 FROM dual;
	CLOSE cursor_var;
END;
Copy
 CREATE OR REPLACE PROCEDURE procedure3 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
	DECLARE
		cursor_var_res RESULTSET;
	BEGIN
		LET cursor_var CURSOR
		FOR
			SELECT 123 FROM dual;
		OPEN cursor_var;
		CLOSE cursor_var;
	END;
$$;
Copy

4. Cursor Variable declared with REF CURSOR type

 CREATE OR REPLACE PROCEDURE procedure4
AS
    TYPE cursor_ref_type1 IS REF CURSOR;
    query1 VARCHAR(200) := 'SELECT 123 FROM dual';
    cursor_var cursor_ref_type1;
BEGIN 
    OPEN cursor_var FOR query1;
    CLOSE cursor_var;
END;
Copy
 CREATE OR REPLACE PROCEDURE procedure4 ()
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 REF CURSOR TYPE DEFINITION' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
--        TYPE cursor_ref_type1 IS REF CURSOR;
        query1 VARCHAR(200) := 'SELECT 123 FROM dual';
        cursor_var_res RESULTSET;
    BEGIN
        !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
        cursor_var_res := (
            EXECUTE IMMEDIATE :query1
        );
        LET cursor_var CURSOR
        FOR
            cursor_var_res;
        OPEN cursor_var;
        CLOSE cursor_var;
    END;
$$;
Copy

5. OPEN FOR statement with USING clause

 CREATE OR REPLACE PROCEDURE procedure5
AS
    query1 VARCHAR(200) := 'SELECT col1 FROM cursortable1 WHERE col1 = :a';
    column_filter INTEGER := 1;
    cursor_var SYS_REFCURSOR;
BEGIN 
    OPEN cursor_var FOR query1 USING column_filter;
    CLOSE cursor_var;
END;
Copy
 CREATE OR REPLACE PROCEDURE procedure5 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        query1 VARCHAR(200) := 'SELECT col1 FROM
   cursortable1
WHERE col1 = ?';
        column_filter INTEGER := 1;
        cursor_var_res RESULTSET;
    BEGIN
        !!!RESOLVE EWI!!! /*** SSC-EWI-0030 - THE STATEMENT BELOW HAS USAGES OF DYNAMIC SQL. ***/!!!
        cursor_var_res := (
            EXECUTE IMMEDIATE :query1 USING ( column_filter)
        );
        LET cursor_var CURSOR
        FOR
            cursor_var_res;
        OPEN cursor_var;
        CLOSE cursor_var;
    END;
$$;
Copy

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIs

  1. [SSC-EWI-0030](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0030): Die nachstehende Anweisung enthält Verwendungen von dynamischen SQL.

  2. [SSC-EWI-0058](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0058): Die Funktionalität wird derzeit nicht von Snowflake Scripting unterstützt.

PARAMETRIZED CURSOR

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

Beschreibung

Oracle unterstützt Parameter für Cursor, die deklariert werden. Snowflake Scripting unterstützt dieses Feature jedoch nicht, so dass die Deklaration und die Verwendung des Cursors nicht möglich sind.

Beispielcode

Oracle-Eingabecode:
 CREATE OR REPLACE PROCEDURE parametrized_cursor_sample AS
    CURSOR cursor1(param1 number) IS SELECT region_name FROM hr.regions where region_id = param1 ORDER BY region_name;
    var1 integer;
BEGIN
    OPEN cursor1(123);
    FETCH cursor1 INTO var1;
    CLOSE cursor1;
    FOR r1 IN cursor1(456) LOOP
        NULL;
    END LOOP;
END;
Copy
Ausgabecode:
 CREATE OR REPLACE PROCEDURE parametrized_cursor_sample ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        cursor1 CURSOR
        FOR
            SELECT
                OBJECT_CONSTRUCT('REGION_NAME', region_name) sc_cursor_record FROM
                hr.regions
            where region_id = ?
            ORDER BY region_name;
                var1 integer;
    BEGIN
                OPEN cursor1 USING (123);
                FETCH cursor1 INTO
            :var1;
    CLOSE cursor1;
                OPEN cursor1 USING (456);
                --** SSC-PRF-0004 - THIS STATEMENT HAS USAGES OF CURSOR FOR LOOP **
                FOR r1 IN cursor1 DO
            LET r1 OBJECT := r1.sc_cursor_record;
                   NULL;
                END FOR;
                CLOSE cursor1;
    END;
$$;
Copy

Empfehlungen

  • Versuchen Sie, Bindungen für die Abfrage im Cursor zu verwenden, und öffnen Sie den Cursor mit der Klausel USING. Denken Sie daran, dass ein Parameter, der mehrfach in einem einzigen Cursor verwendet wird, möglicherweise die mehrfache Übergabe der Variable in der USING-Klausel erfordert.

 CREATE OR REPLACE PROCEDURE PUBLIC.parametrized_cursor_sample_fixed ()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
   DECLARE
      var1 STRING;
      cursor1 CURSOR FOR SELECT region_name FROM hr.regions where region_id = ? ORDER BY region_name;
   BEGIN
      NULL;
      OPEN cursor1 USING (1);
      FETCH cursor1 INTO var1;
      CLOSE cursor1;
      OPEN cursor1 USING (2);
      FOR r1 IN cursor1 DO
         NULL;
      END FOR;
      CLOSE cursor1;
   END;
$$;
Copy
  • Ändern Sie den Cursor manuell, um Bindungen zu verwenden.

  • Wenn Sie weitere Unterstützung benötigen, können Sie uns eine E-Mail an snowconvert-support@snowflake.com senden

Zugehörige EWIs

  1. [SSC-PRF-0004](../../general/technical-documentation/issues-and-troubleshooting/performance-review/README. md#ssc-prf-0004): In dieser Anweisung wird eine Cursor-FOR-Schleife verwendet.

Umgehungsmöglichkeit für Cursor, die Parameter oder Prozedurvariablen verwenden

Beschreibung

Dieser Abschnitt beschreibt, wie Sie die Verwendung von Cursor-Parametern und Prozedurvariablen innerhalb der Abfrage eines Cursors simulieren können. Der Name der Variablen oder Parameter wird durch Bindungen mit dem Zeichen ? ersetzt. Wenn der Cursor dann geöffnet wird, sollten die Werte mit der USING-Klausel übergeben werden.

Bemerkung

Some parts in the output code are omitted for clarity reasons.

Copy

Cursor mit lokalen Variablen

Verwenden Sie Bindungen für die Abfrage im Cursor für verwendete Variablen- oder Prozedurparameter und öffnen Sie den Cursor mit der USING-Klausel.

 CREATE OR REPLACE PROCEDURE oracle_cursor_sample
AS
    like_value VARCHAR(255); 
    CURSOR c1 IS SELECT region_name FROM hr.regions WHERE region_name LIKE like_value ORDER BY region_name;  
    r_name VARCHAR(255);
BEGIN
    like_value := 'E%';
    OPEN c1;
    FETCH c1 INTO r_name;
    CLOSE c1;
    like_value := 'A%';
    FOR r1 IN c1 LOOP
        NULL;
    END LOOP;
END;
Copy
 CREATE OR REPLACE PROCEDURE oracle_cursor_sample ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        like_value VARCHAR(255);
        c1 CURSOR
        FOR
            SELECT region_name FROM
                hr.regions
            WHERE region_name LIKE ?
            ORDER BY region_name;
        r_name VARCHAR(255);
    BEGIN
        like_value := 'E%';
        OPEN c1 USING (like_value);
        FETCH c1 INTO
            :r_name;
    CLOSE c1;
        like_value := 'A%';
        OPEN c1;
        --** SSC-PRF-0004 - THIS STATEMENT HAS USAGES OF CURSOR FOR LOOP **
        FOR r1 IN c1 DO
            NULL;
        END FOR;
        CLOSE c1;
    END;
$$;
Copy

Cursor mit Parametern

Verwenden Sie Bindungen für die Abfrage im Cursor für jeden verwendeten Parameter und öffnen Sie den Cursor mit der USING-Klausel. Denken Sie daran, dass ein Parameter, der mehrfach in einem einzigen Cursor verwendet wird, möglicherweise die mehrfache Übergabe der Variable in der USING-Klausel erfordert.

 CREATE OR REPLACE PROCEDURE parametrized_cursor_sample AS
    CURSOR cursor1(param1 number) IS SELECT region_name FROM hr.regions where region_id = param1 ORDER BY region_name;
    var1 integer;
BEGIN
    OPEN cursor1(123);
    FETCH cursor1 INTO var1;
    CLOSE cursor1;
    FOR r1 IN cursor1(456) LOOP
        NULL;
    END LOOP;
END;
Copy
 CREATE OR REPLACE PROCEDURE parametrized_cursor_sample ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        cursor1 CURSOR
        FOR
            SELECT
                OBJECT_CONSTRUCT('REGION_NAME', region_name) sc_cursor_record FROM
                hr.regions
            where region_id = ?
            ORDER BY region_name;
                var1 integer;
    BEGIN
                OPEN cursor1 USING (123);
                FETCH cursor1 INTO
            :var1;
    CLOSE cursor1;
                OPEN cursor1 USING (456);
                --** SSC-PRF-0004 - THIS STATEMENT HAS USAGES OF CURSOR FOR LOOP **
                FOR r1 IN cursor1 DO
            LET r1 OBJECT := r1.sc_cursor_record;
                   NULL;
                END FOR;
                CLOSE cursor1;
    END;
$$;
Copy

Zugehörige EWIs

  1. [SSC-PRF-0004](../../general/technical-documentation/issues-and-troubleshooting/performance-review/README. md#ssc-prf-0004): Diese Anweisung verwendet eine Cursor-FOR-Schleife

CREATE FUNCTION

Beschreibung

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

Eine gespeicherte Funktion (auch Benutzerfunktion oder benutzerdefinierte Funktion genannt) ist eine Reihe von PL/SQL-Anweisungen, die Sie über einen Namen aufrufen können. Gespeicherte Funktionen sind Prozeduren sehr ähnlich, mit dem Unterschied, dass eine Funktion einen Wert an die Umgebung zurückgibt, in der sie aufgerufen wurde. Benutzerfunktionen können als Teil eines SQL-Ausdrucks verwendet werden.

Eine Aufrufspezifikation deklariert eine Java-Methode oder eine Routine der dritten Generation (3GL), so dass sie von PL/SQL aufgerufen werden kann. Sie können auch die Anweisung CALL SQL verwenden, um eine solche Methode oder Routine aufzurufen. Die Aufrufspezifikation teilt der Oracle-Datenbank mit, welche Java-Methode oder welche benannte Funktion in welcher gemeinsamen Bibliothek bei einem Aufruf aufgerufen werden soll. Sie teilt der Datenbank auch mit, welche Typkonvertierungen für die Argumente und den Rückgabewert vorgenommen werden sollen. Oracle SQL Language Reference Create Function.

Oracle-Syntax

Weitere Informationen zur Create-Funktion in Oracle finden Sie hier.

 CREATE [ OR REPLACE ] [ EDITIONABLE | NONEDITIONABLE ]
FUNCTION
[ schema. ] function_name
  [ ( parameter_declaration [, parameter_declaration]... ) ] RETURN datatype 
[ sharing_clause ]
  [ { invoker_rights_clause
    | accessible_by_clause
    | default_collation_clause    
    | deterministic_clause
    | parallel_enable_clause
    | result_cache_clause 
    | aggregate_clause
    | pipelined_clause
    | sql_macro_clause
       }...
  ]
{ IS | AS } { [ declare_section ] 
    BEGIN statement ...
    [ EXCEPTION exception_handler [ exception_handler ]... ]
    END [ name ] ;
      |
    { java_declaration | c_declaration } } ;
Copy

Snowflake-Syntax

Snowflake erlaubt 3 verschiedene Sprachen in den benutzerdefinierten Funktionen:

  • SQL

  • JavaScript

  • Java

Vorerst wird SnowConvert nur SQL und JavaScript als Zielsprachen unterstützen.

Weitere Informationen zur Create-Funktion in Snowflake finden Sie hier.

Bemerkung

Benutzerdefinierte SQL-Funktionen unterstützen nur eine Abfrage als ihren Body. Sie können aus der Datenbank lesen, dürfen aber nicht in ihr schreiben oder sie verändern (Skalare SQL UDFs).

 CREATE [ OR REPLACE ] [ SECURE ] FUNCTION <name> ( [ <arg_name> <arg_data_type> ] [ , ... ] )
  RETURNS { <result_data_type> | TABLE ( <col_name> <col_data_type> [ , ... ] ) }
  [ [ NOT ] NULL ]
  [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
  [ VOLATILE | IMMUTABLE ]
  [ COMMENT = '<string_literal>' ]
  AS '<function_definition>'
Copy

Bemerkung

Benutzerdefinierte JavaScript-Funktionen erlauben mehrere Anweisungen in ihren Bodys, können aber keine Abfrage der Datenbank durchführen. (Skalare JavaScript UDFs).

 CREATE [ OR REPLACE ] [ SECURE ] FUNCTION <name> ( [ <arg_name> <arg_data_type> ] [ , ... ] )
  RETURNS { <result_data_type> | TABLE ( <col_name> <col_data_type> [ , ... ] ) }
  [ [ NOT ] NULL ]
  LANGUAGE JAVASCRIPT
  [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
  [ VOLATILE | IMMUTABLE ]
  [ COMMENT = '<string_literal>' ]
  AS '<function_definition>'
Copy

Beispielhafte Quellcode-Muster

Beispielhafte Hilfsdaten

Bemerkung

Dieser Code wurde zum besseren Verständnis der Beispiele ausgeführt:

 CREATE TABLE table1 (col1 int, col2 int, col3 varchar2(250), col4 varchar2(250), col5 date);

INSERT INTO table1 VALUES (1, 11, 'val1_1', 'val1_2', TO_DATE('2004/05/03', 'yyyy-MM-dd'));
INSERT INTO table1 VALUES (2, 22, 'val2_1', 'val2_2', TO_DATE('2014/05/03', 'yyyy-MM-dd'));
INSERT INTO table1 VALUES (3, 33, 'val3_1', 'val3_2', TO_DATE('2024/05/03', 'yyyy-MM-dd'));
Copy
 CREATE OR REPLACE TABLE table1 (col1 int,
col2 int,
col3 VARCHAR(250),
col4 VARCHAR(250),
col5 TIMESTAMP /*** SSC-FDM-OR0042 - DATE TYPE COLUMN HAS A DIFFERENT BEHAVIOR IN SNOWFLAKE. ***/
)
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "oracle",  "convertedOn": "07/25/2024" }}'
;

INSERT INTO table1
VALUES (1, 11, 'val1_1', 'val1_2', TO_DATE('2004/05/03', 'yyyy-MM-dd'));

INSERT INTO table1
VALUES (2, 22, 'val2_1', 'val2_2', TO_DATE('2014/05/03', 'yyyy-MM-dd'));

INSERT INTO table1
VALUES (3, 33, 'val3_1', 'val3_2', TO_DATE('2024/05/03', 'yyyy-MM-dd'));
Copy

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIS

  1. [SSC-FDM-OR0042](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/oracleFDM. md#ssc-fdm-or0042): In Zeitstempel umgewandelter Datumstyp zeigt eine andere Verhaltensweise

Cursor für eine Rückgabevariable

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

Dieses Muster definiert eine Funktion in Oracle PL/SQL, die einen Cursor verwendet, um einen einzelnen Wert zu holen und ihn zurückzugeben.

Komponenten:

  1. Funktionsdeklaration:

    • CREATE FUNCTION functionName(parameters) RETURN returnType

    • Deklariert die Funktion mit Eingabeparametern und dem Rückgabetyp.

  2. Variable Deklarationen:

    • Deklariert Variablen, einschließlich der Rückgabevariablen.

  3. Cursordeklaration:

    • CURSOR cursorName IS SELECT singleColumn FROM... WHERE... [AND col1 = localVar1];

    • Definiert einen Cursor zur Auswahl einer einzelnen Spalte aus einer Tabelle mit optionalen Filterbedingungen.

  4. BEGIN-END-Block:

    • Zuordnung von Variablen.

    • Öffnet den Cursor.

    • Rufen Sie das Ergebnis in die Rückgabevariable ab.

    • Schließt den Cursor.

    • Gibt den abgefragten Wert zurück.

In diesem Fall werden die Variablen in einen allgemeinen Tabellenausdruck (CTE) umgewandelt. Sowie die Abfrage innerhalb des Cursors, zu der zusätzlich die FETCH FIRST 1 ROW ONLY-Klausel hinzugefügt wird, um die Verhaltensweise von FETCH CURSOR zu simulieren.

RETURN-Anweisung wird in die endgültige SELECT-Anweisung umgewandelt.

Abfragen

 CREATE OR REPLACE FUNCTION func1 (
   company_ IN VARCHAR2,
   book_id_ IN DATE,
   object_id_ IN VARCHAR2 ) RETURN INTEGER
IS
   temp_ table1.col2%TYPE;
   CURSOR get_attr IS
      SELECT col2
      FROM table1
      WHERE col3 = company_
      AND   col4 = object_id_
      AND   col5 = book_id_;
BEGIN
   OPEN get_attr;
   FETCH get_attr INTO temp_;
   CLOSE get_attr;
   RETURN temp_;
END func1;
Copy
 CREATE OR REPLACE FUNCTION func1 (company_ VARCHAR, book_id_ TIMESTAMP /*** SSC-FDM-OR0042 - DATE TYPE COLUMN HAS A DIFFERENT BEHAVIOR IN SNOWFLAKE. ***/, object_id_ VARCHAR)
RETURNS INTEGER
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "oracle",  "convertedOn": "09/06/2024" }}'
AS
$$
   WITH declaration_variables_cte1 AS
   (
      SELECT
         (
         SELECT col2
         FROM table1
         WHERE col3 = company_
         AND   col4 = object_id_
         AND   col5 = book_id_
         FETCH FIRST 1 ROW ONLY) AS temp_
   )
   SELECT
      temp_
   FROM
      declaration_variables_cte1
$$;
Copy
FUNC1()          | 
-----------------+ 
2004-05-03.      |

Copy
 CREATE FUNCTION func2 (
   fa_period_   IN NUMBER,
   to_date_     IN DATE DEFAULT NULL,
   from_date_   IN DATE DEFAULT NULL ) RETURN NUMBER
IS
   value_                    NUMBER;
   cond_date_to_             DATE;
   cond_date_from_           DATE;
   CURSOR get_acq_value IS
      SELECT NVL(SUM(col1),0)
      FROM   table1
      WHERE  col3                   IN (DECODE(fa_period_, 1, 'val1_1', 'val2_1'))
      AND    col5           <= cond_date_to_
      AND    col5           >= cond_date_from_;
BEGIN
   value_ := 0;
   cond_date_to_       := Get_Cond_Date( to_date_, 'MAX' );
   cond_date_from_     := Get_Cond_Date( from_date_, 'MIN' );
   OPEN get_acq_value;
   FETCH get_acq_value INTO value_;
   CLOSE get_acq_value;
   RETURN (NVL(value_,0));
END func2;
Copy
 CREATE OR REPLACE FUNCTION func2 (fa_period_ NUMBER(38, 18),
  to_date_ TIMESTAMP /*** SSC-FDM-OR0042 - DATE TYPE COLUMN HAS A DIFFERENT BEHAVIOR IN SNOWFLAKE. ***/ DEFAULT NULL,
  from_date_ TIMESTAMP /*** SSC-FDM-OR0042 - DATE TYPE COLUMN HAS A DIFFERENT BEHAVIOR IN SNOWFLAKE. ***/ DEFAULT NULL )
RETURNS NUMBER(38, 18)
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "oracle",  "convertedOn": "09/06/2024" }}'
AS
$$
   WITH declaration_variables_cte1 AS
   (
      SELECT
         0 AS
         value_,
         Get_Cond_Date( to_date_, 'MAX' ) !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'Get_Cond_Date' NODE ***/!!! AS
         cond_date_to_,
         Get_Cond_Date( from_date_, 'MIN' ) !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'Get_Cond_Date' NODE ***/!!! AS
         cond_date_from_
   ),
   declaration_variables_cte2 AS
   (
      SELECT
         (
         SELECT NVL(SUM(col1),0)
         FROM   table1
         WHERE  col3                   IN (DECODE(fa_period_, 1, 'val1_1', 'val2_1'))
         AND    col5           <= cond_date_to_
         AND    col5           >= cond_date_from_
         FETCH FIRST 1 ROW ONLY) AS value_,
         cond_date_to_,
         cond_date_from_
      FROM
         declaration_variables_cte1
   )
   SELECT
      (NVL(value_,0))
   FROM
      declaration_variables_cte2
$$;
Copy
FUNC1()          | 
-----------------+ 
2004-05-03.      |

Copy

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIS

  1. [SSC-FDM-OR0042](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/oracleFDM. md#ssc-fdm-or0042): In Zeitstempel umgewandelter Datumstyp zeigt eine andere Verhaltensweise

  2. [SSC-EWI-0073](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0073): Überprüfung der Funktionsäquivalenz ausstehend.

Cursor mit IF-Anweisung

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

Dieses Muster definiert eine Funktion, die bedingt einen Cursor verwendet, um einen Wert zu holen und zurückzugeben, der auf einer IF-Anweisung basiert.

Komponenten:

  1. Funktionsdeklaration:

    • CREATE FUNCTION functionName(parameters) RETURN returnType

    • Deklariert die Funktion mit Eingabeparametern und dem Rückgabetyp.

  2. Cursordeklaration:

    • CURSOR cursorName IS SELECT singleColumn FROM... WHERE... [AND col1 = localVar1];

    • Definiert einen Cursor zur Auswahl einer einzelnen Spalte aus einer Tabelle mit optionalen Filterbedingungen.

  3. Variablendeklaration:

    • Deklariert Variablen, einschließlich der Rückgabevariablen.

  4. BEGIN-END Block mit IF-Anweisung:

    • Zuordnung von Variablen.

    • Prüfen Sie, ob eine Bedingung „true“ ist.

    • Wenn „true“, wird der Cursor geöffnet, das Ergebnis in die Rückgabevariable geholt, der Cursor geschlossen und der abgefragte Wert zurückgegeben. (Der Cursor kann auch im Block ELSE geöffnet werden und muss dieselben Bedingungen erfüllen)

    • Der ELSE-Block ist optional. Wenn er existiert, sollte er nur eine einzige Anweisung enthalten, die eine Zuweisung oder eine RETURN-Anweisung sein kann.

Die Variablen werden in einen allgemeinen Tabellenausdruck umgewandelt (CTE). Sowie die Abfrage innerhalb des Cursors, zu der zusätzlich die FETCH FIRST 1 ROW ONLY-Klausel hinzugefügt wird, um die Verhaltensweise von FETCH CURSOR zu simulieren.

IF/ELSE Anweisung kann mit Hilfe der CASE EXPRESSION innerhalb der SELECT-Anweisung behandelt werden, so dass Bedingungen innerhalb der Abfragen möglich sind. RETURN-Anweisung wird in die endgültige SELECT-Anweisung umgewandelt.

Abfragen

 CREATE OR REPLACE FUNCTION func1 (
   company_          IN NUMBER) RETURN NUMBER
IS
   CURSOR getmaxperiod IS
      SELECT max(col2)
      FROM   table1;
   max_period_               NUMBER := 12;
BEGIN
   IF 1 = 1 THEN
      OPEN   getmaxperiod;
      FETCH  getmaxperiod INTO max_period_ ;
      CLOSE  getmaxperiod;
      RETURN max_period_;
   ELSE
      RETURN NULL;
   END IF;
END func1;
Copy
 CREATE OR REPLACE FUNCTION func1 (company_ NUMBER(38, 18))
RETURNS NUMBER(38, 18)
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "oracle",  "convertedOn": "09/06/2024" }}'
AS
$$
   WITH declaration_variables_cte0 AS
   (
      SELECT
         12 AS
         max_period_
   ),
   declaration_variables_cte1 AS
   (
      SELECT
         CASE
            WHEN 1 = 1
               THEN (
               SELECT max(col2)
               FROM   table1
               FETCH FIRST 1 ROW ONLY)
            ELSE NULL
         END AS max_period_
      FROM
         declaration_variables_cte0
   )
   SELECT
      max_period_
   FROM
      declaration_variables_cte1
$$;
Copy
FUNC2(0)      |
--------------+
NULL          |

FUNC2(1)      |
--------------+
33            |

Copy
 CREATE OR REPLACE FUNCTION func2(
   company_          IN NUMBER) RETURN NUMBER
IS
   CURSOR getmaxperiod IS
      SELECT max(col2)
      FROM   table1;
   max_period_               NUMBER := 1;
BEGIN
   max_period_:= 2;
   IF company_ = 1 THEN
      RETURN max_period_ * 2;
   ELSE
      OPEN   getmaxperiod;
      FETCH  getmaxperiod INTO max_period_ ;
      CLOSE  getmaxperiod;
      RETURN max_period_;
   END IF;
END func2;
Copy
 CREATE OR REPLACE FUNCTION func2 (company_ NUMBER(38, 18))
RETURNS NUMBER(38, 18)
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "oracle",  "convertedOn": "09/06/2024" }}'
AS
$$
   WITH declaration_variables_cte0 AS
   (
      SELECT
         1 AS
         max_period_
   ),
   declaration_variables_cte1 AS
   (
      SELECT
         2 AS
         max_period_
      FROM
         declaration_variables_cte0
   ),
   declaration_variables_cte2 AS
   (
      SELECT
         CASE
            WHEN company_ = 1
               THEN max_period_ * 2
            ELSE (
            SELECT max(col2)
            FROM   table1
            FETCH FIRST 1 ROW ONLY)
         END AS max_period_
      FROM
         declaration_variables_cte1
   )
   SELECT
      max_period_
   FROM
      declaration_variables_cte2
$$;
Copy
FUNC2(0)      |
--------------+
33            |

FUNC2(1)      |
--------------+
2             |

Copy
 CREATE OR REPLACE FUNCTION func3 (
   company_          IN NUMBER) RETURN NUMBER
IS
   CURSOR getmaxperiod IS
      SELECT max(col2)
      FROM   table1;
   max_period_               NUMBER := 0;
BEGIN
   IF company_ = 1 THEN
      OPEN   getmaxperiod;
      FETCH  getmaxperiod INTO max_period_ ;
      CLOSE  getmaxperiod;
   END IF;
   RETURN max_period_;
END func10;
Copy
 CREATE OR REPLACE FUNCTION func3 (company_ NUMBER(38, 18))
RETURNS NUMBER(38, 18)
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "oracle",  "convertedOn": "09/06/2024" }}'
AS
$$
   WITH declaration_variables_cte0 AS
   (
      SELECT
         0 AS
         max_period_
   ),
   declaration_variables_cte1 AS
   (
      SELECT
         CASE
            WHEN company_ = 1
               THEN (
               SELECT max(col2)
               FROM   table1
               FETCH FIRST 1 ROW ONLY)
            ELSE max_period_
         END AS max_period_
      FROM
         declaration_variables_cte0
   )
   SELECT
      max_period_
   FROM
      declaration_variables_cte1
$$;
Copy
FUNC2(0)      |
--------------+
0             |

FUNC2(1)      |
--------------+
33            |

Copy

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIS

Keine zugehörigen EWIs.

Mehrere IFs-Anweisung

Dieses Muster definiert eine Funktion, die bedingte Anweisungen über lokale Variablen verwendet.

Komponenten:

  1. Funktionsdeklaration:

    • CREATE FUNCTION functionName(parameters) RETURN returnType

    • Deklariert die Funktion mit Eingabeparametern und dem Rückgabetyp.

  2. Variablendeklaration:

    • Deklariert Variablen, einschließlich der Rückgabevariablen.

  3. BEGIN-END Block mit IF-Anweisung:

    • Prüfen Sie, ob eine Bedingung „true“ ist.

    • Jeder Fall wird verwendet, um einen Wert über dieselbe Variable zuzuweisen.

Konvertierung:

DECLARE SECTION: Variablen mit Standardausdruck werden in einen allgemeinen Tabellenausdruck verschoben.

IF/ELSE-Anweisung kann mit Hilfe der CASE EXPRESSION innerhalb der SELECT-Anweisung behandelt werden, was Bedingungen innerhalb der Abfragen ermöglicht.

RETURN-Anweisung wird in die endgültige SELECT-Anweisung umgewandelt.

 CREATE OR REPLACE FUNCTION Case1 (
   in_date_ IN DATE,
   min_max_ IN VARCHAR2 )
RETURN DATE
IS
   cond_date_  DATE := CURRENT_DATE;
BEGIN
   IF ( in_date_ IS NULL ) THEN
      IF ( min_max_ = 'MIN' ) THEN
         cond_date_ := FOO1();
      ELSE
         cond_date_ := FOO2();
      END IF;
   ELSE
      cond_date_ := TRUNC(in_date_);
   END IF;
   RETURN cond_date_;
END Case1;
Copy
 CREATE OR REPLACE FUNCTION Case1 (in_date_ TIMESTAMP /*** SSC-FDM-OR0042 - DATE TYPE COLUMN HAS A DIFFERENT BEHAVIOR IN SNOWFLAKE. ***/, min_max_ VARCHAR)
RETURNS TIMESTAMP /*** SSC-FDM-OR0042 - DATE TYPE COLUMN HAS A DIFFERENT BEHAVIOR IN SNOWFLAKE. ***/
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "oracle",  "convertedOn": "09/06/2024" }}'
AS
$$
   WITH declaration_variables_cte0 AS
   (
      SELECT
         CURRENT_DATE AS
         cond_date_
   ),
   declaration_variables_cte1 AS
   (
      SELECT
         CASE
            WHEN ( in_date_ IS NULL )
               THEN CASE
                  WHEN ( min_max_ = 'MIN' )
                     THEN FOO1() !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'FOO1' NODE ***/!!!
                  ELSE FOO2() !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'FOO2' NODE ***/!!!
               END
            ELSE TRUNC(in_date_, 'DD')
         END AS cond_date_
      FROM
         declaration_variables_cte0
   )
   SELECT
      cond_date_
   FROM
      declaration_variables_cte1
$$;
Copy
 CREATE OR REPLACE FUNCTION Case2 (
   year_        IN NUMBER,
   id           IN NUMBER) 
   RETURN VARCHAR2
IS
   base_value_        NUMBER;
   fully_depritiated_ VARCHAR2(5);
   residual_value_    NUMBER;
   acc_depr_prev_     NUMBER;
   acc_depr_          NUMBER;
BEGIN

   base_value_     := FOO1(year_, id);
   acc_depr_       := FOO2(year_, id);
   acc_depr_prev_  := FOO3(year_, id);
   residual_value_ := NVL(base_value_,0) -(acc_depr_ + acc_depr_prev_);

   IF (residual_value_=0 AND base_value_!=0) THEN
      fully_depritiated_ := 'TRUE';
   ELSE
      fully_depritiated_ := 'FALSE';
   END IF;

   RETURN fully_depritiated_;
END Case2;
Copy
 CREATE OR REPLACE FUNCTION Case2 (year_ NUMBER(38, 18), id NUMBER(38, 18))
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "oracle",  "convertedOn": "09/06/2024" }}'
AS
$$
   WITH declaration_variables_cte1 AS
   (
      SELECT
         FOO1(year_, id) !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'FOO1' NODE ***/!!! AS

         base_value_,
         FOO2(year_, id) !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'FOO2' NODE ***/!!! AS
         acc_depr_,
         FOO3(year_, id) !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'FOO3' NODE ***/!!! AS
         acc_depr_prev_,
         !!!RESOLVE EWI!!! /*** SSC-EWI-OR0036 - TYPES RESOLUTION ISSUES, ARITHMETIC OPERATION '-' MAY NOT BEHAVE CORRECTLY BETWEEN ExactNumeric AND unknown ***/!!!
         NVL(base_value_,0) -(acc_depr_ + acc_depr_prev_) AS
         residual_value_,
         CASE
            WHEN (residual_value_=0 AND base_value_!=0)
               THEN 'TRUE'
            ELSE 'FALSE'
         END AS fully_depritiated_
   )
   SELECT
      fully_depritiated_
   FROM
      declaration_variables_cte1
$$;
Copy
 CREATE OR REPLACE FUNCTION Case2_1 (
   year_        IN NUMBER,
   id           IN NUMBER) 
   RETURN VARCHAR2
IS
   base_value_        NUMBER;
   fully_depritiated_ VARCHAR2(5);
   residual_value_    NUMBER;
   acc_depr_prev_     NUMBER;
   acc_depr_          NUMBER;
BEGIN

   base_value_     := FOO1(year_, id);
   acc_depr_       := FOO2(year_, id);
   acc_depr_prev_  := FOO3(year_, id);
   residual_value_ := NVL(base_value_,0) -(acc_depr_ + acc_depr_prev_);

   IF (residual_value_=0 AND base_value_!=0) THEN
      fully_depritiated_ := 'TRUE';
   ELSE
      fully_depritiated_ := 'FALSE';
   END IF;

   fully_depritiated := fully_depritiated || ' CONCAT FOR TESTING';
   fully_depritiated := fully_depritiated || ' CONCAT FOR TESTING2';
   RETURN fully_depritiated_;
END Case2;
Copy
 CREATE OR REPLACE FUNCTION Case2_1 (year_ NUMBER(38, 18), id NUMBER(38, 18))
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "oracle",  "convertedOn": "09/06/2024" }}'
AS
$$
   WITH declaration_variables_cte1 AS
   (
      SELECT
         FOO1(year_, id) !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'FOO1' NODE ***/!!! AS

         base_value_,
         FOO2(year_, id) !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'FOO2' NODE ***/!!! AS
         acc_depr_,
         FOO3(year_, id) !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'FOO3' NODE ***/!!! AS
         acc_depr_prev_,
         !!!RESOLVE EWI!!! /*** SSC-EWI-OR0036 - TYPES RESOLUTION ISSUES, ARITHMETIC OPERATION '-' MAY NOT BEHAVE CORRECTLY BETWEEN ExactNumeric AND unknown ***/!!!
         NVL(base_value_,0) -(acc_depr_ + acc_depr_prev_) AS
         residual_value_,
         CASE
            WHEN (residual_value_=0 AND base_value_!=0)
               THEN 'TRUE'
            ELSE 'FALSE'
         END AS fully_depritiated_,
         NVL(fully_depritiated :: STRING, '') || ' CONCAT FOR TESTING' AS

         fully_depritiated
   ),
   declaration_variables_cte2 AS
   (
      SELECT
         NVL(fully_depritiated :: STRING, '') || ' CONCAT FOR TESTING2' AS
         fully_depritiated,
         base_value_,
         acc_depr_,
         acc_depr_prev_,
         residual_value_
      FROM
         declaration_variables_cte1
   )
   SELECT
      fully_depritiated_
   FROM
      declaration_variables_cte2
$$;
Copy
 CREATE OR REPLACE FUNCTION Case2_1 (
   year_        IN NUMBER,
   id           IN NUMBER) 
   RETURN VARCHAR2
IS
   base_value_        NUMBER;
   fully_depritiated_ VARCHAR2(5);
   residual_value_    NUMBER;
   acc_depr_prev_     NUMBER;
   acc_depr_          NUMBER;
BEGIN

   base_value_     := FOO1(year_, id);
   acc_depr_       := FOO2(year_, id);
   acc_depr_prev_  := FOO3(year_, id);
   residual_value_ := NVL(base_value_,0) -(acc_depr_ + acc_depr_prev_);

   IF (residual_value_=0 AND base_value_!=0) THEN
      fully_depritiated_ := 'TRUE';
   ELSE
      fully_depritiated_ := 'FALSE';
   END IF;

   fully_depritiated := fully_depritiated || ' CONCAT FOR TESTING';
   fully_depritiated := fully_depritiated || ' CONCAT FOR TESTING2';
   RETURN fully_depritiated_;
END Case2;
Copy
 CREATE OR REPLACE FUNCTION Case2_1 (year_ NUMBER(38, 18), id NUMBER(38, 18))
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "oracle",  "convertedOn": "09/06/2024" }}'
AS
$$
   WITH declaration_variables_cte1 AS
   (
      SELECT
         FOO1(year_, id) !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'FOO1' NODE ***/!!! AS

         base_value_,
         FOO2(year_, id) !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'FOO2' NODE ***/!!! AS
         acc_depr_,
         FOO3(year_, id) !!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'FOO3' NODE ***/!!! AS
         acc_depr_prev_,
         !!!RESOLVE EWI!!! /*** SSC-EWI-OR0036 - TYPES RESOLUTION ISSUES, ARITHMETIC OPERATION '-' MAY NOT BEHAVE CORRECTLY BETWEEN ExactNumeric AND unknown ***/!!!
         NVL(base_value_,0) -(acc_depr_ + acc_depr_prev_) AS
         residual_value_,
         CASE
            WHEN (residual_value_=0 AND base_value_!=0)
               THEN 'TRUE'
            ELSE 'FALSE'
         END AS fully_depritiated_,
         NVL(fully_depritiated :: STRING, '') || ' CONCAT FOR TESTING' AS

         fully_depritiated
   ),
   declaration_variables_cte2 AS
   (
      SELECT
         NVL(fully_depritiated :: STRING, '') || ' CONCAT FOR TESTING2' AS
         fully_depritiated,
         base_value_,
         acc_depr_,
         acc_depr_prev_,
         residual_value_
      FROM
         declaration_variables_cte1
   )
   SELECT
      fully_depritiated_
   FROM
      declaration_variables_cte2
$$;
Copy

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIS

  1. [SSC-FDM-OR0042](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/oracleFDM. md#ssc-fdm-or0042): In Zeitstempel umgewandelter Datumstyp zeigt eine andere Verhaltensweise

  2. [SSC-EWI-0073](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0073): Überprüfung der Funktionsäquivalenz ausstehend.

  3. [SSC-EWI-OR0036](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0036): Probleme bei der Auflösung von Typen, die arithmetische Operation verhält sich möglicherweise nicht korrekt zwischen Zeichenfolge und Datum.

DML STATEMENTS

Beschreibung

DML-Anweisungserweiterungen unterscheiden sich von normalen DML- Anweisungen, da sie PL/SQL-Elemente wie Sammlungen und Datensätze verwenden können. Bislang werden einige dieser Elemente von Snowflake Scripting nicht unterstützt. Wenn eine Anweisung nicht unterstützt wird, wird während der Übersetzung eine EWI hinzugefügt. Andere DML-Anweisungen werden so übersetzt, als befänden sie sich nicht innerhalb einer Prozedur.

Die folgenden werden als DML-Anweisungen betrachtet:

Es gibt einen Abschnitt, in dem beschrieben wird, wie Sie die Verhaltensweise von RECORDS und COLLECTIONS für die Anweisungen SELECT und INSERT simulieren können:

Sammlungen und Datensätze

Erweiterung der INSERT-Anweisung

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

Beschreibung

Mit der PL/SQL-Erweiterung der SQL INSERT-Anweisung können Sie einen Datensatznamen in der values_clause des single_table_insert angeben, anstatt eine Spaltenliste unter insert_into_clause zu spezifizieren. (Oracle PL/SQL Language Reference Erweiterung INSERT Statement)

Snowflake INSERT INTO unterscheidet sich von Snowflake Scripting in den Variableneinschränkungen. Den Namen muss ein Doppelpunkt „:“ vorangestellt werden, um den Wert der Variablen zu binden.

Empfehlungen

Bemerkung

Dieser Code wurde zum besseren Verständnis der Beispiele ausgeführt:

 CREATE TABLE numbers_table(num integer, word varchar2(20));
Copy
 CREATE OR REPLACE TABLE PUBLIC.numbers_table (num integer,
word VARCHAR(20));
Copy

Simple Case, Erweiterung der INSERT-Anweisung

Oracle
 CREATE OR REPLACE PROCEDURE proc_insert_statement
AS
number_variable integer := 10;
word_variable varchar2(20) := 'ten';
BEGIN 
	INSERT INTO numbers_table VALUES(number_variable, word_variable);	
	INSERT INTO numbers_table VALUES(11, 'eleven');	
END;

CALL proc_insert_statement();
SELECT * FROM numbers_table ;
Copy
|NUM|WORD  |
|---|------|
|10 |ten   |
|11 |eleven|


Copy
Snowflake Scripting
 CREATE OR REPLACE PROCEDURE proc_insert_statement ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
	DECLARE
		number_variable integer := 10;
		word_variable VARCHAR(20) := 'ten';
	BEGIN
		INSERT INTO numbers_table
		VALUES(:number_variable, :word_variable);
		INSERT INTO numbers_table
		VALUES(11, 'eleven');
	END;
$$;

CALL proc_insert_statement();

SELECT * FROM
	numbers_table;
Copy
|NUM|WORD  |
|---|------|
|10 |ten   |
|11 |eleven|


Copy

Bekannte Probleme

1. Records are not supported by Snowflake Scripting

Da Datensätze von Snowflake Scripting nicht unterstützt werden, müssen Sie die VALUES record-Klausel in eine SELECT-Klausel ändern und die Spalten des Datensatzes aufteilen. Weitere Informationen finden Sie im Abschnitt Definition Datensatztyp.

Zugehörige EWIs

Keine zugehörigen EWIs.

MERGE-Anweisung

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

Beschreibung

Die Anweisung MERGE wird verwendet, um Zeilen aus einer oder mehreren Quellen zur Aktualisierung oder zum Einfügen in eine Tabelle oder Ansicht auszuwählen. Es ist möglich, Bedingungen festzulegen, um zu bestimmen, ob die Zieltabelle oder -ansicht aktualisiert oder eingefügt werden soll. Diese Anweisung ist eine praktische Möglichkeit, mehrere Operationen zu kombinieren. So können Sie mehrere INSERT, UPDATE und DELETE DML-Anweisungen vermeiden. MERGE ist eine deterministische Anweisung. Es ist nicht möglich, dieselbe Zeile der Zieltabelle mehrmals in derselben MERGE-Anweisung zu aktualisieren. (Oracle PL/SQL Language Reference MERGE Statement))

 MERGE [ hint ]
   INTO [ schema. ] { table | view } [ t_alias ]
   USING { [ schema. ] { table | view }
         | ( subquery )
         } [ t_alias ]
   ON ( condition )
   [ merge_update_clause ]
   [ merge_insert_clause ]
   [ error_logging_clause ] ;

merge_update_clause := WHEN MATCHED THEN
UPDATE SET column = { expr | DEFAULT }
           [, column = { expr | DEFAULT } ]...
[ where_clause ]
[ DELETE where_clause ]

merge_insert_clause := WHEN NOT MATCHED THEN
INSERT [ (column [, column ]...) ]
VALUES ({ expr | DEFAULT }
          [, { expr | DEFAULT } ]...
       )
[ where_clause ]

error_logging_clause := LOG ERRORS 
  [ INTO [schema.] table ]
  [ (simple_expression) ]
  [ REJECT LIMIT { integer | UNLIMITED } ]

where_clause := WHERE condition
Copy
 MERGE INTO <target_table> USING <source> ON <join_expr> 
{ matchedClause | notMatchedClause } [ ... ]

matchedClause ::= WHEN MATCHED [ AND <case_predicate> ] 
THEN { UPDATE SET <col_name> = <expr> [ , <col_name2> = <expr2> ... ] | DELETE } [ ... ]

notMatchedClause ::= WHEN NOT MATCHED [ AND <case_predicate> ] 
THEN INSERT [ ( <col_name> [ , ... ] ) ] VALUES ( <expr> [ , ... ] )
Copy

Beispielhafte Quellcode-Muster

Beispielhafte Hilfsdaten

Bemerkung

Dieser Code wurde zum besseren Verständnis der Beispiele ausgeführt:

 CREATE TABLE people_source (
    person_id INTEGER NOT NULL PRIMARY KEY,
    first_name VARCHAR2(20) NOT NULL,
    last_name VARCHAR2(20) NOT NULL,
    title VARCHAR2(10) NOT NULL
);

CREATE TABLE people_target (
    person_id INTEGER NOT NULL PRIMARY KEY,
    first_name VARCHAR2(20) NOT NULL,
    last_name VARCHAR2(20) NOT NULL,
    title VARCHAR2(10) NOT NULL
);

CREATE TABLE bonuses (
    employee_id NUMBER,
    bonus NUMBER DEFAULT 100
);

INSERT INTO people_target
VALUES (1, 'John', 'Smith', 'Mr');

INSERT INTO people_target
VALUES (2, 'alice', 'jones', 'Mrs');

INSERT INTO people_source
VALUES (2, 'Alice', 'Jones', 'Mrs.');

INSERT INTO people_source
VALUES (3, 'Jane', 'Doe', 'Miss');

INSERT INTO people_source
VALUES (4, 'Dave', 'Brown', 'Mr');

INSERT INTO
    bonuses(employee_id) (
        SELECT
            e.employee_id
        FROM
            hr.employees e,
            oe.orders o
        WHERE
            e.employee_id = o.sales_rep_id
        GROUP BY
            e.employee_id
    );
Copy
 CREATE OR REPLACE TABLE people_source (
    person_id INTEGER NOT NULL PRIMARY KEY,
    first_name VARCHAR(20) NOT NULL,
    last_name VARCHAR(20) NOT NULL,
    title VARCHAR(10) NOT NULL
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE TABLE people_target (
    person_id INTEGER NOT NULL PRIMARY KEY,
    first_name VARCHAR(20) NOT NULL,
    last_name VARCHAR(20) NOT NULL,
    title VARCHAR(10) NOT NULL
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE TABLE bonuses (
    employee_id NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/,
    bonus NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/ DEFAULT 100
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

INSERT INTO people_target
VALUES (1, 'John', 'Smith', 'Mr');

INSERT INTO people_target
VALUES (2, 'alice', 'jones', 'Mrs');

INSERT INTO people_source
VALUES (2, 'Alice', 'Jones', 'Mrs.');

INSERT INTO people_source
VALUES (3, 'Jane', 'Doe', 'Miss');

INSERT INTO people_source
VALUES (4, 'Dave', 'Brown', 'Mr');

INSERT INTO bonuses(employee_id) (
    SELECT
        e.employee_id
    FROM
        hr.employees e,
        oe.orders o
    WHERE
        e.employee_id = o.sales_rep_id
    GROUP BY
        e.employee_id
);
Copy

Simple Case, MERGE-Anweisung

Oracle
 MERGE INTO people_target pt USING people_source ps ON (pt.person_id = ps.person_id)
WHEN MATCHED THEN
UPDATE
SET
    pt.first_name = ps.first_name,
    pt.last_name = ps.last_name,
    pt.title = ps.title
    WHEN NOT MATCHED THEN
INSERT
    (
        pt.person_id,
        pt.first_name,
        pt.last_name,
        pt.title
    )
VALUES
    (
        ps.person_id,
        ps.first_name,
        ps.last_name,
        ps.title
    );

SELECT * FROM people_target;
Copy
PERSON_ID|FIRST_NAME|LAST_NAME|TITLE|
---------+----------+---------+-----+
        1|John      |Smith    |Mr   |
        2|Alice     |Jones    |Mrs. |
        3|Jane      |Doe      |Miss |
        4|Dave      |Brown    |Mr   |

Copy
Snowflake
 MERGE INTO people_target pt USING people_source ps ON (pt.person_id = ps.person_id)
WHEN MATCHED THEN
    UPDATE
SET
    pt.first_name = ps.first_name,
    pt.last_name = ps.last_name,
    pt.title = ps.title
WHEN NOT MATCHED THEN
INSERT
    (
        pt.person_id,
        pt.first_name,
        pt.last_name,
        pt.title
    )
VALUES
    (
        ps.person_id,
        ps.first_name,
        ps.last_name,
        ps.title
    );

SELECT * FROM
    people_target;
Copy
PERSON_ID|FIRST_NAME|LAST_NAME|TITLE|
---------+----------+---------+-----+
        1|John      |Smith    |Mr   |
        2|Alice     |Jones    |Mrs. |
        3|Jane      |Doe      |Miss |
        4|Dave      |Brown    |Mr   |

Copy

MERGE-Anweisung mit DELETE- und WHERE-Klausel

Um eine Äquivalenz für die Anweisung DELETE und die WHERE-Klausel zu finden, ist es notwendig, die MERGE-Anweisung von Snowflake neu zu ordnen und einige Änderungen vorzunehmen.

Änderungen erforderlich:
  • Ersetzen Sie die DELETE where_clause von Oracle durch eine neue matchedClause von Snowflake mit der AND Prädikat-Anweisung

  • Ersetzen Sie die where_clause aus Oracles merge\_insert_clause durch eine AND Prädikat-Anweisung in der Snowflakes notMatchedClause

Oracle
 MERGE INTO bonuses D USING (
    SELECT
        employee_id,
        salary,
        department_id
    FROM
        hr.employees
    WHERE
        department_id = 80
) S ON (D.employee_id = S.employee_id)
WHEN MATCHED THEN
UPDATE
SET
    D.bonus = D.bonus + S.salary *.01 DELETE
WHERE
    (S.salary > 8000)
    WHEN NOT MATCHED THEN
INSERT
    (D.employee_id, D.bonus)
VALUES
    (S.employee_id, S.salary *.01)
WHERE
    (S.salary <= 8000);

SELECT * FROM bonuses ORDER BY employee_id;
Copy
EMPLOYEE_ID|BONUS|
-----------+-----+
        153|  180|
        154|  175|
        155|  170|
        159|  180|
        160|  175|
        161|  170|
        164|   72|
        165|   68|
        166|   64|
        167|   62|
        171|   74|
        172|   73|
        173|   61|
        179|   62|

Copy
Snowflake
 --** SSC-FDM-OR0018 - SNOWFLAKE MERGE STATEMENT MAY HAVE SOME FUNCTIONAL DIFFERENCES COMPARED TO ORACLE **
MERGE INTO bonuses D USING (
 SELECT
     employee_id,
     salary,
     department_id
 FROM
     hr.employees
 WHERE
     department_id = 80) S ON (D.employee_id = S.employee_id)
    WHEN MATCHED AND
    (S.salary > 8000) THEN
 DELETE
    WHEN MATCHED THEN
 UPDATE SET
    D.bonus = D.bonus + S.salary *.01
    WHEN NOT MATCHED AND
    (S.salary <= 8000) THEN
 INSERT
 (D.employee_id, D.bonus)
VALUES
 (S.employee_id, S.salary *.01);

SELECT * FROM
bonuses
ORDER BY employee_id;
Copy
EMPLOYEE_ID|BONUS|
-----------+-----+
        153|  180|
        154|  175|
        155|  170|
        159|  180|
        160|  175|
        161|  170|
        164|   72|
        165|   68|
        166|   64|
        167|   62|
        171|   74|
        172|   73|
        173|   61|
        179|   62|

Copy

Warnung

In manchen Fällen funktionieren die vorgenommenen Änderungen nicht wie erwartet, wie im folgenden Beispiel:

Oracle
 MERGE INTO people_target pt USING people_source ps ON (pt.person_id = ps.person_id)
WHEN MATCHED THEN
UPDATE
SET
    pt.first_name = ps.first_name,
    pt.last_name = ps.last_name,
    pt.title = ps.title DELETE
where
    pt.title = 'Mrs.'
    WHEN NOT MATCHED THEN
INSERT
    (
        pt.person_id,
        pt.first_name,
        pt.last_name,
        pt.title
    )
VALUES
    (
        ps.person_id,
        ps.first_name,
        ps.last_name,
        ps.title
    )
WHERE
    ps.title = 'Mr';

SELECT * FROM people_target;
Copy
PERSON_ID|FIRST_NAME|LAST_NAME|TITLE|
---------+----------+---------+-----+
        1|John      |Smith    |Mr   |
        4|Dave      |Brown    |Mr   |

Copy
Snowflake
 --** SSC-FDM-OR0018 - SNOWFLAKE MERGE STATEMENT MAY HAVE SOME FUNCTIONAL DIFFERENCES COMPARED TO ORACLE **
MERGE INTO people_target pt USING people_source ps ON (pt.person_id = ps.person_id)
    WHEN MATCHED AND
    pt.title = 'Mrs.' THEN
        DELETE
    WHEN MATCHED THEN
        UPDATE SET
    pt.first_name = ps.first_name,
    pt.last_name = ps.last_name,
    pt.title = ps.title
    WHEN NOT MATCHED AND
    ps.title = 'Mr' THEN
        INSERT
        (
            pt.person_id,
            pt.first_name,
            pt.last_name,
            pt.title
        )
VALUES
        (
            ps.person_id,
            ps.first_name,
            ps.last_name,
            ps.title
        );


SELECT * FROM
        people_target;
Copy
PERSON_ID|FIRST_NAME|LAST_NAME|TITLE|
---------+----------+---------+-----+
        1|John      |Smith    |Mr   |
        2|Alice     |Jones    |Mrs. |
        4|Dave      |Brown    |Mr   |

Copy

Bekannte Probleme

1. Oracle’s error_logging_clause is not supported

Es gibt keine Entsprechung für die Klausel zur Fehlerprotokollierung in Snowflake Scripting.

2. Changed applied do not work as expected

Manchmal funktionieren die Änderungen, die vorgenommen wurden, um die Funktionsäquivalenz zwischen der MERGE-Anweisung von Oracle und der von Snowflake zu erreichen, nicht wie erwartet.

Zugehörige EWIs

  1. [SSC-FDM-0006](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0006): Zahlentyp-Spalte verhält sich in Snowflake möglicherweise nicht ähnlich.

  2. [SSC-FDM-OR0018](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/oracleFDM. md#ssc-fdm-or0018): MERGE-Anweisung funktioniert möglicherweise nicht wie erwartet

SELECTINTO-Anweisung

Bemerkung

Einige Teile des Ausgabecodes wurden aus Gründen der Übersichtlichkeit weggelassen.

Beschreibung

Die Anweisung SELECT INTO ruft Werte aus einer oder mehreren Datenbanktabellen ab (was die SQL SELECT-Anweisung tut) und speichert sie in Variablen (was die SQL SELECT-Anweisung nicht tut). (Oracle PL/SQL Language Reference SELECT INTO Statement)

 SELECT [ { DISTINCT | UNIQUE } | ALL ] select_list
    { into_clause | bulk_collect_into_clause } FROM rest-of-statement ;
Copy
 INTO { variable [, variable ]... | record )
Copy
 BULK COLLECT INTO { collection | :host_array }
  [, { collection | :host_array } ]...
Copy
 SELECT [ { ALL | DISTINCT } ]
    {
          [{<object_name>|<alias>}.]*
        | [{<object_name>|<alias>}.]<col_name>
        | [{<object_name>|<alias>}.]$<col_position>
        | <expr>
        [ [ AS ] <col_alias> ]
    }
    [ , ... ]
    INTO :<variable> [, :<variable> ... ]
    [...]
Copy

Beispielhafte Quellcode-Muster

Beispielhafte Hilfsdaten

Bemerkung

Dieser Code wurde zum besseren Verständnis der Beispiele ausgeführt:

 CREATE TABLE numbers_table(num integer, word varchar2(20));
INSERT INTO numbers_table VALUES (1, 'one');
CREATE TABLE aux_numbers_table(aux_num integer, aux_word varchar2(20));
Copy
 CREATE OR REPLACE TABLE numbers_table (num integer,
word VARCHAR(20))
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

INSERT INTO numbers_table
VALUES (1, 'one');

CREATE OR REPLACE TABLE aux_numbers_table (aux_num integer,
aux_word VARCHAR(20))
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;
Copy

Simple Case, SELECT INTO-Anweisung

Oracle
 CREATE OR REPLACE PROCEDURE proc_select_into_variables
AS
number_variable integer;
word_variable varchar2(20);
BEGIN 
	SELECT * INTO number_variable, word_variable FROM numbers_table;
	INSERT INTO aux_numbers_table VALUES(number_variable, word_variable);	
END;

CALL proc_select_into_variables();
SELECT * FROM aux_numbers_table;
Copy
|AUX_NUM|AUX_WORD|
|-------|--------|
|1      |one     |

Copy
Snowflake Scripting
 CREATE OR REPLACE PROCEDURE proc_select_into_variables ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
	DECLARE
		number_variable integer;
		word_variable VARCHAR(20);
	BEGIN
		SELECT * INTO
			:number_variable,
			:word_variable
		FROM
			numbers_table;
		INSERT INTO aux_numbers_table
		VALUES(:number_variable, :word_variable);
	END;
$$;

CALL proc_select_into_variables();

SELECT * FROM
	aux_numbers_table;
Copy
|AUX_NUM|AUX_WORD|
|-------|--------|
|1      |one     |


Copy

Bekannte Probleme

1. BULK COLLECT INTO is not supported

Snowflake Scripting unterstützt die BULK COLLECTINTO -Klausel nicht. Es ist jedoch möglich, ARRAY_AGG zu verwenden, um eine neue Variable zu konstruieren. Weitere Informationen finden Sie im Abschnitt Sammlung Bulk-Operationen.

2. Collections and records are not supported

Snowflake Scripting unterstützt weder die Verwendung von Sammlungen noch von Datensätzen. Es ist möglich, sie mit Hilfe von semistrukturierten Daten zu migrieren, wie in diesem Abschnitt erläutert.

Zugehörige EWIs

Keine zugehörigen EWIs.

Umgehungsmöglichkeit, um die Verwendung von Datensätzen zu simulieren

Warnung

Diese Seite ist veraltet, wurde aber aus Kompatibilitätsgründen beibehalten. Den aktualisierten Abschnitt finden Sie unter Sammlungen und Datensätze

Beschreibung

In diesem Abschnitt wird beschrieben, wie Sie die Verhaltensweise von Oracle-Datensätzen in SELECT- und INSERT-Anweisungen simulieren können, indem Sie RESULTSET und CURSORS von Snowflake Scripting verwenden.

Snowflake Scripting RESULTSET und CURSOR

 <resultset_name> RESULTSET [ DEFAULT ( <query> ) ] ;

LET <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;

LET <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
Copy

Empfehlungen

Bemerkung

Für die folgenden Beispiele wurde dieser Code zum besseren Verständnis der Beispiele ausgeführt:

 CREATE TABLE numbers_table(num integer, word varchar2(20));
INSERT INTO numbers_table VALUES (1, 'one');
CREATE TABLE aux_numbers_table(aux_num integer, aux_word varchar2(20));
Copy
 CREATE OR REPLACE TABLE numbers_table (num integer,
word VARCHAR(20))
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

INSERT INTO numbers_table
VALUES (1, 'one');

CREATE OR REPLACE TABLE aux_numbers_table (aux_num integer,
aux_word VARCHAR(20))
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;
Copy

RESULTSET und Cursor anstelle von Datensätzen verwenden

Oracle
 CREATE OR REPLACE PROCEDURE proc_insert_select_resultset
AS
TYPE number_record_definition IS RECORD(
	rec_num numbers_table.num%type,
	rec_word numbers_table.word%type
);
number_record number_record_definition;
BEGIN 
	SELECT * INTO number_record FROM numbers_table;	
	INSERT INTO aux_numbers_table VALUES number_record;
END;

CALL proc_insert_select_resultset();
SELECT * FROM aux_numbers_table;
Copy
|AUX_NUM|AUX_WORD|
|-------|--------|
|1      |one     |

Copy
Snowflake
 CREATE OR REPLACE PROCEDURE proc_insert_select_resultset ()
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 number_record_definition IS RECORD(
			rec_num numbers_table.num%type,
			rec_word numbers_table.word%type
		);
		number_record OBJECT !!!RESOLVE EWI!!! /*** SSC-EWI-0036 - number_record_definition DATA TYPE CONVERTED TO OBJECT ***/!!! := OBJECT_CONSTRUCT();
	BEGIN
		SELECT
			OBJECT_CONSTRUCT( *) INTO
			:number_record
		FROM
			numbers_table;
		INSERT INTO aux_numbers_table
		SELECT
			:number_record:REC_NUM,
			:number_record:REC_WORD;
	END;
$$;

CALL proc_insert_select_resultset();

SELECT * FROM
	aux_numbers_table;
Copy
 CREATE OR REPLACE PROCEDURE PUBLIC.proc_select_into()
RETURNS INTEGER
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
AS
$$
DECLARE
    NUMBER_VARIABLE INTEGER;
    WORD_VARIABLE VARCHAR;
    NUMBER_RECORD RESULTSET;
BEGIN
    LET c2 CURSOR FOR NUMBER_RECORD;
    FOR row_variable IN c2 DO
        let var1 integer := row_variable.num;
        let var2 varchar := row_variable.word;
        INSERT INTO PUBLIC.aux_numbers_table VALUES(:var1, :var2);
    END FOR;
end;
$$;
Copy
|AUX_NUM|AUX_WORD|
|-------|--------|
|1      |one     |


Copy

Bekannte Probleme

1. Limitation in the use of RESULTSET

RESULTSET ist in seiner Verwendung sehr eingeschränkt. Wenn table(result_scan(last_query_id()))-Anweisung verwendet wird, sollte sie direkt nach der Ausführung der Abfrage RESULTSET verwendet werden. Weitere Informationen finden Sie unter diesem Link.

Zugehörige EWIs

  1. [SSC-EWI-0036](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0036): Datentyp in einen anderen Datentyp konvertiert.

  2. [SSC-EWI-0056](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0056): Typ erstellen wird nicht unterstützt.

PACKAGES

Beschreibung

Verwenden Sie die Anweisung CREATE PACKAGE, um die Spezifikation für ein gespeichertes Paket zu erstellen. Dabei handelt es sich um eine gekapselte Sammlung verwandter Prozeduren, Funktionen und anderer Programmobjekte, die gemeinsam in der Datenbank gespeichert werden. Die Paketspezifikation deklariert diese Objekte. Der Paket-Body, der später angegeben wird, definiert diese Objekte. (Oracle PL/SQL Language Reference CREATE PACKAGE Statement)

Snowflake hat keine Entsprechung für Oracle-Pakete. Um die Struktur beizubehalten, werden die Pakete in ein Schema umgewandelt, in dem alle Elemente definiert sind. Außerdem werden das Paket und seine Elemente umbenannt, um den ursprünglichen Schemanamen zu erhalten. Weitere Informationen zur Umbenennung von Paketen finden Sie im Abschnitt Optionen für die Übersetzung von Paketen.

BODY

Beschreibung

Die Kopfzeile des PACKAGE BODY wird entfernt und jede Prozedur- oder Funktionsdefinition wird in eine eigenständige Funktion oder Prozedur umgewandelt.

CREATE [ OR REPLACE ]
[ EDITIONABLE | NONEDITIONABLE ]
PACKAGE BODY plsql_package_body_source

Copy

Beispielhafte Quellcode-Muster

Bemerkung

Die folgenden Abfragen wurden mit der deaktivierten Option PackagesAsSchema umgewandelt.

Oracle

 CREATE OR REPLACE PACKAGE BODY SCHEMA1.PKG1 AS
    PROCEDURE procedure1 AS
        BEGIN
            dbms_output.put_line('hello world');
        END;
END package1;
Copy
Snowflake
 CREATE OR REPLACE PROCEDURE SCHEMA1_PKG1.procedure1 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        --** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
        CALL DBMS_OUTPUT.PUT_LINE_UDF('hello world');
    END;
$$;
Copy

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIs

  1. [SSC-FDM-OR0035](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/oracleFDM. md#ssc-fdm-or0035): DBMS_OUTPUT.PUTLINE UDF Implementierung überprüfen.

Konstanten

Beschreibung

PACKAGE CONSTANTS kann entweder in der Paketdeklaration oder im PACKAGE BODY deklariert werden. Wenn eine Paketkonstante in einer Prozedur verwendet wird, wird eine neue Variable mit demselben Namen und Wert wie die Konstante deklariert, so dass der resultierende Code der Eingabe ziemlich ähnlich ist.

constant CONSTANT datatype [NOT NULL] { := | DEFAULT } expression ;

Copy

Beispielhafte Quellcode-Muster

Beispiel für Hilfscode

 create table table1(id number);
Copy
 CREATE OR REPLACE TABLE table1 (id NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;
Copy
Oracle
 CREATE OR REPLACE PACKAGE PKG1 AS
    PROCEDURE procedure1;
    package_constant CONSTANT NUMBER:= 9999;
END PKG1;

CREATE OR REPLACE PACKAGE BODY PKG1 AS
    PROCEDURE procedure1 AS
    BEGIN
        INSERT INTO TABLE1(ID) VALUES(package_constant);
    END;
END PKG1;

CALL PKG1.procedure1();

SELECT * FROM TABLE1;
Copy
|ID  |
|----|
|9999|


Copy
Snowflake
 CREATE SCHEMA IF NOT EXISTS PKG1
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

CREATE OR REPLACE PROCEDURE PKG1.procedure1 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        PACKAGE_CONSTANT NUMBER := 9999;
    BEGIN
        INSERT INTO TABLE1(ID) VALUES(:PACKAGE_CONSTANT);
    END;
$$;

CALL PKG1.procedure1();

SELECT * FROM
    TABLE1;
Copy
|ID  |
|----|
|9999|


Copy

Bemerkung

Beachten Sie, dass die Definition vonPROCEDURE entfernt wird, da sie in Snowflake nicht erforderlich ist.

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIs

  1. [SSC-FDM-0006](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0006): Zahlentyp-Spalte verhält sich in Snowflake möglicherweise nicht ähnlich.

DECLARATION

Beschreibung

Die Deklaration wird in ein Schema umgewandelt, so dass jedes innere Element innerhalb dieses Schemas deklariert wird. Alle Elemente des Pakets sind kommentiert, mit Ausnahme der VARIABLES, die eine eigene Transformation haben.

CREATE [ OR REPLACE ]
[ EDITIONABLE | NONEDITIONABLE ]
PACKAGE plsql_package_source

Copy

Beispielhafte Quellcode-Muster

Bemerkung

Die folgenden Abfragen wurden mit der deaktivierten Option PackagesAsSchema umgewandelt.

Oracle

 CREATE OR REPLACE PACKAGE SCHEMA1.PKG1 AS
   -- Function Declaration
   FUNCTION function_declaration(param1 VARCHAR) RETURN INTEGER;

   -- Procedure Declaration
   PROCEDURE procedure_declaration(param1 VARCHAR2, param2 VARCHAR2);

END PKG1;
Copy
Snowflake
 CREATE SCHEMA IF NOT EXISTS SCHEMA1_PKG1
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;
Copy

Bemerkung

Beachten Sie, dass die Definitionen FUNCTION und PROCEDURE entfernt werden, da sie in Snowflake nicht erforderlich sind.

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIs

Keine zugehörigen EWIs.

VARIABLES

Beschreibung

PACKAGE VARIABLES kann entweder in der Paketdeklaration oder im PACKAGE BODY deklariert werden. Aufgrund ihres Verhaltens werden diese Variablen in Snowflake-Sitzungsvariablen umgewandelt, so dass jede Verwendung oder Zuweisung in ihre Entsprechung in Snowflake übersetzt wird.

 variable datatype [ [ NOT NULL] {:= | DEFAULT} expression ] ;
Copy

Beispielhafte Quellcode-Muster

Beispiel für Hilfscode

 create table table1(id number);
Copy
 CREATE OR REPLACE TABLE table1 (id NUMBER(38, 18) /*** SSC-FDM-0006 - NUMBER TYPE COLUMN MAY NOT BEHAVE SIMILARLY IN SNOWFLAKE. ***/
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;
Copy

Variablendeklaration

Oracle
 CREATE OR REPLACE PACKAGE PKG1 AS
    package_variable NUMBER:= 100;
END PKG1;
Copy
Snowflake Scripting
 CREATE SCHEMA IF NOT EXISTS PKG1
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

SET "PKG1.PACKAGE_VARIABLE" = '' || (100);
Copy

Verwendung von Variablen

Die Verwendung von Paketvariablen wird in die Snowflake GETVARIABLE-Funktion umgewandelt, die auf den aktuellen Wert einer Sitzungsvariablen zugreift. Eine explizite Umwandlung wird zum ursprünglichen Variablendatentyp hinzugefügt, um die Funktionsäquivalenz bei den Operationen, bei denen diese Variablen verwendet werden, zu erhalten.

Oracle
 CREATE OR REPLACE PACKAGE PKG1 AS
    PROCEDURE procedure1;
    package_variable NUMBER:= 100;
END PKG1;

CREATE OR REPLACE PACKAGE BODY PKG1 AS
    PROCEDURE procedure1 AS
    BEGIN
        INSERT INTO TABLE1(ID) VALUES(package_variable);
    END;
END PKG1;

CALL SCHEMA1.PKG1.procedure1();

SELECT * FROM TABLE1;
Copy
|ID |
|---|
|100|


Copy
Snowflake
 CREATE SCHEMA IF NOT EXISTS PKG1
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

SET "PKG1.PACKAGE_VARIABLE" = '' || (100);

CREATE OR REPLACE PROCEDURE PKG1.procedure1 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        INSERT INTO TABLE1(ID) VALUES(GETVARIABLE('PKG1.PACKAGE_VARIABLE') :: NUMBER);
    END;
$$;

CALL SCHEMA1.PKG1.procedure1();

SELECT * FROM
    TABLE1;
Copy
|ID |
|---|
|100|


Copy

Bemerkung

Beachten Sie, dass die PROCEDURE-Definition im Paket entfernt wurde, da sie von Snowflake nicht benötigt wird.

Reguläre Variablenzuweisung

Wenn eine Paketvariable mit dem Operator : = zugewiesen wird, wird die Zuweisung durch eine SnowConvert UDF namens UPDATE_PACKAGE\_VARIABLE\_STATE ersetzt, die eine Abstraktion der Snowflake SETVARIABLE-Funktion ist.

Oracle

 CREATE OR REPLACE PACKAGE PKG1 AS
    PROCEDURE procedure1;
    package_variable NUMBER:= 100;
END PKG1;

CREATE OR REPLACE PACKAGE BODY PKG1 AS
    PROCEDURE procedure1 AS
    BEGIN
        package_variable := package_variable + 100;
        INSERT INTO TABLE1(ID) VALUES(package_variable);
    END;
END PKG1;

CALL PKG1.procedure1();

SELECT * FROM TABLE1;
Copy
|ID |
|---|
|200|


Copy

Snowflake

 CREATE SCHEMA IF NOT EXISTS PKG1
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

SET "PKG1.PACKAGE_VARIABLE" = '' || (100);

CREATE OR REPLACE PROCEDURE PKG1.procedure1 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        CALL UPDATE_PACKAGE_VARIABLE_STATE_UDF('PKG1.PACKAGE_VARIABLE', TO_VARCHAR(GETVARIABLE('PKG1.PACKAGE_VARIABLE') :: NUMBER + 100));
        INSERT INTO TABLE1(ID) VALUES(GETVARIABLE('PKG1.PACKAGE_VARIABLE') :: NUMBER);
    END;
$$;

CALL PKG1.procedure1();

SELECT * FROM
    TABLE1;
Copy
|ID |
|---|
|200|


Copy

Bemerkung

Beachten Sie, dass die PROCEDURE-Definition im Paket entfernt wurde, da sie von Snowflake nicht benötigt wird.

Variablenzuweisung als Ausgabeargument

Wenn eine Paketvariable als Ausgabeargument verwendet wird, wird innerhalb der Prozedur eine neue Variable deklariert. Diese Variable fängt den Wert des Ausgabearguments der Prozedur auf und wird dann verwendet, um die Sitzungsvariable zu aktualisieren, die auf die Paketvariable verweist, indem die oben erwähnte UPDATE_PACKAGE_VARIABLE_STATE-Funktion verwendet wird. Weitere Informationen finden Sie unter Transformation von Ausgabeparametern.

Oracle
 CREATE OR REPLACE PACKAGE PKG1 AS
    PROCEDURE procedure1;
    PROCEDURE procedure2(out_param OUT NUMBER);
    package_variable NUMBER:= 100;
END PKG1;

CREATE OR REPLACE PACKAGE BODY PKG1 AS
    PROCEDURE procedure1 AS
    BEGIN
        procedure2(package_variable);
        INSERT INTO TABLE1(ID) VALUES(package_variable);
    END;
    PROCEDURE procedure2 (out_param OUT NUMBER) AS
    BEGIN
        out_param := 1000;
    END;
END PKG1;

CALL PKG1.procedure1();
Copy
|ID  |
|----|
|1000|


Copy
Snowflake
 CREATE SCHEMA IF NOT EXISTS PKG1
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
;

SET "PKG1.PACKAGE_VARIABLE" = '' || (100);

CREATE OR REPLACE PROCEDURE PKG1.procedure1 ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        PKG1_PACKAGE_VARIABLE VARIANT;
        call_results VARIANT;
    BEGIN
        call_results := (
            CALL PKG1.
            procedure2(:PKG1_PACKAGE_VARIABLE)
        );
        PKG1_PACKAGE_VARIABLE := :call_results;
        CALL UPDATE_PACKAGE_VARIABLE_STATE_UDF('PKG1.PACKAGE_VARIABLE', TO_VARCHAR(:PKG1_PACKAGE_VARIABLE));
        INSERT INTO TABLE1(ID) VALUES(GETVARIABLE('PKG1.PACKAGE_VARIABLE') :: NUMBER);
    END;
$$;

CREATE OR REPLACE PROCEDURE PKG1.procedure2 (out_param NUMBER(38, 18))
RETURNS VARIANT
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    BEGIN
        out_param := 1000;
        RETURN null;
    END;
$$;

CALL PKG1.procedure1();
Copy
|ID  |
|----|
|1000|


Copy

Bemerkung

Beachten Sie, dass die PROCEDURE-Definition im Paket entfernt wurde, da sie von Snowflake nicht benötigt wird.

Bekannte Probleme

Es wurden keine Probleme gefunden.

Zugehörige EWIs

  1. [SSC-FDM-0006](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0006): Zahlentyp-Spalte verhält sich in Snowflake möglicherweise nicht ähnlich.

COLLECTIONS AND RECORDS

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

Bitte beachten Sie die Übersetzungsreferenz für die Anweisung CREATE TYPE , da sich einige Umgehungsmöglichkeiten überschneiden und in beiden Szenarien funktionieren können.

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 SnowConvert-Unterstützung

Die nächste Tabelle zeigt eine Übersicht über die aktuelle Unterstützung durch das SnowConvert-Tool. Bitte beachten Sie, dass die Übersetzungen noch nicht endgültig sind und noch weitere Arbeiten erforderlich sein können.

Sub-FeatureCurrent recognition statusCurrent translation statusHas Known Workarounds
Record Type DefinitionsRecognized.Not Translated.Yes.
Associative Array Type DefinitionsNot Recognized.Not Translated.Yes.
Varray Type DefinitionsRecognized.Not Translated.Yes.
Nested Table Array Type DefinitionsRecognized.Not Translated.Yes.

Bekannte Probleme

1. Associate Arrays are considered a Nested Table

Derzeit unterscheidet SnowConvert nicht zwischen einem assoziativen Array und einer verschachtelten Tabelle, d.h. sie werden in denselben Bewertungszählungen verwechselt.

Zugehörige EWIs

Keine zugehörigen EWIs.

Definition eines assoziativen Array-Typs

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 index kann entweder ein Zeichenfolgentyp (VARCHAR2, VARCHAR, STRING, oder LONG) oder PLS_INTEGER sein. Indizes werden in der Sortierreihenfolge gespeichert, nicht in der Reihenfolge ihrer Erstellung. Bei Zeichenfolgentypen wird die Sortierreihenfolge durch die Initialisierungsparameter NLS_SORT und NLS_COMP bestimmt.

(Oracle PL/SQL Language Reference ASSOCIATIVE ARRAYS)

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
                     }

Copy

Um eine Variable dieses Typs zu deklarieren:

variable_name collection_type;

Copy

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();
Copy
DBMS OUTPUT
-----------
1
3
4
2
3

Copy
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;
Copy
DBMS OUTPUT
-----------
1

3
4
2
3

Copy

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();
Copy
DBMS OUTPUT
-----------
-1
3
-4
-2
-3

Copy
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;
Copy
DBMS OUTPUT
-----------
-1
3
-4
-2
-3

Copy

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();
Copy
DBMS OUTPUT
-----------
-1
3
-4
-2
-3

Copy
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;
Copy
DBMS OUTPUT
-----------
-1
3
-4
-2
-3

Copy

Bekannte Probleme

1. They are currently not being recognized

SnowConvert behandelt diese Sammlungen als verschachtelte Tabellen-Arrays. Es gibt ein Work-Element, um dies zu beheben.

Zugehörige EWIs

Keine zugehörigen EWIs.

Sammlungsmethoden

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.

(Oracle PL/SQL Language Reference COLLECTION METHODS)

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 SnowConvert-Unterstützung

Die nächste Tabelle zeigt eine Übersicht über die aktuelle Unterstützung durch das SnowConvert-Tool. Bitte beachten Sie, dass die Übersetzungen noch nicht endgültig sind und noch weitere Arbeiten erforderlich sein können.

MethodCurrent recognition statusCurrent translation statusMapped to
DELETENot Recognized.Not Translated.UDF
TRIMNot Recognized.Not Translated.UDF (To be defined)
EXTENDNot Recognized.Not Translated.UDF
EXISTSNot Recognized.Not Translated.ARRAY_CONTAINS
FIRSTNot Recognized.Not Translated.UDF
LASTNot Recognized.Not Translated.UDF
COUNTNot Recognized.Not Translated.ARRAY_SIZE
LIMITNot Recognized.Not Translated.Not Supported.
PRIORNot Recognized.Not Translated.UDF (To be defined)
NEXTNot Recognized.Not Translated.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();
Copy
DBMS OUTPUT
-----------
2
3
4

Copy
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;
Copy
DBMS OUTPUT
-----------
2
3
4

Copy

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();
Copy
DBMS OUTPUT
-----------
2
3
4

Copy
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;
Copy
DBMS OUTPUT
-----------
2
3
4

Copy

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();
Copy
DBMS OUTPUT
-----------
abc
bca
             --These empty spaces are due to it evaluating to null

1
4

Copy
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
 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
DBMS OUTPUT
-----------
abc
bca
             --These empty spaces are due to it evaluating to null

1
4

Copy

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();
Copy
DBMS OUTPUT
-----------
0
0
3
2
0
3
1

Copy
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;
Copy
DBMS OUTPUT
-----------
0
0
3
2
0
3
1

Copy

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();
Copy
DBMS OUTPUT
-----------
5
5
5

Copy
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;
Copy
DBMS OUTPUT
-----------
5
5
5

Copy

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();
Copy
DBMS OUTPUT
-----------
2
2

Copy

LIMIT

Diese Methode gibt das maximale Limit eines Varrays zurück.

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();
Copy
DBMS OUTPUT
-----------
5
6

Copy

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();
Copy
DBMS OUTPUT
-----------
        -- Empty spaces are due to null results
1
3


abc
jkl

jkl



Copy

Known Issues

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.

Related EWIs

Keine zugehörigen EWIs.

Typdefinition für verschachtelte Tabellen-Arrays

Warnung

Dieser Abschnitt ist noch in Arbeit, die Informationen können sich in Zukunft noch ändern.

Bemerkung

Dieser Abschnitt bezieht sich auf die PL/SQL-Version der verschachtelten Tabellen-Arrays. Für die eigenständige Version lesen Sie bitte Typdefinition für verschachtelte Tabellen.

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.

(Oracle PL/SQL Language Reference NESTED TABLES)

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;

Copy

Um eine Variable dieses Typs zu deklarieren:

variable_name collection_type;

Copy

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;
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

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();
Copy
DBMS OUTPUT
-----------
10
20
30
40
20
30

Copy
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;
Copy
 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
DBMS OUTPUT
-----------
10
20
30
40
20
30

Copy

Bekannte Probleme

1. They are currently not being converted

SnowConvert unterstützt die Übersetzung dieser Elemente nicht.

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

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.

(Oracle PL/SQL Language Reference RECORD VARIABLES)

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]

Copy

Um eine Variable dieses Typs zu deklarieren:

variable_name { record_type
              | rowtype_attribute
              | record_variable%TYPE
              };

Copy

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;
Copy
|COL1|COL2|
|----+----|
| 1.5|   1|
| 2.5|   2|

Copy
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;
Copy
COL1|COL2|
----+----+
 1.5|   1|
 2.5|   2|

Copy

%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;
Copy
|COL1|   COL2|     COL3|
|----+-------|---------|
|   1|"Hello"|25-DEC-20|

Copy
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;
Copy
|COL1|   COL2|     COL3|
|----+-------|---------|
|   1|"Hello"|25-DEC-20|

Copy

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();
Copy
DBMS OUTPUT
-----------
1
Hello
25-DEC-20

Copy
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
        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;
        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
DBMS OUTPUT
-----------
1
Hello
25-DEC-20

Copy

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

 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
 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
|COL1    |COL2  |
|--------|------|
|SELECT 1|NAME 1|
|SELECT 2|NAME 2|
|SELECT 3|NAME 3|
|SELECT 4|NAME 4|


Copy
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
|COL1    |COL2  |
|--------|------|
|SELECT 1|NAME 1|
|SELECT 2|NAME 2|
|SELECT 3|NAME 3|
|SELECT 4|NAME 4|


Copy

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

  1. [SSC-EWI-0036](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0036): Datentyp in einen anderen Datentyp konvertiert.

  2. [SSC-EWI-0056](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0056): Create-Typ wird nicht unterstützt

  3. [SSC-FDM-0006](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0006): Zahlentyp-Spalte verhält sich in Snowflake möglicherweise nicht ähnlich.

  4. [SSC-FDM-OR0042](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/oracleFDM. md#ssc-fdm-or0042): In Zeitstempel umgewandelter Datumstyp zeigt eine andere Verhaltensweise

  5. [SSC-FDM-OR0035](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/oracleFDM. md#ssc-fdm-or0035): DBMS_OUTPUT.PUTLINE UDF Implementierung überprüfen.

  6. [SSC-PRF-0003](../../general/technical-documentation/issues-and-troubleshooting/performance-review/README. md#ssc-prf-0003): Fetch innerhalb einer Schleife wird als komplexes Muster betrachtet, was die Leistung von Snowflake beeinträchtigen kann.

Definition des Varray-Typs

Warnung

Dieser Abschnitt ist noch in Arbeit, die Informationen können sich in Zukunft noch ändern.

Bemerkung

Dieser Abschnitt bezieht sich auf die PL/SQL-Version der Varrays, für die Standalone-Version lesen Sie bitte Definition des Array-Typs.

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ür index ist 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.

(Oracle PL/SQL Language Reference VARRAYS)

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];

Copy

Um eine Variable dieses Typs zu deklarieren:

variable_name collection_type;

Copy

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;
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

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();
Copy
DBMS OUTPUT
-----------
10
20
30
40
20
30

Copy
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
        FOR i IN 1 TO 0 /*varray_variable.COUNT*/!!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'VARRAY CUSTOM TYPE EXPRESSION' NODE ***/!!! 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;
        FOR i IN 1 TO 0 /*varray_variable.COUNT*/!!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'VARRAY CUSTOM TYPE EXPRESSION' NODE ***/!!! 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
 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
DBMS OUTPUT
-----------
10
20
30
40
20
30

Copy

Bekannte Probleme

1. They are currently not being converted

SnowConvert unterstützt die Übersetzung dieser Elemente nicht.

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

  1. [SSC-EWI-0058](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0058): Die Funktionalität wird derzeit nicht von Snowflake Scripting unterstützt.

  2. [SSC-EWI-0062](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0062): Benutzerdefinierte Typverwendung auf Variante geändert.

  3. [SSC-EWI-0073](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0073): Überprüfung der Funktionsäquivalenz ausstehend.

  4. [SSC-EWI-OR0108](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0108): Die folgende Zuweisungsanweisung wird von Snowflake Scripting nicht unterstützt.

  5. [SSC-FDM-OR0035](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/oracleFDM. md#ssc-fdm-or0035): DBMS_OUTPUT.PUTLINE UDF Implementierung überprüfen.

Sammlung Bulk-Operationen

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 BULK COLLECT-Klausel, ein Feature von Bulk-SQL, gibt die Ergebnisse von SQL bis PL/SQL in Batches und nicht einzeln zurück.

Die BULK COLLECT-Klausel kann vorkommen in der:

  • SELECT``INTO-Anweisung

  • FETCH-Anweisung

  • RETURNING INTO-Klausel von:

    • DELETE-Anweisung

    • INSERT-Anweisung

    • UPDATE-Anweisung

    • EXECUTE``IMMEDIATE-Anweisung

Mit der Klausel BULK COLLECT ruft 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);
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 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();
Copy
DBMS OUTPUT
-----------
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

Copy
Snowflake

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
        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;
                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 ***/!!! 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;
                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 ***/!!! 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;
                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 ***/!!! 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
DBMS OUTPUT
-----------
1
2
3
4
5
6
7
8
9
10
11
    -- EXECUTE IMMEDIATE NOT EXECUTED, it's not supported

Copy

SELECT INTO-Anweisungsfall

In diesem Fall verwendet die Übersetzungsspezifikation RESULTSETs. Lesen Sie die Dokumentation zu den Anweisungen WITH, SELECT und BULK COLLECT INTO hier:

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

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 nicht unterstützt, können aber manuell in SELECT-Anweisungen geändert werden.

Zugehörige EWIs

  1. [SSC-EWI-0058](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0058): Die Funktionalität wird derzeit nicht von Snowflake Scripting unterstützt.

  2. [SSC-EWI-0062](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0062): Benutzerdefinierte Typverwendung auf Variante geändert.

  3. [SSC-EWI-0073](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0073): Überprüfung der Funktionsäquivalenz ausstehend

  4. [SSC-EWI-OR0036](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0036): Probleme bei der Auflösung von Typen, die arithmetische Operation verhält sich möglicherweise nicht korrekt zwischen Zeichenfolge und Datum.

  5. [SSC-EWI-OR0108](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0108): Die folgende Zuweisungsanweisung wird von Snowflake Scripting nicht unterstützt.

  6. [SSC-FDM-OR0035](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/oracleFDM. md#ssc-fdm-or0035): DBMS_OUTPUT.PUTLINE UDF Implementierung überprüfen.

  7. [SSC-PRF-0001](../../general/technical-documentation/issues-and-troubleshooting/performance-review/README. md#ssc-prf-0001): Diese Anweisung hat Verwendungen von Cursor-Massenabrufoperationen.

  8. [SSC-EWI-0030](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0030): Die folgende Anweisung enthält dynamische SQL-Verwendungen

WITH-, SELECT- und BULKCOLLECTINTO-Anweisungen

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:

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.

 -- 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
 -- 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

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
-- Additional Params: -t JavaScript
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

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

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 Scripting
 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 Helpers Code section is omitted.

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

CALL simple_procedure();
Copy

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:

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
Statement processed.
Average Salary for IT Department: 77500

Copy
Snowflake Scripting
 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;
		  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 ***/!!! LOOP
		  	v_average_salary :=
		  	!!!RESOLVE EWI!!! /*** SSC-EWI-OR0036 - TYPES RESOLUTION ISSUES, ARITHMETIC OPERATION '+' MAY NOT BEHAVE CORRECTLY BETWEEN ExactNumeric 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

SIMPLE_PROCEDURE

Durchschnittsgehalt für IT-Abteilung: 77.500

Known Issues

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.

Related EWIs

  1. [SSC-EWI-0058](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0058): Die Funktionalität wird derzeit nicht von Snowflake Scripting unterstützt.

  2. [SSC-EWI-0062](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0062): Benutzerdefinierte Typverwendung auf Variante geändert.

  3. [SSC-EWI-0073](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/generalEWI. md#ssc-ewi-0073): Überprüfung der Funktionsäquivalenz ausstehend

  4. [SSC-EWI-OR0036](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0036): Probleme bei der Auflösung von Typen, die arithmetische Operation verhält sich möglicherweise nicht korrekt zwischen Zeichenfolge und Datum.

  5. [SSC-EWI-OR0072](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0072): Prozedurales Element nicht unterstützt

  6. [SSC-EWI-OR0104](../../general/technical-documentation/issues-and-troubleshooting/conversion-issues/oracleEWI. md#ssc-ewi-or0104): Unverwendbare Sammelvariable.

  7. [SSC-FDM-0006](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/generalFDM. md#ssc-fdm-0006): Zahlentyp-Spalte verhält sich in Snowflake möglicherweise nicht ähnlich.

  8. [SSC-FDM-OR0035](../../general/technical-documentation/issues-and-troubleshooting/functional-difference/oracleFDM. md#ssc-fdm-or0035): DBMS_OUTPUT.PUTLINE UDF Implementierung überprüfen.

HELPERS

Bulk Cursor-Hilfsfunktion

Bemerkung

Das könnte Sie auch interessieren: Standard FORALL-Transformation.

Der Cursor wird durch ein OBJECT mit verschiedenen Informationen über den Zustand des Cursors simuliert. Es wird eine temporäre Tabelle erstellt, um das Resultset der Abfrage des Cursors zu speichern.

Die meisten dieser Prozeduren geben ein neues Objekt mit dem aktualisierten Status des Cursors zurück.

INIT_CURSOR

Diese Funktion initialisiert ein neues Objekt mit den grundlegenden Cursorinformationen

 CREATE OR REPLACE FUNCTION INIT_CURSOR(NAME VARCHAR, QUERY VARCHAR)
RETURNS OBJECT
AS
$$
  SELECT OBJECT_CONSTRUCT('NAME', NAME, 'ROWCOUNT', -1, 'QUERY', QUERY, 'ISOPEN', FALSE, 'FOUND', NULL, 'NOTFOUND', NULL)
$$;
Copy

OPEN_BULK_CURSOR

Diese Prozeduren erstellen eine temporäre Tabelle mit der Abfrage des Cursors. Es gibt eine optionale Überladung, um Bindungen zu unterstützen.

 CREATE OR REPLACE PROCEDURE OPEN_BULK_CURSOR(CURSOR OBJECT, BINDINGS ARRAY)
RETURNS OBJECT
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
  var query = `CREATE OR REPLACE TEMPORARY TABLE ${CURSOR.NAME}_TEMP_TABLE AS ${CURSOR.QUERY}`;
  snowflake.execute({ sqlText: query, binds: BINDINGS });
  CURSOR.ROWCOUNT = 0;
  CURSOR.ISOPEN = true;
  return CURSOR;
$$;
Copy
 CREATE OR REPLACE PROCEDURE OPEN_BULK_CURSOR(CURSOR OBJECT)
RETURNS OBJECT
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
  DECLARE
    RESULT OBJECT;
  BEGIN
    RESULT := (CALL OPEN_BULK_CURSOR(:CURSOR, NULL));
    RETURN :RESULT;
  END;
$$;
Copy

CLOSE_BULK_CURSOR

Diese Prozedur löscht die temporäre Tabelle, in der das Resultset des Cursors gespeichert war, und setzt die Eigenschaften des Cursors auf ihren Ausgangszustand zurück.

 CREATE OR REPLACE PROCEDURE CLOSE_BULK_CURSOR(CURSOR OBJECT)
RETURNS OBJECT
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
  var query = `DROP TABLE ${CURSOR.NAME}_TEMP_TABLE`;
  snowflake.execute({ sqlText: query });
  CURSOR.ROWCOUNT = -1;
  CURSOR.ISOPEN = false;
  CURSOR.FOUND = null;
  CURSOR.NOTFOUND = null;
  return CURSOR;
$$;
Copy

FETCH-Hilfsfunktion

Da Oracle in der Lage ist, die Anweisung FETCH in verschiedenen Szenarien auszuführen, wurden mehrere Prozeduren mit Überlastungen für jeden Fall erstellt. Diese Hilfsfunktionen speichern die abgerufenen Werte in der Eigenschaft RESULT im CURSOR Objekt.

Einige der Überlastungen beinhalten Variationen, wenn die LIMIT-Klausel verwendet wurde oder nicht. Andere Überlastungen haben ein COLUMN_NAMES-Argument, das notwendig ist, wenn die FETCH-Anweisung in eine Variable ausgeführt wird, die Datensätze mit Spaltennamen hat oder enthält, die sich von den Spaltennamen der Abfrage unterscheiden.

FETCH_BULK_COLLECTION_RECORDS

Diese Prozeduren werden verwendet, wenn FETCH BULK in einer Sammlung von Datensätzen ausgeführt wird.

 CREATE OR REPLACE PROCEDURE FETCH_BULK_COLLECTION_RECORDS(CURSOR OBJECT, LIMIT FLOAT, COLUMN_NAMES ARRAY)
RETURNS OBJECT
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
  var objectConstructArgs = [];
  if (COLUMN_NAMES) {
    for (let i = 0 ; i < COLUMN_NAMES.length ; i++) {
      objectConstructArgs.push("'" + COLUMN_NAMES[i] + "'");
      objectConstructArgs.push('$' + (i + 1));
    }
  } else {
    objectConstructArgs.push('*');
  }
  var limitValue = LIMIT ?? 'NULL';
  var query = `SELECT ARRAY_AGG(OBJECT_CONSTRUCT(${objectConstructArgs.join(', ')})) FROM (SELECT * FROM ${CURSOR.NAME}_TEMP_TABLE LIMIT ${limitValue} OFFSET ${CURSOR.ROWCOUNT})`;
  var stmt = snowflake.createStatement({ sqlText: query});
  var resultSet = stmt.execute();
  resultSet.next();
  CURSOR.RESULT = resultSet.getColumnValue(1);
  CURSOR.ROWCOUNT += CURSOR.RESULT.length;
  CURSOR.FOUND = CURSOR.RESULT.length > 0;
  CURSOR.NOTFOUND = !CURSOR.FOUND;
  return CURSOR;
$$;
Copy
 CREATE OR REPLACE PROCEDURE FETCH_BULK_COLLECTION_RECORDS(CURSOR OBJECT)
RETURNS OBJECT
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
  DECLARE
    RESULT OBJECT;
  BEGIN
    RESULT := (CALL FETCH_BULK_COLLECTION_RECORDS(:CURSOR, NULL, NULL));
    RETURN :RESULT;
  END;
$$;
Copy
 CREATE OR REPLACE PROCEDURE FETCH_BULK_COLLECTION_RECORDS(CURSOR OBJECT, LIMIT INTEGER)
RETURNS OBJECT
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
  DECLARE
    RESULT OBJECT;
  BEGIN
    RESULT := (CALL FETCH_BULK_COLLECTION_RECORDS(:CURSOR, :LIMIT, NULL));
    RETURN :RESULT;
  END;
$$;
Copy
 CREATE OR REPLACE PROCEDURE FETCH_BULK_COLLECTION_RECORDS(CURSOR OBJECT, COLUMN_NAMES ARRAY)
RETURNS OBJECT
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
  DECLARE
    RESULT OBJECT;
  BEGIN
    RESULT := (CALL FETCH_BULK_COLLECTION_RECORDS(:CURSOR, NULL, :COLUMN_NAMES));
    RETURN :RESULT;
  END;
$$;
Copy

FETCH_BULK_COLLECTIONS

Diese Prozeduren werden verwendet, wenn die Anweisung FETCH in einer oder mehreren Sammlungen ausgeführt wird. Da die Spalten in dieser FETCH-Operation angegeben werden, ist eine Überschreibung für spezifische COLUMN_NAMES nicht notwendig.

 CREATE OR REPLACE PROCEDURE FETCH_BULK_COLLECTIONS(CURSOR OBJECT, LIMIT FLOAT)
RETURNS OBJECT
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
  var limitClause = '';
  var limitValue = LIMIT ?? 'NULL';
  var query = `SELECT * FROM ${CURSOR.NAME}_TEMP_TABLE LIMIT ${limitValue} OFFSET ${CURSOR.ROWCOUNT}`;
  var stmt = snowflake.createStatement({ sqlText: query});
  var resultSet = stmt.execute();
  var column_count = stmt.getColumnCount();
  CURSOR.RESULT = [];
  for (let i = 0 ; i < column_count ; i++) {
    CURSOR.RESULT[i] = [];
  }

  while (resultSet.next()) {
    for (let i = 1 ; i <= column_count ; i++) {
      let columnName = stmt.getColumnName(i);
      CURSOR.RESULT[i - 1].push(resultSet.getColumnValue(columnName));
    }
  }
  CURSOR.ROWCOUNT += stmt.getRowCount();
  CURSOR.FOUND = stmt.getRowCount() > 0;
  CURSOR.NOTFOUND = !CURSOR.FOUND;
  return CURSOR;
$$;
Copy
 CREATE OR REPLACE PROCEDURE FETCH_BULK_COLLECTIONS(CURSOR OBJECT)
RETURNS OBJECT
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
  DECLARE
    RESULT OBJECT;
  BEGIN
    RESULT := (CALL FETCH_BULK_COLLECTIONS(:CURSOR, NULL));
    RETURN :RESULT;
  END;
$$;
Copy

FETCH_BULK_RECORD_COLLECTIONS

Diese Prozeduren werden verwendet, wenn FETCH BULK in einem Datensatz von Sammlungen ausgeführt wird.

 CREATE OR REPLACE PROCEDURE FETCH_BULK_RECORD_COLLECTIONS(CURSOR OBJECT, LIMIT FLOAT, COLUMN_NAMES ARRAY)
RETURNS OBJECT
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
  var limitValue = LIMIT ?? 'NULL';
  var query = `SELECT * FROM ${CURSOR.NAME}_TEMP_TABLE LIMIT ${limitValue} OFFSET ${CURSOR.ROWCOUNT}`;
  var stmt = snowflake.createStatement({ sqlText: query});
  var resultSet = stmt.execute();
  var column_count = stmt.getColumnCount();
  CURSOR.RESULT = {};
  if (COLUMN_NAMES)
  {
    for (let i = 0 ; i < COLUMN_NAMES.length ; i++) {
      CURSOR.RESULT[COLUMN_NAMES[i]] = [];
    }
  } else {
    for (let i = 1 ; i <= column_count ; i++) {
      let columnName = stmt.getColumnName(i);
      CURSOR.RESULT[columnName] = [];
    }
  }
  
  while (resultSet.next()) {
    for (let i = 1 ; i <= column_count ; i++) {
      let columnName = stmt.getColumnName(i);
      let fieldName = COLUMN_NAMES ? COLUMN_NAMES[i - 1] : columnName;
      CURSOR.RESULT[fieldName].push(resultSet.getColumnValue(columnName));
    }
  }
  CURSOR.ROWCOUNT += stmt.getRowCount();
  CURSOR.FOUND = stmt.getRowCount() > 0;
  CURSOR.NOTFOUND = !CURSOR.FOUND;
  return CURSOR;
$$;
Copy
 CREATE OR REPLACE PROCEDURE FETCH_BULK_RECORD_COLLECTIONS(CURSOR OBJECT)
RETURNS OBJECT
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
  DECLARE
    RESULT OBJECT;
  BEGIN
    RESULT := (CALL FETCH_BULK_RECORD_COLLECTIONS(:CURSOR, NULL, NULL));
    RETURN :RESULT;
  END;
$$;
Copy
 CREATE OR REPLACE PROCEDURE FETCH_BULK_RECORD_COLLECTIONS(CURSOR OBJECT, LIMIT INTEGER)
RETURNS OBJECT
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
  DECLARE
    RESULT OBJECT;
  BEGIN
    RESULT := (CALL FETCH_BULK_RECORD_COLLECTIONS(:CURSOR, :LIMIT, NULL));
    RETURN :RESULT;
  END;
$$;
Copy
 CREATE OR REPLACE PROCEDURE FETCH_BULK_RECORD_COLLECTIONS(CURSOR OBJECT, COLUMN_NAMES ARRAY)
RETURNS OBJECT
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
  DECLARE
    RESULT OBJECT;
  BEGIN
    RESULT := (CALL FETCH_BULK_RECORD_COLLECTIONS(:CURSOR, NULL, :COLUMN_NAMES));
    RETURN :RESULT;
  END;
$$;
Copy