SnowConvert:PL/SQL からSnowflake Scriptingへ

ASSIGNMENT STATEMENT

説明

割り当てステートメントは、データ項目の値を有効な値に設定します。\ (Oracle PL/SQL 言語リファレンス ASSIGNMENT ステートメント)

注釈

わかりやすくするため、出力コードの一部を省略しています。

 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

注釈

変数が以前に宣言されている場合、LET キーワードは割り当てステートメントでは必要ありません。詳細は Snowflake Assignmentドキュメント を参照してください。

サンプルソースパターン

1.スカラー変数

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スクリプト
 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

警告

いくつかのデータ型の変換を更新する必要があり、異なる結果を引き起こす可能性があります。例えば、NUMBER から NUMBER は値を丸め、小数点は失われます。この問題については、すでに作業項目があります。

2.アウトパラメーター割り当て

出力パラメーターがどのように変換されるかについての詳しい情報は、以下の記事 出力パラメーターをご覧ください。

3.サポートされていない割り当て

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スクリプト
 --** 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

既知の問題

1.いくつかのサポートされていない割り当てステートメント

現在、カーソル、コレクション、記録、ユーザー定義タイプ変数の変換はSnow Scriptingではサポートされていません。そのため、これらの変数を使用する割り当てステートメントにはコメントが付けられ、サポートされていないとマークされています。これらの変数をSnowflakeの 半構造化データ型 に変更することで、シナリオによっては回避策として役立つ可能性があります。

CALL

説明

Oracleの呼び出しステートメントには2つのタイプがあります。

1-CALL ステートメント:

SQL 内からルーチン(スタンドアロンのプロシージャや関数、またはタイプやパッケージ内で定義されたプロシージャや関数)を実行するには、CALL ステートメントを使用します。(Oracle SQL 言語リファレンス CALL)

2-呼び出し仕様:

呼び出し仕様は、JavaメソッドまたはC言語サブプログラムを宣言し、PL/SQL から呼び出せるようにします。(Oracle SQL 言語リファレンス呼び出し仕様)

CALL 仕様は、Cおよび JAVA 用の開発ライブラリの一部であり、SQL ステートメントではないため、Snowflake Scriptingではサポートされておらず、このステートメントは変換されません。

既知の問題

問題は見つかりませんでした。

関連 EWIs

関連 EWIs はありません。

CASE

説明

CASE ステートメントは、一連の条件から選択し、対応するステートメントを実行します。Oracle 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

検索されたケース

 [ <<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

サンプルソースパターン

サンプル補助テーブル

 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

単純なケース

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スクリプト
 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

検索されたケース

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スクリプト
 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

既知の問題

1.Snowflake Scripting CASE 構文ではラベルはサポートされていません

ラベルは位置によってコメントアウトされたり削除されたりします。

関連 EWIS

  1. SSC-EWI-0094: ラベル宣言がサポートされていません。

  2. SSC-FDM-0007: 依存関係のない要素。

COMPOUND STATEMENTS

警告

このセクションは進行中であり、情報は将来変更される可能性があります。

注釈

わかりやすくするため、出力コードの一部を省略しています。

概要

PL/SQL ソースプログラムの基本単位はブロックで、関連する宣言やステートメントをグループ化します。

PL/SQL ブロックはキーワード DECLARE、BEGIN、EXCEPTION、END で定義されます。これらのキーワードは、ブロックを宣言部分、実行部分、例外処理部分に分割します。必要なのは実行部分だけです。(PL/SQL匿名ブロック)

Oracleの BEGIN...END ブロックには以下のような特徴があります。

  1. ネストされます。

  2. 変数の DECLARE ステートメントを含みます。

  3. 複数の SQL または PL/SQL ステートメントをグループ化します。

Oracle構文

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

Snowflake構文

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

注釈

Snowflakeでは、BEGIN/END ブロックを匿名ブロック内の最上位の構造にすることができます(Snowflakeドキュメント)。

サンプルソースパターン

1.IF-ELSE ブロック

IF ステートメントについては、以下のドキュメントを参照してください。SnowConvert IF ステートメント翻訳および Snowflake IF ステートメントドキュメント

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

警告

プロシージャやユーザー定義関数(UDF)を呼び出す場合、call_results 変数として等価性をサポートするコードを生成する必要があります。この場合、情報を印刷するために使用されます。

こちらで使用されているユーザー定義関数(UDF)を確認してください。

 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 ステートメント

詳細情報については、以下のドキュメントを参照してください: SnowConvert CASE ステートメントドキュメントおよび Snowflake CASE ドキュメント

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

警告

プロシージャやユーザー定義関数(UDF)を呼び出す場合、call_results 変数として等価性をサポートするコードを生成する必要があります。この場合、情報を印刷するために使用されます。

こちらで使用されているユーザー定義関数(UDF)を確認してください。

 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 ステートメント

詳細情報については、以下のドキュメントを参照してください: SnowConvert FOR LOOPおよびSnowflake LOOP ドキュメント および FOR ドキュメント

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.プロシージャ呼び出しと OUTPUT パラメーター

Oracleの匿名ブロックはプロシージャへの呼び出しを持つことがあります。さらに、以下のドキュメントが役に立つかもしれません: SnowConvert プロシージャドキュメント

以下の例では、OUT パラメーターを使用しています。現在の変換に関する情報は、こちらをご覧ください: SnowConvert OUTPUT パラメーター

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.セッションを変更

詳細については、次のドキュメントを確認してください: セッションの変更に関するドキュメント

Oracleでは、 BEGIN...END のブロックは、 EXECUTE IMMEDIATE ステートメントを使用して、 alter session ステートメントを実行する必要があることに注意してください。

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

警告

今後、以下の警告が追加される可能性があります:\ /***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.カーソル

次の例では、 BEGIN...END ブロックの中に カーソル を使用しています。詳しくは以下のドキュメントをご覧ください: カーソルドキュメント

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

警告

プロシージャやユーザー定義関数(UDF)を呼び出す場合、call_results 変数として等価性をサポートするコードを生成する必要があります。この場合、情報を印刷するために使用されます。

こちらで使用されているユーザー定義関数(UDF)を確認してください。

 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ステートメント

詳細情報については、以下のドキュメントをご覧ください: Selectドキュメント

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

警告

プロシージャやユーザー定義関数(UDF)を呼び出す場合、call_results 変数として等価性をサポートするコードを生成する必要があります。この場合、情報を印刷するために使用されます。

こちらで使用されているユーザー定義関数(UDF)を確認してください。

 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ステートメント

詳細情報については、以下のドキュメントをご覧ください: Joinsドキュメント

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

警告

プロシージャやユーザー定義関数(UDF)を呼び出す場合、call_results 変数として等価性をサポートするコードを生成する必要があります。この場合、情報を印刷するために使用されます。

こちらで使用されているユーザー定義関数(UDF)を確認してください。

 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.例外処理

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

警告

Snowflakeの ZERO_DIVIDE 例外はサポートされていません。

 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

既知の問題

  1. Oracleでサポートされていない GOTO ステートメント。

  2. GOTO ステートメントを使用する例外も影響を受ける可能性があります。

  3. カーソル機能は、現在の翻訳の制限に従って適応される場合があります。

関連 EWIs

  1. SSC-EWI-0027:次のステートメントは、無効なクエリを含む変数/リテラルを使用しているため、実行されません。

  2. SSC-EWI-OR0036: タイプ解決の問題で、文字列と日付の間で算術演算が正しく動作しない場合があります。

  3. SSC-FDM-OR0035: DBMS_OUTPUT.PUTLINE UDF の実装を確認してください。

  4. SSC-FDM-0006: Snowflakeで数値タイプ列が同様に動作しない場合があります。

  5. SSC-PRF-0004: このステートメントには、cursor for loopの使用があります。

  6. SSC-EWI-0030: 以下のステートメントには動的 SQL の使用法があります

CONTINUE

説明

CONTINUE ステートメントは、条件付きまたは無条件でループの現在の反復を終了し、現在のループまたは囲んでいるラベル付きループの次の反復に制御を移します。\ (Oracle PL/SQL 言語リファレンス CONTINUE ステートメント)

注釈

わかりやすくするため、出力コードの一部を省略しています。

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

サンプルソースパターン

1.単純な継続

コードは CONTINUE を使って INSERT ステートメントをスキップします。

このケースは機能的に等価です。

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 を使って偶数の挿入をスキップします。

注釈

このケースは機能的に等価ではありませんが、条件を IF ステートメントに変えることができます。

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スクリプト
 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.ラベルと条件付きで継続

コードは19行目をスキップし、 CONTINUE は常にラベルを使って外側のループにジャンプするため、内側のループは1回しか実行されません。

このケースは、機能的には前のサンプルと同じプロセスを適用するのと同じです。

注釈

ラベルはコメントアウトされることに注意してください。

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スクリプト
 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

既知の問題

問題は見つかりませんでした。

関連 EWIs

  1. SSC-EWI-0094: ラベル宣言がサポートされていません。

CREATE PROCEDURE

説明

注釈

わかりやすくするため、出力コードの一部を省略しています。

プロシージャとは、 PL/SQL ステートメントのグループで、名前で呼び出すことができます。呼び出し仕様(コールスペックと呼ばれることもあります)は、Javaメソッドまたは第3世代言語(3GL)ルーチンを宣言して、 SQL および PL/SQL から呼び出せるようにします。呼び出し仕様は、呼び出しが行われたときにどのJavaメソッドを呼び出すかをOracleデータベースに伝えます。また、引数と戻り値の型変換もデータベースに指示します。Oracle SQL 言語リファレンスプロシージャの作成

Oracleのプロシージャ作成の詳細情報については、 こちら をご覧ください。

 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

Snowflakeのプロシージャ作成の詳細情報については、 こちら をご覧ください。

 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

サンプルソースパターン

1.基本プロシージャ

 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.異なるパラメーターを持つプロシージャ

 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
出力パラメーター

Snowflakeではプロシージャ内で出力パラメーターを使用することができません。この動作をシミュレートする方法として、変数を宣言し、プロシージャの終了時にその値を返すことができます。

デフォルト値のパラメーター

Snowflakeでは、プロシージャのパラメーターにデフォルト値を設定することはできません。この動作をシミュレートする方法としては、デフォルト値を持つ変数を宣言するか、プロシージャをオーバーロードすることが考えられます。

3.追加設定によるプロシージャ

 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.基本ステートメントによるプロシージャ

 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.RETURN ステートメントが空のプロシージャ

Oracleのプロシージャでは、プロシージャの実行を終了するために空の RETURN ステートメントを持つことができます。Snowflake Scriptingでは、プロシージャは RETURN ステートメントを持つことができますが、値を持つ必要があります。デフォルトでは、空の RETURN ステートメントはすべて NULL 値で変換されます。

 -- 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 ステートメント

出力パラメーターを持つプロシージャでは、Snowflake Scriptingの出力パラメーターをシミュレートするために、空の RETURN ステートメントで NULL 値の代わりに OBJECT_CONSTRUCT が使用されます。

 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.DEFAULT パラメーターを持つプロシージャ

DEFAULT パラメーターは、値が渡されない場合、名前付きパラメーターをデフォルト値で初期化することができます。

 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

既知の問題

1.サポートされていない OUT パラメーター

Snowflakeプロシージャには、出力パラメーターのネイティブオプションがありません。

2.サポートされていないOracleの追加設定

以下のOracle設定および句は、Snowflakeプロシージャではサポートされていません。

  • sharing_clause

  • default_collation_option

  • invoker_rights_clause

  • accessible_by_clause

  • java_declaration

  • c_declaration

関連 EWIS

  1. SSC-EWI-0058: この関数は現在Snowflake Scriptingではサポートされていません

  2. SSC-EWI-OR0097: プロシージャのプロパティはSnowflakeプロシージャではサポートされていません。

  3. SSC-FDM-OR0012: COMMIT と ROLLBACK ステートメントが意図したとおりに機能するためには十分なセットアップが必要です。

  4. SSC-PRF-0003: ループ内のフェッチは複雑なパターンとみなされるため、Snowflakeのパフォーマンスが低下する可能性があります。

  5. SSC-PRF-0004: このステートメントには、cursor for loopの使用があります。

  6. SSC-EWI-0030: 以下のステートメントには動的 SQL の使用法があります

DECLARE

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

Oracle DECLARE ステートメントは、 PL/SQL ブロックステートメントのオプション部分です。変数、定数、プロシージャの宣言と定義、関数の宣言と定義、例外、カーソル、タイプ、その他多くのステートメントを作成することができます。Oracle DECLARE に関する詳細情報については、 こちら をご覧ください。

 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

サンプルソースパターン

変数宣言

 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スクリプト
 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

定数宣言

警告

定数はSnowflake Scriptingではサポートされていませんが、動作をシミュレートするために変数に変換しています。

 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スクリプト
 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

カーソル宣言

 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

Oracle _ カーソル宣言 _ は必須ではありませんので、出力コードではコメントアウトされているかもしれません。_ カーソル定義 _ が代わりに使用され、Snowflake Scripting _ カーソル宣言 _ に変換されます。カーソル定義の詳細については CURSOR セクションを参照してください。

例外宣言

例外宣言の後に例外の初期化が続くことがありますが、今回の変換ではその両方を受け取り、Snowflake Scriptingの例外宣言にマージします。元の PRAGMA EXCEPTION_INIT はコメントアウトされます。

 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

サポートされていないケース

次のOracle宣言ステートメントは、Snowflake Scripting宣言ブロックではサポートされていません。

  1. カーソル変数の宣言。

  2. コレクション変数の宣言。

  3. 記録変数の宣言。

  4. タイプ定義(すべてのバリアント)。

  5. 関数の宣言と定義。

  6. プロシージャの宣言と定義。

Known issues

1.NOT NULL 制約を含む変数宣言はSnow Scriptingではサポートされていません。

Snow Scriptingで、 NOT NULL 制約を持つ変数の作成でエラーが発生しました。

2.カーソル宣言は、Snowflake Scriptingには相当するものがありません。

Oracleのカーソル宣言は役に立たないので、出力コードではコメントアウトされているかもしれません。カーソル定義が代わりに使用され、Snowflake Scriptingのカーソル宣言に変換されます。

3.例外コードがSnowflake Scriptingの制限を超えています。

Oracle例外コードは、Snowflake Scriptingコード制限を超えると削除されます。例外コードは-20000と-20999の間の整数でなければなりません。

3.サポートされていないケース。

Oracleの宣言ステートメントの中には、Snowflake Scriptingの宣言ブロックでサポートされていないものがあるため、コメントアウトされ、警告が追加される場合があります。

Related EWIS

  1. SSC-EWI-OR0051: PRAGMA EXCEPTION_INIT はサポートされていません。

  2. SSC-EWI-OR0099: 例外コードがSnowflake Scriptingの制限を超えています。

  3. SSC-FDM-0016: 定数はSnowflake Scriptingではサポートされていません。変数に変換されました。

  4. SSC-FDM-OR0025: Not Null制約はSnowflakeプロシージャではサポートされていません。

DEFAULT PARAMETERS

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

デフォルトパラメーター は、プロシージャや関数の呼び出しで引数が渡されなかった場合に値を持つパラメーターのことです。Snowflakeはデフォルトのパラメーターをサポートしていないため、 SnowConvert はプロシージャまたは関数の呼び出しにデフォルト値を挿入します。

宣言では、パラメーターの DEFAULT VALUE 句が削除されます。:= 記号と DEFAULT 句の両方の構文がサポートされています。

サンプルソースパターン

補助コードのサンプル

 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

デフォルトパラメーター宣言

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スクリプト
 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

デフォルトパラメーターを持つプロシージャの呼び出し

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スクリプト
 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

機能が正しくエミュレートされていることを確認するために、次のクエリは、前述のテーブルからプロシージャと SELECT を実行します。

Oracle
 CALL PROC_WITH_DEFAULT_CALLS();

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


Copy
Snowflakeスクリプト
 CALL PROC_WITH_DEFAULT_CALLS();

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


Copy

名前付き引数とデフォルトパラメーターを持つプロシージャの呼び出し

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スクリプト
 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

機能が正しくエミュレートされていることを確認するために、次のクエリは、前述のテーブルからプロシージャと SELECT を実行します。

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スクリプト
 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

既知の問題

1.問題が見つかりません

関連 EWIs

関連 EWIs はありません。

EXECUTE IMMEDIATE

説明

EXECUTE IMMEDIATE ステートメントは、1回の操作で動的な SQL ステートメントを構築し、実行します。

ネイティブの動的 SQL は、 EXECUTE IMMEDIATE ステートメントを使用して、ほとんどの動的 SQL ステートメントを処理します。(Oracle PL/SQL 言語リファレンス EXECUTE IMMEDIATE ステートメント)

 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は、いくつかの機能的な違いはあるものの、このステートメントをサポートしています。Snowflakeのカウンターパートの詳細情報については、 Snowflakeの EXECUTE IMMEDIATE ドキュメント をご覧ください。

 EXECUTE IMMEDIATE <dynamic statement> ;

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

サンプルソースパターン

次のサンプルでは、テーブルを作成し、Execute Immediateを使用してテーブルのドロップを試みます。

ハードコードされた文字列の使用

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スクリプト
 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

文字列の変数への格納

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スクリプト
 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

動的ステートメントでのパラメーターの連結

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スクリプト
 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

USING 句の変換

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スクリプト

注釈

Snowflake Scriptingの USING 句のパラメーターには括弧が必要です。

 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

既知の問題

1.Immediate Executionの結果を変数に格納することはできません。

SnowScripting は INTO も BULK COLLECT INTO 句もサポートしていません。このため、結果は別の手段で渡す必要があります。

2.数値プレースホルダー

プレースホルダーの数値名は現在、 SnowConvert によって認識されませんが、この問題を修正するための作業項目があります。

3.引数式はSnowflake Scriptingではサポートされていません

Oracleでは、Using句の引数として式を使用することができますが、Snowflake Scriptingではサポートされていないため、コメントアウトされています。

4.動的 SQL 実行クエリが誤って実行不可とマークされることがあります。

シナリオによっては、実行が安全か安全でないかに関係なく、実行ステートメントがコメントされる可能性があるため、これを考慮してください。

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スクリプト

注釈

Snowflake Scriptingの USING 句のパラメーターには括弧が必要です。

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

関連 EWIs

  1. SSC-EWI-0027: クエリが無効な変数です。

  2. SSC-EWI-0030: 以下のステートメントには、動的 SQL の使用があります。

EXIT

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

EXIT ステートメントは、条件付きまたは無条件でループの現在の反復を終了し、現在のループまたは囲んでいるラベル付きループの終了に制御を移します。\ (Oracle PL/SQL 言語リファレンス EXIT ステートメント)

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

サンプルソースパターン

注釈

BREAKEXIT を変更しても、すべて同じように動作することに注意してください。

1.単純な終了

コードは EXIT を使って INSERT ステートメントをスキップします。

このケースは機能的に等価です。

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.条件付きで終了

コードはイテレータが5より大きいときにループを終了します。

このケースは、条件を IF ステートメントに変えることで、機能的に等価になります。

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スクリプト
 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 ステートメントを使用して、両方のループを解除します。

このケースは、機能的には前のサンプルと同じプロセスを適用するのと同じです。

注釈

ラベルはコメントアウトされることに注意してください。

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スクリプト
 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

既知の問題

問題は見つかりませんでした。

関連 EWIs

  1. SSC-EWI-0094: ラベル宣言がサポートされていません。

EXPRESSIONS

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

次のテーブルは、異なる種類の Oracle式 をSnow Scriptingに変換する方法の要約です。

構文

変換ステータス

注意

文字式

部分的

部分的にサポートされる一般的なシナリオ

数値式

部分的

部分的にサポートされる一般的なシナリオ

日付式

部分的

部分的にサポートされる一般的なシナリオ

ブール式

部分的

サポートされていないブール式

単純なケース式

完全

N/A

検索されたケース式

完全

N/A

コレクションコンストラクター

翻訳されていません

Snowflakeには、Oracleコレクションと同等のネイティブ機能はありません。コレクションと記録を参照してください。

修飾式

翻訳されていません

Snowflakeには、Oracleの記録タイプと同等のネイティブ機能はありません。コレクションと記録を参照してください。

部分的にサポートされる一般的なシナリオ

Oracle定数

詳細情報については、 Oracle定数宣言セクションを確認してください。

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

サポートされていない数値式

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

サポートされていないブール式

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

関連 EWIs。

  1. SSC-FDM-0016: 定数はSnowflake Scriptingではサポートされていません。変数に変換されました。

FOR LOOP

説明

FOR LOOP ステートメントが繰り返されるたびに、ステートメントが実行され、インデックスがインクリメントまたはデクリメントされ、制御はループの先頭に戻ります。(Oracle PL/SQL 言語リファレンス FOR LOOP ステートメント)。

 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は、指定回数ループする FOR LOOP をサポートしています。上下限は INTEGER でなければなりません。詳細は Snowflake Scriptingドキュメント を参照してください。

Oracle FOR LOOP の動作もステートメントで変更できます。

サンプルソースパターン

1.FOR LOOP

このケースは機能的に等価です。

 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

 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

 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

 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

警告

カスタムタイプの変換は、現在Snowflake Scriptingではサポートされていません。

既知の問題

1.複数の条件を含むFor

Oracleでは、1つの FOR LOOP に複数の条件を設定できますが、Snowflake Scriptingでは、1つの FOR LOOP に1つの条件しか設定できません。最初の条件だけが移行され、他の条件は変換中に無視されます。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.Mutable・Counter変数とInmutable Counter変数

Oracleでは、ループ内部で変数 FOR LOOP の値を変更することができます。現在のドキュメント にはこの機能が含まれていますが、Snowflakeはこれを避けることを推奨します。この変数の値を変更すると、Snowflake Scriptingで正しく動作しない場合があります。

3.上限または下限の整数と浮動小数点数

Snowflake Scriptingでは、 FOR LOOP 条件の境界として、 INTEGER または INTEGER と評価される式のみが許可されます。浮動小数点数は切り上げまたは切り下げされ、元の境界を変更します。SSC-EWI-OR0102 を確認してください。

4.Oracleでサポートされていない句

Oracleでは、 FOR LOOP 条件に句を追加することができます。 BY 句のように、条件を段階的にインクリメントします。また、 WHILEWHEN 句はブール式です。これらの追加句はSnowflake Scriptingではサポートされておらず、変換時には無視されます。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.サポートされていない形式

Oracleでは、 FOR LOOP にさまざまなタイプの条件を指定できます。ブール式、コレクション、記録などをサポートします。ただし、Snowflake Scriptingでは、境界として定義された整数を持つ FOR LOOP のみをサポートします。それ以外の形式はサポート外と表示され、変換には手作業が必要となります。SSC-EWI-OR0103を確認してください。

関連 EWIs

  1. SSC-EWI-0058: この関数は現在Snowflake Scriptingではサポートされていません。

  2. SSC-EWI-0062: カスタムタイプの使用がバリアントに変更されました。

  3. SSC-EWI-OR0100: 複数の条件を含むFor Loopは現在Snowflake Scriptingではサポートされていません。最初の条件のみが使用されます。

  4. SSC-EWI-OR0101: 特定のFor Loop句は現在Snowflake Scriptingではサポートされていません。

  5. SSC-EWI-OR0103: For Loop形式は現在Snowflake Scriptingではサポートされていません。

FORALL

説明

FORALL ステートメントは、1つの DML ステートメントを複数回実行し、 VALUESWHERE 句に異なる値を指定します。(Oracle PL/SQL 言語リファレンス FORALL ステートメント)。

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

警告

Snowflake Scriptingは FORALL ステートメントと直接等価ではありませんが、さまざまな回避策でエミュレートし、機能的に等価にすることができます。

サンプルソースパターン

セットアップデータ

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

Oracle

以下の3つのケースは、Snowflake Scriptingへの変換が同じであり、機能的にも等価です。

 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

注釈

EWIs SSC-PRF-0001と SSC-PRF-0003は、 FORALL ステートメントに FETCH BULK COLLECT ごとに追加されます。

2.INSERT INTO を使用した FORALL

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

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

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.動的 SQL を含む FORALL

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.リテラル SQL を含む FORALL

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

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.LOOPS なしの FORALL

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.UPDATE ステートメントを含む FORALL

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.DELETE ステートメントを含む FORALL

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.PACKAGE 参照を含む FORALL

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

警告

上記の変換は、パッケージで定義された変数がコレクションの記録である場合にのみ機能します。

12.MERGE ステートメントを含む FORALL

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

警告

上記の変換は、 MERGE 内部の SELECT ステートメントが DUAL テーブルから選択している場合にのみ機能します。

13.デフォルト FORALL 変換

注釈

一括カーソルヘルパー もご覧ください。

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

注釈

この変換は、先に述べた変換がどれもできない場合にのみ行われます。

14.LOOP 句の中の複数の FORALL

注釈

このパターンは、同じプロシージャに複数の FORALL があり、以下の構造を満たす場合に適用されます。

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.異なる LOOP 句の中の複数の FORALL

注釈

このパターンは、同じプロシージャに複数の FORALL があり、以下の構造を満たす場合に適用されます。

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.MERGE INTO と LOG ERRORS の FORALL

警告

このパターンはまだ実装されていません

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.INSERT と LOG ERRORS の FORALL

警告

このパターンはまだ実装されていません

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

既知の問題

問題は見つかりませんでした。

関連 EWIs

  1. SSC-EWI-0030: 以下のステートメントには、動的 SQL の使用があります。

  2. SSC-EWI-0036: データ型が別のデータ型に変換されました。

  3. SSC-EWI-0056: 作成タイプがサポートされていません。

  4. SSC-EWI-0058: この関数は現在Snowflake Scriptingではサポートされていません。

  5. SSC-EWI-0062: カスタムタイプの使用がバリアントに変更されました。

  6. SSC-EWI-OR0049: ステートフルパッケージのパッケージ定数はまだサポートされていません。

  7. SSC-FDM-0006: Snowflakeで数値タイプ列が同様に動作しない場合があります。

  8. SSC-FDM-0015:クエリで参照されているカスタムタイプが見つかりません。

  9. SSC-PRF-0001: このステートメントには、カーソルフェッチの一括操作の使用があります。

  10. SSC-PRF-0003: ループ内のフェッチは複雑なパターンとみなされるため、Snowflakeのパフォーマンスが低下する可能性があります。

IF

説明

IF ステートメントは、 BOOLEAN 式の値に応じて、1つ以上のステートメントのシーケンスを実行するかスキップします。Oracle IF に関する詳細情報については、 こちら をご覧ください。

 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

サンプルソースパターン

サンプル補助テーブル

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

考えられる IF バリエーション

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スクリプト
 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

既知の問題

問題は見つかりませんでした。

関連 EWIS

関連 EWIs はありません。

IS EMPTY

警告

このセクションは進行中であり、情報は将来変更される可能性があります。

説明

IS [NOT] EMPTY 条件を使用して、コレクションの要素が NULL であるかどうかに関係なく、指定されたネストされたテーブルが空かどうかをテストします。(ドキュメント)。

Oracle構文

 nested_table IS [ NOT ] EMPTY
Copy

サンプルソースパターン

Oracle

次の例は、 IS EMPTY ステートメントの使用例です。ステートメントは、 UDT を定義型として使用するネストされたテーブルに対して適用されます。出力には、電話番号を持っていない従業員の名前が表示されます。

 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

ジェーン・スミス

Snowflake

以下に示すSnowflakeクエリは、 IS EMPTY ステートメントの機能と同等です。特に、 IS EMPTY ステートメントには、 NULL と EMPTY オブジェクトの違いがあります。

ユーザー定義型が VARIANT に変換されていることに注目してください。Snowflakeの VARIANT 型はオブジェクトや配列を格納することができます。ネストされたテーブルは一連の情報であるため、 ARRAY 型はそれらを再定義し、オブジェクト ARRAY が空であるかどうかを検証するのに最も適した型です。

ARRAY_SIZE の等価の解決策は、ネストされたテーブルの無効性(VARIANT に変換)を求めることもできます。言い換えれば、 VARIANT 型は、 NULLs と空の ARRAYs も格納できます。

 !!!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

ジェーン・スミス

その他の可能な組み合わせ

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;
```

既知の問題

1.ユーザー定義型はバリアントに変換されます。

ユーザー定義型はサポートされていないため、いくつかの機能を確保するために手作業が必要となるバリアント型に変換されます。

詳細は以下のページをご覧ください。

create-type-statement

2.ネストされたテーブルはサポートされていません。

ネストされたテーブルは現在サポートされていません。この等価性に基づく最良のアプローチは、ネストされたテーブルをバリアントとして扱いますが、 JSON データを内部に持つ配列を宣言し、 PARSE_JSON Snowflake関数を実行してネストされた情報を入力することです。

詳細は以下のページをご覧ください。

nested-table-array-type-definition.md

nested-table-type-definition.md

3.Insertステートメントはユーザー定義型ではサポートされていません。

ユーザー定義型はサポートされていないため、これらの型へのInsertステートメントはサポートされていません。特にネストされたテーブルでは、 INSERT INTO ... VALUES ステートメントを INSERT INTO ...SELECT に変更する必要があります。これは、 ARRAY_CONSTRUCT 関数がこのパターンで使用されることが期待されているためです。

詳細は以下のページをご覧ください。

object-type-definition.md

4.ロジックは ARRAY 型に合わせて調整する必要があります。

ネストされたテーブルは、 VARIANT に等価に変換され、 ARRAYs として動作する必要があるため、プロシージャの実装やデータとのインタラクションの機能とロジックを適合させる必要があります。

以下の例をご覧ください。

4.1 プロシージャの等価性
 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ステートメント

出力はテーブルから ARRAYs まで異なる場合があります。

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 ]

関連 EWIs

  1. SSC-EWI-0056: 作成タイプがサポートされていません。

  2. SSC-EWI-0062: カスタムタイプの使用がバリアントに変更されました。

  3. SSC-EWI-0073: 機能同等性レビュー保留中。

  4. SSC-EWI-OR0035: テーブル関数が式の集合として使用されている場合はサポートされていません。

  5. SSC-FDM-0006: Snowflakeで数値タイプ列が同様に動作しない場合があります。

  6. SSC-FDM-0015:クエリで参照されているカスタムタイプが見つかりません。

  7. SSC-FDM-OR0035: DBMS_OUTPUT.PUTLINE UDF の実装を確認してください。

LOCK TABLE

注釈

関連性のないステートメント。

警告

このステートメントは 関連性のない構文であるため、 移行から削除されていることに注意してください。 Snowflakeでは必要ないということです。

説明

Oracleでは、 LOCK TABLE ステートメントにより、指定したテーブルの共有または排他テーブルロックを明示的に取得できます。テーブルロックは現在のトランザクションが終了するまで続きます。詳しくは こちら をご覧ください。

構文

 LOCK TABLE tableName IN { SHARE | EXCLUSIVE } MODE
Copy

サンプルソースパターン

ロック中のテーブル

この例では、 LOCK TABLE ステートメントが削除されていることに注意してください。これは、Snowflakeがトランザクションを通じて別の方法でロックを処理するためです。

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

LOG ERROR

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

FORALL ステートメントは、1つの DML ステートメントを複数回実行し、 VALUESWHERE 句に異なる値を指定します。(Oracle PL/SQL 言語リファレンス FORALL ステートメント)。

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

警告

Snowflake Scriptingは FORALL ステートメントと直接等価ではありませんが、さまざまな回避策でエミュレートし、機能的に等価にすることができます。

サンプルソースパターン

セットアップデータ

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.FORALL 内の MERGE INTO

Oracle

以下の3つのケースは、Snowflake Scriptingへの変換が同じであり、機能的にも等価です。

 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

注釈

EWIs MSCCP0005 と SSC-PRF-0003は、 FETCH BULK COLLECT が出現するたびに FORALL ステートメントに追加されます。

2.INSERT INTO を使用した FORALL

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

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

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.動的 SQL を含む FORALL

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.LOOPS なしの FORALL

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.UPDATE ステートメントを含む FORALL

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.DELETE ステートメントを含む FORALL

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

既知の問題

問題は見つかりませんでした。

関連 EWIs

  1. SSC-EWI-0030: 以下のステートメントには、動的 SQL の使用があります。

  2. SSC-EWI-0036: データ型が別のデータ型に変換されました。

  3. SSC-EWI-0058: この関数は現在Snowflake Scriptingではサポートされていません。

  4. SSC-EWI-0062: カスタムタイプの使用がバリアントに変更されました。

  5. SSC-EWI-OR0129: TYPE 属性を解決できませんでした。

  6. SSC-FDM-0006: Snowflakeで数値タイプ列が同様に動作しない場合があります。

  7. SSC-FDM-OR0031: DML ステートメント内のエラーログ句はSnowflakeではサポートされていません。

  8. SSC-PRF-0001: このステートメントには、カーソルフェッチの一括操作の使用があります。

  9. SSC-PRF-0003: ループ内のフェッチは複雑なパターンとみなされるため、Snowflakeのパフォーマンスが低下する可能性があります。

LOOP

説明

基本的な LOOP ステートメントが繰り返されるたびに、ステートメントが実行され、制御はループの先頭に戻ります。LOOP ステートメントは、ループ内のステートメントがループ外に制御を渡すか、例外を発生させると終了します。\ (Oracle PL/SQL 言語リファレンス BASIC LOOP ステートメント)

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

Oracle BASIC LOOP の動作もステートメントで変更できます。

サンプルソースパターン

ループの単純なケース

このケースは機能的に等価です。

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

問題は見つかりませんでした。

Related EWIs

関連 EWIs はありません。

OUTPUT PARAMETERS

Description

出力パラメーター は、ストアドプロシージャ/関数モジュールから、呼び出し元の PL/SQL ブロックに値が渡されるパラメーターです。出力パラメーターはSnowflake Scriptingではサポートされていないため、その機能をエミュレートするためのソリューションが実装されています。

Sample Source Patterns

サンプル補助テーブル

 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

宣言では、 OUT または IN OUT キーワードは削除されます。割り当ては入力と同じように行われますが、出力パラメーターの機能をエミュレートするためにいくつかのステートメントが追加されています。

出力パラメーターを持つプロシージャが別のプロシージャに呼び出される場合、それぞれの引数の値を取得し、割り当てるためにいくつかのステートメントが追加されます。

単一の出力パラメーター

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

複数の出力パラメーター

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

機能が正しくエミュレートされていることを確認するために、次のクエリは、前述のテーブルからプロシージャと SELECT を実行します。

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

顧客データ型 OUT パラメーター

出力パラメーターが顧客型の場合、処理は通常のデータ型と同様です。

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.パッケージ内の出力パラメーターを持つプロシージャが正しく動作しない場合があります

現在、パッケージ内に存在するプロシージャのセマンティック情報を収集することに問題があり、そのために出力パラメーターの変換が部分的に機能したり、まったく機能しなかったりします。この問題を解決するための作業がすでに進行中です。

2.データ型によっては正常に動作しない場合があります

変換に見られるように、呼び出されたプロシージャから値を取得するとき、 VARIANT から変数で指定された型への暗黙のキャストが実行されます。可能なデータ型は多数あるため、キャストによっては失敗したり、異なるデータを含むことがあります。

Related EWIs

  1. SSC-FDM-0006: Snowflakeで数値タイプ列が同様に動作しない場合があります。

  2. SSC-FDM-0007: 依存関係のない要素。

  3. SSC-FDM-0015: データ型が認識されません。

PROCEDURE CALL

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

このセクションでは、プロシージャや匿名ブロックなど、 PL ブロック内のサブプログラム呼び出しの構文について説明します。

この件に関する詳細は、Oracleのサブプログラムのドキュメントを参照してください: (Oracle PL/SQL 言語リファレンスサブプログラム呼び出しステートメント)

プロシージャ呼び出しは、オプションのパラメーターがなく、その順序が正式なパラメーターと一致する限り、Snowflakeに移行できます。プロシージャの呼び出しはCallステートメントに移行することに注意してください。

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

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

Snowflake Scriptingは、いくつかの機能的な違いはあるものの、このステートメントをサポートしています。

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

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

サンプルソースパターン

注釈

次のテーブルとプロシージャの例を考えてみましょう。

 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

単純な呼び出し

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スクリプト
 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

オプションのパラメーターを持つプロシージャの呼び出し

警告

このサンプルには、いくつかの機能差に対する手動の介入が含まれており、それらを説明するために使用されます。これらの相違点の詳細については、以下の「既知の問題」セクションをご確認ください。

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スクリプト
 -- 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

既知の問題

1.デフォルト値でのサブプログラムの呼び出しはサポートされていません

Snowflakeはパラメーターのデフォルト値のセットをサポートしていません。したがって、これらをすべての呼び出しに入力する必要があります。

2.名前付きパラメーターは使用可能ですが、機能的には等価ではありません

これらのパラメーターは、Snowflakeで実行してもコンパイルエラーは発生しませんが、呼び出しでは位置指定が行われます。そのため、これらのパラメーターの順番をチェックする必要があります。SnowConvert はこれらのパラメーターのチェックや並び替えをサポートしていません。

3.出力パラメーターによるサブプログラムの呼び出しはサポートされていません

Snowflakeはパラメーターモードをサポートしていませんが、その機能をエミュレートするソリューションが実装されています。出力パラメーターの変換に関する詳しい情報は、以下の記事 出力パラメーターをご覧ください。

関連 EWIs

  1. SSC-EWI0002: デフォルトパラメーターの順番を変更する必要があります。

  2. SSC-FDM-0007: 依存関係のない要素。

RAISE

説明

RAISE ステートメントは明示的に例外を発生させます。

例外ハンドラーの外では、例外名を指定する必要があります。例外ハンドラーの内部では、例外名を省略すると、 RAISE ステートメントが現在の例外を再度発生させます。(Oracle PL/SQL 言語リファレンスRaiseステートメント)

ステートメントはSnowflake Scriptingで完全にサポートされていますが、いくつかのコミットステートメントとロールバックステートメントを持つ場合、いくつかの違いがあるかもしれないことを考慮してください。

 RAISE <exception_name> ;
Copy

Snowflake Scriptingはこのステートメントをサポートしています。

 RAISE <exception_name> ;
Copy

サンプルソースパターン

単純な例外のスロー

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スクリプト
 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

既知の問題

問題は見つかりませんでした。

関連 EWIs

関連 EWIs はありません。

RAISE_APPICATION_ERROR

概要

プロシージャ RAISE_APPLICATION_ERROR では、ストアドサブプログラムからユーザー定義の ORA- エラーメッセージを発行することができます。そうすることで、アプリケーションにエラーを報告し、処理されない例外を返すことを避けることができます(Oracleドキュメント)。

Oracle構文

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

注釈

error_number は-20000から-20999までの範囲の負の整数で、 message は2048バイトまでの文字列です。

オプションの3つ目のパラメーターが TRUE の場合、エラーは以前のエラーのスタックに置かれます。パラメーターが FALSE (デフォルト)の場合、エラーは以前のエラーをすべて置き換えます。

Snowflakeの同等のステートメントは RAISE 句です。ただし、ユーザー定義の例外を変数として宣言してから、その例外のための RAISE ステートメントを呼び出す必要があります。

Snowflake構文

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

注釈

詳細情報については、以下の Snowflakeドキュメント を参照してください。

サンプルソースパターン

1.セクションを宣言しない関数での例外

このシナリオでは、宣言セクションのない関数は例外宣言のあるプロシージャに翻訳されます。以下の点にご注意ください。

  • 例外変数名は大文字で宣言されます。

  • 例外変数名は説明に基づき、末尾は例外コード名と連続番号で構成されます。

  • 最初の関数やプロシージャに宣言セクションがなくても、宣言セクションは作成されます。

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.制限外の例外コード番号

次の例では、プロシージャ本文でコメントアウトされた翻訳を示しています。これは、コードがSnowflakeの適用可能なコード制限外にあるためです。解決策は、クエリセクションで利用可能なコードの例外コードを変更することです。

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.例外スタック機能

例外スタック機能はSnowflakeではサポートされていないため、例外宣言から削除されています。

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.同じ例外コードを持つ複数の例外

宣言セクションとraiseステートメントには、同じ例外を複数共存させることができます。

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

既知の問題

  1. SQLREM 関数が見直される可能性があります。

  2. Snowflakeで適用可能な制限外の例外コード番号を利用可能なコード例外に変更する必要があります。

  3. エラーのスタックへの追加はサポートされていません。

関連 EWIs

  1. SSC-EWI-OR0099: 例外コードがSnowflake Scriptingの制限を超えています。

  2. SSC-FDM-0029: ユーザー定義関数がSnowflakeプロシージャに変換されました。

  3. SSC-FDM-OR0011: 「スタックに追加」オプションがサポートされていないため、ブール引数が削除されました。

UDF CALL

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

広く知られているように、Oracleのスカラーでないユーザー定義関数(UDFs)は、より複雑な機能に対応するためにSnowflakeのストアドプロシージャに変換されます。

この変換により、関数の呼び出し方も変わり、従来の関数呼び出しからストアドプロシージャ呼び出しに移行します。

ストアドプロシージャの呼び出しに関する詳細は、ここからアクセスできるドキュメントを参照してください: PROCEDURE CALL

サンプルソースパターン

注釈

次の関数とテーブルの例を考えてみましょう。

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 呼び出し

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スクリプト
 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 呼び出し

関数呼び出しがクエリ内に埋め込まれている場合、クエリ内でプロシージャを直接呼び出すことができないというSnowflakeの制限により、呼び出しプロセスが複雑になります。この制限を克服するために、プロシージャの呼び出しはクエリの外部に移動され、結果は変数に割り当てられます。この変数がクエリ内で参照されることで、機能的等価性が達成されます。このアプローチにより、プロシージャ制約を遵守しながら、Snowflakeクエリ内でより複雑な動作を実行することができます。

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スクリプト
 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

既知の問題

1.クエリ依存関係のあるクエリでの UDFs のサポートされていない使用

クエリ依存関係を持つクエリ内でユーザー定義関数(UDFs)を呼び出す場合、列を引数に持つ埋め込み関数を含むシナリオはサポートされません。クエリの外部から列値にアクセスできないため、このような制限が生じます。サポートされていないシナリオの例としては、以下のようなものがあります。

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

\ サポートされるシナリオには、リテラル値、外部変数、パラメーターなど他のタイプの引数を持つ関数呼び出しが含まれます。例:

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

サポートされているシナリオでは、関数を効果的に移行することができます。

関連 EWIs

  1. SSC-EWI-0073: 機能同等性レビュー保留中。

  2. SSC-FDM-0006: Snowflakeで数値タイプ列が同様に動作しない場合があります。

  3. SSC-FDM-0029: ユーザー定義関数がSnowflakeプロシージャに変換されました。

WHILE

説明

WHILE LOOP ステートメントは、条件が TRUE である間、1つ以上のステートメントを実行します。\ (Oracle PL/SQL 言語リファレンス WHILE ステートメント)

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

Oracle WHILE の動作もステートメントで変更できます。

サンプルソースパターン

Whileの単純なケース

このケースは機能的に等価です。

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

問題は見つかりませんでした。

Related EWIs

関連 EWIs はありません。

CURSOR

Description

注釈

カーソル宣言に関する詳しい情報は、 こちらを参照してください。

このセクションでは、Oracle 明示的カーソル の翻訳リファレンスについて説明します。Oracle カーソル変数 については、Snowflake Scriptingには同等のものはありません。

注釈

わかりやすくするため、出力コードの一部を省略しています。

カーソルは、ユーザーがクエリ結果を反復処理できるようにするポインターです。Oracleのカーソルの詳細情報については、 こちら をご覧ください。

Cursor Definition

 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

Cursor Attributes

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

Cursor FOR Loop

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

Snowflake Scriptingはカーソルをサポートしていますが、Oracleと比較すると機能は少ないです。これらのカーソルに関する詳しい情報は、 こちら をご覧ください。

カーソル宣言

 <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 Loop

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

サンプルソースパターン

1.基本的なカーソルの例

 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.明示的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.暗黙的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.パラメーター化されたカーソル

「?」を使用できます宣言セクションのカーソルのフィルター条件で、バインド変数を定義します。カーソルを開いている間に、バインド変数を渡すために「USING <bind_variable_1 >」という構文を追加することができます。

以下は、カーソルでパラメーターを使用する際に起こりうるシナリオの例です。

4.1 基本的なカーソルのパラメーター化の例
 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 複数の送信パラメーターを持つパラメーター化カーソル
 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 クエリでプロシージャパラメーターを使用するパラメーター化カーソル
 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.FetchとFor Loopでのカーソルの使用

カーソルは FOR ステートメントを使用して制御することができ、カーソルの各記録を処理することができます。一方、 FETCH ステートメントは、カーソルによって返された値を記録ごとに変数のセットに格納します。この変数は PLSQL 記録である可能性があります

5.1 Cursors For Loop
 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

既知の問題

1.RETURN 句はSnowflake Scriptingのカーソル宣言ではサポートされていません

Snowflake Scriptingのカーソル宣言にはこの句はありません。Oracleのカーソル定義からこれを削除することで、機能的等価性を得ることができます。

2.OPEN ステートメントは宣言された引数の値を渡すことはできません

カーソルに対して引数を宣言することができても、Snowflake Scriptingではその値を割り当てることはできません。最善の代替案は、バインド変数とともに USING 句を使用することです。

3.FETCH ステートメントで記録を使用することはできません

Snowflake Scriptingは記録をサポートしていません。しかし、 OBJECT データ型と OBJECT_CONSTRUCT()メソッドを使って移行することは可能です。詳しくは 記録タイプ定義セクションをご覧ください。

4.FETCH BULK COLLECT INTO 句はSnowflake Scriptingではサポートされていません

Snowflake Scriptingは BULK COLLECT INTO 句をサポートしていません。しかし、 ARRAY_AGG を一時テーブルと共に使用することで、カーソル情報に対応するデータを持つ新しい変数を構築することが可能です。詳細情報については、 コレクション一括操作セクションを参照してください。

5.Snowflake Scriptingにカーソル属性は存在しません

Oracleカーソルには、カーソルが開かれているかどうかやフェッチされた行数などのステータスをユーザーが確認できるさまざまな属性がありますが、カーソルステータスに関するこれらの属性はSnowflake Scriptingには存在しません。

6.カーソルのクエリはプロシージャの変数やパラメーターにアクセスできません

Oracleでは、カーソル宣言のクエリはプロシージャ変数やパラメーターにアクセスできますが、Snowflake Scriptingではアクセスできません。これに代わる方法は、バインド変数を含む USING 句を使用することです。詳細は このセクション をご参照ください。

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

Oracleでは、開いているカーソルからの最初のフェッチの前に、cursor_name%NOTFOUND は、最後のフェッチが行を返せなかった場合は TRUE を返し、最後のフェッチが行を返した場合は FALSE を返します。Snowflake Scriptingはこの属性の使用をサポートしていません。代わりに、カーソル結果に割り当てられた変数に値が含まれているかどうかを検証することができます

関連 EWIs

  1. SSC-EWI-0036: データ型が別のデータ型に変換されました。

  2. SSC-EWI-OR0002: 式の列が見つかりません。

  3. SSC-EWI-OR0036: タイプ解決の問題で、文字列と日付の間で算術演算が正しく動作しない場合があります。

  4. SSC-PRF-0003: ループ内のフェッチは複雑なパターンとみなされるため、Snowflakeのパフォーマンスが低下する可能性があります。

  5. SSC-PRF-0004: このステートメントには、cursor for loopの使用があります。

CURSOR DECLARATION

注釈

関連性のないステートメント。

警告

このステートメントは 関連性のない構文であるため、 移行から削除されていることに注意してください。 Snowflakeでは必要ないということです。

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

このセクションでは、Oracleにおけるカーソル宣言の翻訳について説明します。詳細情報については、Oracleの プロシージャカーソル に関する以下のドキュメントを参照してください。

サンプルソースパターン

CURSOR DECLARATION

この例では、 CURSOR ステートメントが削除されていることに注意してください。これはSnowflakeをターゲットにした変換では関係のない構文です。

 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

既知の問題

問題は見つかりませんでした。

関連 EWIs

関連 EWIs はありません。

カーソル変数

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

カーソル変数は、1つのクエリに限定されない明示的なカーソルのようなものです。

(Oracle PL/SQL 言語リファレンスカーソル変数宣言)

参照カーソルタイプ定義

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

カーソル変数宣言

 cursor_variable type;
Copy

OPEN FOR ステートメント

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

警告

Snowflake Scriptingはカーソル変数や OPEN FOR ステートメントと直接等価ではありませんが、さまざまな回避策でエミュレートし、機能的に等価にすることができます。

サンプルソースパターン

1.VARCHAR 変数内の動的 SQL を含む OPEN FOR ステートメント

 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.文字列リテラル内の動的 SQL を含む OPEN FOR ステートメント

 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.SELECT ステートメントを含む OPEN FOR ステートメント

 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.REF CURSOR 型で宣言されたカーソル変数

 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.USING 句を含む OPEN FOR ステートメント

 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

既知の問題

問題は見つかりませんでした。

関連 EWIs

  1. SSC-EWI-0030: 以下のステートメントには、動的 SQL の使用があります。

  2. SSC-EWI-0058: この関数は現在Snowflake Scriptingではサポートされていません。

PARAMETRIZED CURSOR

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

Oracleは宣言されたカーソルのパラメーターをサポートします。しかし、Snowflake Scriptingはこの機能をサポートしていないため、カーソルの宣言や使用はできません。

コード例

入力コードOracle:
 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

推奨事項

  • カーソル内のクエリにバインディングを使用し、 USING 句でカーソルを開いてみてください。1つのカーソルで複数回使用されるパラメーターは、 USING 句で変数を複数回渡す必要があることに注意してください。

 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
  • バインディングを使用するカーソルを手動で変更します。

  • さらにサポートが必要な場合は、snowconvert-support@snowflake.comまでメールでお問い合わせください。

関連 EWIs

  1. SSC-PRF-0004: このステートメントには、cursor for loopの使用があります。

パラメーターまたはプロシージャ変数を使用するカーソルの回避策

説明

このセクションでは、カーソルのクエリ内でのカーソルパラメーターとプロシージャ変数の使用のシミュレーション方法について説明します。変数やパラメーターの名前は、 ? 記号を使ってバインディングに置き換えられます。そして、カーソルがオープンされた時、値は USING 句で渡されなければなりません。

注釈

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

Copy

ローカル変数を含むカーソル

使用される変数やプロシージャパラメーターのために、クエリのバインディングをカーソルで使用し、 USING 句でカーソルをオープンしてください。

 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

パラメーターを含むカーソル

使用されるパラメーターごとにクエリのバインディングをカーソルで使用し、 USING 句でカーソルを開きます。1つのカーソルで複数回使用されるパラメーターは、 USING 句で変数を複数回渡す必要があることに注意してください。

 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

関連 EWIs

  1. SSC-PRF-0004: このステートメントには、cursor for loopの使用があります

CREATE FUNCTION

説明

注釈

わかりやすくするため、出力コードの一部を省略しています。

ストアド関数ユーザー関数 または ユーザー定義関数 とも呼ばれます)は、名前で呼び出すことができる一連の PL/SQL ステートメントです。ストアド関数はプロシージャとよく似ていますが、関数は呼び出された環境に値を返すという点が異なります。ユーザー関数は、 SQL 式の一部として使用できます。

呼び出し仕様 は、Javaメソッドまたは第三世代言語(3GL)ルーチンを宣言し、 PL/SQL から呼び出せるようにします。このようなメソッドやルーチンを呼び出すには、 CALL SQL ステートメントを使用することもできます。呼び出し仕様は、呼び出しが行われたときにどのJavaメソッド、またはどの共有ライブラリ内のどの名前付き関数を呼び出すかをOracleデータベースに伝えます。また、引数と戻り値の型変換もデータベースに指示します。Oracle SQL 言語リファレンス関数の作成

Oracle構文

Oracleの関数作成の詳細情報については、 こちら をご覧ください。

 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構文

Snowflakeでは、ユーザー定義関数で3つの異なる言語を使用できます。

  • SQL

  • JavaScript

  • Java

今のところ、 SnowConvert は SQLJavaScript のみをターゲット言語としてサポートしています。

Snowflakeの関数作成の詳細情報については、 こちら をご覧ください。

注釈

SQL ユーザー定義関数は、本文として1つのクエリしかサポートしていません。データベースからの読み取りは可能ですが、書き込みや変更はできません(スカラー 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

注釈

JavaScript ユーザー定義関数は、本文中に複数のステートメントを記述することができますが、データベースへのクエリを実行することはできません。(スカラー 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

サンプルソースパターン

サンプル補助データ

注釈

このコードは例の理解を深めるために実行されました。

 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

既知の問題

問題は見つかりませんでした。

関連 EWIS

  1. SSC-FDM-OR0042: タイムスタンプに変換された日付タイプの動作が異なる

return変数のカーソル

注釈

わかりやすくするため、出力コードの一部を省略しています。

このパターンは、Oracle PL/SQL で、カーソルを使用して単一の値をフェッチし、それを返す関数を定義します。

コンポーネント:

  1. 関数宣言:

    • CREATE FUNCTION functionName(parameters) RETURN returnType

    • 入力パラメーターと戻り値の型で関数を宣言します。

  2. 変数の宣言:

    • return変数を含む変数を宣言します。

  3. カーソル宣言:

    • CURSOR cursorName IS SELECT singleColumn FROM ... WHERE ... [AND col1 = localVar1];

    • テーブルから1つの列を選択するためのカーソルを定義し、オプションのフィルター条件を指定します。

  4. BEGIN-END ブロック:

    • 変数の割り当て。

    • カーソルを開きます。

    • 結果をreturn変数に取得します。

    • カーソルを閉じます。

    • 取得した値を返します。

この場合、変数は共通テーブル式(CTE)に変換されます。カーソル内のクエリと同様に、 FETCH CURSOR の動作をシミュレートするために、 FETCH FIRST 1 ROW ONLY 句が追加されています。

RETURN ステートメントが最後の選択に変換されます。

クエリ

 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

既知の問題

問題は見つかりませんでした。

関連 EWIS

  1. SSC-FDM-OR0042: タイムスタンプに変換された日付タイプの動作が異なります。

  2. SSC-EWI-0073: 機能同等性レビュー保留中。

IF ステートメントを含むカーソル

注釈

わかりやすくするため、出力コードの一部を省略しています。

このパターンは、 IF ステートメントに基づいて、条件付きでカーソルを使用して値をフェッチして返す関数を定義します。

コンポーネント:

  1. 関数宣言:

    • CREATE FUNCTION functionName(parameters) RETURN returnType

    • 入力パラメーターと戻り値の型で関数を宣言します。

  2. カーソル宣言:

    • CURSOR cursorName IS SELECT singleColumn FROM ... WHERE ... [AND col1 = localVar1];

    • テーブルから1つの列を選択するためのカーソルを定義し、オプションのフィルター条件を指定します。

  3. 変数宣言:

    • return変数を含む変数を宣言します。

  4. IF ステートメントを含む BEGIN-END ブロック:

    • 変数の割り当て。

    • 条件がtrueかどうかをチェックします。

    • trueの場合、カーソルを開き、return変数に結果をフェッチし、カーソルを閉じ、フェッチされた値を返します。(カーソルは ELSE ブロックでも開くことができ、同じ条件を満たす必要があります)

    • ELSE ブロックはオプションです。存在する場合は、割り当てまたは RETURN ステートメントになる単一のステートメントのみを含める必要があります。

変数は共通テーブル式(CTE)に変換されます。カーソル内のクエリと同様に、 FETCH CURSOR の動作をシミュレートするために、 FETCH FIRST 1 ROW ONLY 句が追加されています。

IF/ELSE ステートメントは、クエリ内で条件式を使用できるように、select内でCASE EXPRESSIONを使用して処理できます。 RETURN ステートメントは、最終的なselectに変換されます。

クエリ

 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

既知の問題

問題は見つかりませんでした。

関連 EWIS

関連する EWIs なし。

複数の IFs ステートメント

このパターンは、ローカル変数に対する条件ステートメントを使用する関数を定義します。

コンポーネント:

  1. 関数宣言:

    • CREATE FUNCTION functionName(parameters) RETURN returnType

    • 入力パラメーターと戻り値の型で関数を宣言します。

  2. 変数宣言:

    • return変数を含む変数を宣言します。

  3. IF ステートメントを含む BEGIN-END ブロック:

    • 条件がtrueかどうかをチェックします。

    • 各ケースは、同じ変数に値を割り当てるために使用されます。

変換:

DECLARE SECTION: デフォルトの式を持つ変数は、共通テーブル式に移動します。

IF/ELSE ステートメントは、クエリ内で条件式を使用できるように、select内でCASE EXPRESSIONを使用して処理できます。

RETURN ステートメントが最後の選択に変換されます。

 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

既知の問題

問題は見つかりませんでした。

関連 EWIS

  1. SSC-FDM-OR0042: タイムスタンプに変換された日付タイプの動作が異なります。

  2. SSC-EWI-0073: 機能同等性レビュー保留中。

  3. SSC-EWI-OR0036: タイプ解決の問題で、文字列と日付の間で算術演算が正しく動作しない場合があります。

DML STATEMENTS

説明

DML ステートメントの拡張は、コレクションや記録などの PL/SQL 要素を使用できるため、通常の DML ステートメントとは異なります。今のところ、これらの要素のいくつかはSnowflake Scriptingではサポートされていません。1つのステートメントがサポートされていない場合、翻訳中に EWI が追加されます。その他の DML ステートメントは、プロシージャ内にないものとして翻訳されます。

以下は、 DML ステートメントとみなされます。

SELECT、 INSERT ステートメントに対して、 RECORDS、 COLLECTIONS の動作をシミュレートする方法を説明するセクションがあります。

collections-and-records

INSERT ステートメント拡張

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

SQL INSERT ステートメントの PL/SQL 拡張を使用すると、 single_table_insertvalues_clause で、 insert_into_clause で列リストを指定する代わりに、記録名を指定できます。(Oracle PL/SQL 言語リファレンス INSERT ステートメント拡張)

Snowflake INSERT INTO はSnowflake Scriptingと異なり、変数の制約があります。変数の値をバインドするためには、名前の前にコロン「:」を付ける必要があります。

推奨事項

注釈

このコードは例の理解を深めるために実行されました。

 CREATE TABLE numbers_table(num integer, word varchar2(20));
Copy
 CREATE OR REPLACE TABLE PUBLIC.numbers_table (num integer,
word VARCHAR(20));
Copy

INSERT ステートメント拡張の単純なケース

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スクリプト
 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

既知の問題

1.記録はSnowflake Scriptingではサポートされていません

記録はSnowflake Scriptingでサポートされていないため、 VALUES record 句を使用する代わりに、 SELECT 句に変更し、記録の列を分割する必要があります。詳細は 記録タイプ定義セクションを参照してください。

関連 EWIs

関連 EWIs はありません。

MERGE ステートメント

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

MERGE ステートメントは、1つ以上のソースから行を選択し、テーブルまたはビューに更新または挿入するために使用されます。ターゲットテーブルやビューに対して、更新や挿入を行うかどうかの条件を指定することができます。このステートメントは、複数の操作を組み合わせる便利な方法です。これにより、複数の INSERTUPDATE、および DELETE DML ステートメントを回避できます。 MERGE は決定論的なステートメントです。同じ MERGE ステートメントでターゲットテーブルの同じ行を複数回更新することはできません。(Oracle PL/SQL 言語リファレンス MERGE ステートメント))

 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

サンプルソースパターン

サンプル補助データ

注釈

このコードは例の理解を深めるために実行されました。

 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

MERGE ステートメントの単純なケース

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

DELETE およびwhere句を含む MERGE ステートメント

DELETE ステートメントと where句 の等価性を見つけるためには、Snowflakeのmergeステートメントの順序を変更し、いくつかの変更を実装する必要があります。

変更が必要です。
  • Oracleの DELETE where_clause を、 AND 述語 ステートメントを含む新しいSnowflakeの matchedClause に置き換えます。

  • Oracleの merge\insert\clausewhere\clause を、Snowflakeの notMatchedClauseAND 述語 ステートメントに置き換えます

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

警告

場合によっては、次の例のように、適用された変更が期待通りに機能しないことがあります。

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

既知の問題

1.Oracleのerror_logging_clauseはサポートされていません

Snowflake Scriptingのエラーログ句に相当するものはありません。

2.適用した変更が期待どおりに機能しません

OracleのmergeステートメントとSnowflakeのmergeステートメントの機能的等価性を達成するために適用された変更が、期待通りに機能しないことがあります。

関連 EWIs

  1. SSC-FDM-0006: Snowflakeで数値タイプ列が同様に動作しない場合があります。

  2. SSC-FDM-OR0018: mergeステートメントが期待通りに機能しないことがあります

SELECT INTO ステートメント

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

SELECT INTO ステートメントは、(SQL SELECT ステートメントと同様に)1つ以上のデータベーステーブルから値を取得し、(SQL SELECT ステートメントでは行わない)変数に格納します。(Oracle PL/SQL 言語リファレンス SELECT INTO ステートメント)

 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

サンプルソースパターン

サンプル補助データ

注釈

このコードは例の理解を深めるために実行されました。

 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

SELECT INTO ステートメントの単純なケース

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スクリプト
 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

既知の問題

1.BULK COLLECT INTO はサポートされていません

Snowflake Scriptingは BULK COLLECT INTO 句をサポートしていません。ただし、 ARRAY_AGG を使用して新しい変数を作成することは可能です。詳細情報については、 コレクション一括操作セクションを参照してください。

2.コレクションと記録はサポートされていません

Snowflake Scriptingはコレクションや記録の使用をサポートしていません。このセクションで説明されているように、半構造化データ型を使って移行することが可能です。

関連 EWIs

関連 EWIs はありません。

記録の使用をシミュレートする回避策

警告

このページは非推奨ですが、互換性のために残されています。更新されたセクションをご覧になりたい方は、 コレクションと記録をご参照ください

説明

ここでは、Snowflake Scriptingの RESULTSET と CURSORS を使用して、 SELECT と INSERT ステートメントでOracleの記録の動作をシミュレートする方法を説明します。

Snowflake Scripting RESULTSET および CURSOR

 <resultset_name> RESULTSET [ DEFAULT ( <query> ) ] ;

LET <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;

LET <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
Copy

推奨事項

注釈

以下の例では、このコードは例の理解を深めるために実行されました。

 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 とカーソルを使用する

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

既知の問題

1.RESULTSET の使用制限

RESULTSET の使用は非常に限られています。table(result_scan(last_query_id())) ステートメントの場合、 RESULTSET のクエリが実行された直後に使用する必要があります。詳細情報はこちらの リンク をご覧ください。

関連 EWIs

  1. SSC-EWI-0036: データ型が別のデータ型に変換されました。

  2. SSC-EWI-0056: 作成タイプがサポートされていません。

PACKAGES

説明

CREATE PACKAGE ステートメントを使用して、ストアドパッケージの仕様を作成します。ストアドパッケージとは、関連するプロシージャ、関数、その他のプログラムオブジェクトをカプセル化してデータベースに格納したものです。パッケージ仕様では、これらのオブジェクトを宣言しています。続いて指定されるパッケージ本文がこれらのオブジェクトを定義します。(Oracle PL/SQL 言語リファレンス CREATE PACKAGE ステートメント)

SnowflakeにはOracleのパッケージに相当するものがないため、構造を維持するためにパッケージをスキーマに変換し、すべての要素をスキーマ内で定義します。また、パッケージとその要素は、元のスキーマ名を保持するように名前が変更されます。パッケージ名の変更に関する詳しい情報は、 パッケージ翻訳オプションのセクションを参照してください。

BODY

説明

PACKAGE BODY のヘッダーが削除され、各プロシージャや関数定義がスタンドアロンの関数やプロシージャに変換されます。

CREATE [ OR REPLACE ]
[ EDITIONABLE | NONEDITIONABLE ]
PACKAGE BODY plsql_package_body_source

Copy

サンプルソースパターン

注釈

以下のクエリは、 PackagesAsSchema オプションを無効にして変換されました。

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

既知の問題

問題は見つかりませんでした。

関連 EWIs

  1. SSC-FDM-OR0035: DBMS_OUTPUT.PUTLINE UDF の実装を確認してください。

定数

説明

PACKAGE CONSTANTS は、パッケージ宣言か PACKAGE BODY のどちらかで宣言できます。プロシージャでパッケージ定数を使用すると、定数と同じ名前と値を持つ新しい変数が宣言されるため、結果のコードは入力とほぼ同じになります。

constant CONSTANT datatype [NOT NULL] { := | DEFAULT } expression ;

Copy

サンプルソースパターン

補助コードのサンプル

 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

注釈

なお、 PROCEDURE の定義はSnowflakeでは必要ないため、削除されます。

既知の問題

問題は見つかりませんでした。

関連 EWIs

  1. SSC-FDM-0006: Snowflakeで数値タイプ列が同様に動作しない場合があります。

DECLARATION

説明

宣言はスキーマに変換されるので、各内部要素はこのスキーマの中で宣言されます。パッケージ内に存在するすべての要素は、適切な変換を持つ VARIABLES を除いてコメントされています。

CREATE [ OR REPLACE ]
[ EDITIONABLE | NONEDITIONABLE ]
PACKAGE plsql_package_source

Copy

サンプルソースパターン

注釈

以下のクエリは、 PackagesAsSchema オプションを無効にして変換されました。

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

注釈

なお、 FUNCTIONPROCEDURE の定義はSnowflakeでは必要ないため、削除されます。

既知の問題

問題は見つかりませんでした。

関連 EWIs

関連 EWIs はありません。

VARIABLES

説明

PACKAGE VARIABLES は、パッケージ宣言か PACKAGE BODY のどちらかで宣言できます。その動作により、これらの変数は Snowflakeセッション変数 に変換されるため、各使用または割り当てはSnowflakeの等価なものに翻訳されます。

 variable datatype [ [ NOT NULL] {:= | DEFAULT} expression ] ;
Copy

サンプルソースパターン

補助コードのサンプル

 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
    package_variable NUMBER:= 100;
END PKG1;
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);
Copy

変数の使用

パッケージ変数の使用は、セッション変数の現在値にアクセスするSnowflake GETVARIABLE 関数に変換されます。これらの変数が使用される操作において機能的等価性を維持するために、元の変数のデータ型に明示的なキャストが追加されます。

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

注釈

パッケージ内の PROCEDURE 定義は、Snowflakeでは必要ないため削除されることに注意してください。

変数レギュラー割り当て

:= 演算子を使ってパッケージ変数が割り当てられると、その割り当ては UPDATE_PACKAGE_VARIABLE_STATE という、Snowflake SETVARIABLE 関数を抽象化した SnowConvert UDF に置き換えられます。

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

注釈

パッケージ内の PROCEDURE 定義は、Snowflakeでは必要ないため削除されることに注意してください。

出力引数としての変数割り当て

パッケージ変数が出力引数として使用される場合、プロシージャ内部で新しい変数が宣言され、この変数がプロシージャの出力引数の値をキャッチし、前述の UPDATE_PACKAGE_VARIABLE_STATE を使用してパッケージ変数を参照するセッション変数を更新するためにこの変数が使用されます。詳細情報については、 出力パラメーターの変換をご覧ください。

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

注釈

パッケージ内の PROCEDURE 定義は、Snowflakeでは必要ないため削除されることに注意してください。

既知の問題

問題は見つかりませんでした。

関連 EWIs

  1. SSC-FDM-0006: Snowflakeで数値タイプ列が同様に動作しない場合があります。

COLLECTIONS AND RECORDS

警告

このセクションは進行中であり、情報は将来変更される可能性があります。

概要

PL/SQL では、コレクションと記録の2種類の複合データ型を定義できます。複合とは、内部コンポーネントを持つ値を格納するデータ型のことです。

コレクションでは、内部コンポーネントは常に同じデータ型を持ち、要素と呼ばれます。

記録では、内部コンポーネントは異なるデータ型を持つことができ、フィールドと呼ばれます。(Oracle PL/SQL 言語リファレンス COLLECTIONS AND RECORDS)

注釈

いくつかの回避策は重複する可能性があり、両方のシナリオで機能する可能性があるため、 CREATE TYPE ステートメント翻訳リファレンスを考慮してください。

制限事項

Snowflakeは、オンラインドキュメント サポートされていないデータ型 によると、 PL コレクションと記録を含むユーザー定義データ型をサポートしていませんが、 半構造化データ型 をサポートしており、これは記録の階層のような構造とコレクションユーザー定義型の要素構造の両方を模倣するために使用することができます。このため、回避策がない機能のタイプが複数あります。

以下は、 NO 回避策が提案されている機能です。

変数のサイズは 16MB を超えることはできません

Snowflakeは VARIANT、 OBJECT、 ARRAY の最大サイズを 16MBs にセットします。つまり、記録、コレクション、またはいずれかの要素がこのサイズを超えると、ランタイムエラーが発生します。

Varrayの容量を制限することはできません

OracleのVarraysは、その中の要素数を制限することができます。これはSnowflakeではサポートされていません。

提案されている回避策

記録タイプの定義について

提案されている回避策は、Oracleのデータ型を模倣するために「OBJECT」半構造化データ型を使用することです。

コレクションタイプの定義について

移行するコレクションのタイプによって、2つの異なる回避策があります。

  • 連想配列は、「OBJECT」半構造化データ型に変更されることが提案されています。

  • Varraysとネストされたテーブル配列は、「ARRAY」半構造化データ型に変更されることが提案されています。

現在の SnowConvert サポート

次のテーブルは、 SnowConvert ツールが現在提供しているサポートの概要です。翻訳はまだ最終的なものではない可能性があり、さらに作業が必要な場合があることをご考慮ください。

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.

既知の問題

1.連想配列はネストされたテーブルとみなされます

今のところ、 SnowConvert は連想配列とネストされたテーブルを区別していません。つまり、これらは同じ評価数で混在しています。

関連 EWIs

関連 EWIs はありません。

連想配列型の定義

警告

このセクションは進行中であり、情報は将来変更される可能性があります。

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

連想配列(以前は PL/SQL テーブルまたはインデックスバイテーブルと呼ばれていました)はキー値のペアのセットです。各キーは一意なインデックスで、構文 variable_name(index) で関連する値を探すのに使われます。

インデックス のデータ型は、文字列型(VARCHAR2VARCHARSTRING、または LONG)または PLS_INTEGER のいずれかです。インデックスは作成順ではなく、ソート順で格納されます。文字列型の場合、ソート順は初期化パラメーター NLS_SORTNLS_COMP によって決定されます。

(Oracle PL/SQL 言語リファレンス ASSOCIATIVE ARRAYS)

警告

PL/SQL NESTED TABLE 型定義と混同しないでください。

翻訳のために、型定義は OBJECT 半構造化データ型 に置き換えられ、その使用はあらゆる操作にわたって適宜変更されます。

連想配列型を定義するための構文は以下の通りです。

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

indexing_datatype := { PLS_INTEGER
                     | BINARY_INTEGER
                     | string_datatype
                     }

Copy

この型の変数を宣言するには

variable_name collection_type;

Copy

サンプルソースパターン

Varcharインデックス付き連想配列

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

CALL associative_array();
Copy
DBMS OUTPUT
-----------
1
3
4
2
3

Copy
Snowflake

OBJECT_INSERT の「true」パラメーターに注意してください。これは、その要素がすでに配列内に存在する場合に、その要素が更新されるようにするためです。

 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

数値インデックス付き連想配列

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

数値は、操作が必要とするときに適宜varcharに変換されることに注意してください。さらに、 OBJECT_INSERT の「true」パラメーターに注意してください。これは、その要素がすでに配列内に存在する場合に、その要素が更新されるようにするためです。

 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

記録要素数値インデックス付き連想配列

この場合、連想配列は記録構造で構成されており、この構造を保持する必要があります。そのために、挿入に関する操作がさらに追加されました。

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

このシナリオでは、挿入/更新は、連想配列内の記録の自動作成を想定しており、新しい記録を作成するときにこれを考慮する必要があります。

 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

既知の問題

1.現在は認識されていません

SnowConvert はこれらのコレクションをネストされたテーブル配列として扱います。これを修正する作業項目があります。

関連 EWIs

関連 EWIs はありません。

コレクションメソッド

警告

このセクションは進行中であり、情報は将来変更される可能性があります

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

コレクションメソッドは、 PL/SQL サブプログラムで、コレクションに関する情報を返す関数、またはコレクションを操作するプロシージャです。コレクションメソッドは、コレクションを使いやすくし、アプリケーションを保守しやすくします。

(Oracle PL/SQL 言語リファレンス COLLECTION METHODS)

これらのメソッドの一部は、ネイティブのSnowflake半構造化操作にマッピングできます。できないもの、あるいは違いがあるものは、 UDF の実装にマッピングされます。

現在の SnowConvert サポート

次のテーブルは、 SnowConvert ツールが現在提供しているサポートの概要です。翻訳はまだ最終的なものではない可能性があり、さらに作業が必要な場合があることをご考慮ください。

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)

サンプルソースパターン

COUNT

このメソッドは、コレクション内の「未定義ではない」(nullと混同しないでください)要素の数を返します(ネストされたテーブルは、これらの要素が間に残ったまままばらになることがあります)。連想配列では、配列内のキーの数を返します。

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

Snowflakeの同等のものは、 ARRAY_SIZE メソッドです。

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

CALL PUBLIC.collection_count();
SELECT * FROM DBMS_OUTPUT.DBMS_OUTPUT_LOG;
Copy
DBMS OUTPUT
-----------
2
3
4

Copy

EXISTS

このメソッドは、指定された要素がコレクション内に含まれる場合にtrueを返します。連想配列では、キーが含まれているかどうかを調べます。

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

Snowflakeの同等のものは、 ARRAY_CONTAINS メソッドです。Varchar要素を使用する場合は、バリアントへのキャストが必要であることに注意してください。

 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

この2つのメソッドは、それぞれコレクションの最初と最後の要素を返します。コレクションが空の場合はnullを返します。この操作は UDF にマッピングされており、今後の改訂で追加される予定です。

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

このメソッドは、コレクションから要素を削除するために使用します。バリアントは3種類あります。

  • .DELETE はすべての要素を削除します。

  • .DELETE(n)はインデックスが「n」にマッチする要素を削除します。

  • .DELETE(n, m)は、「n」から「m」までのインデックスを削除します。

注釈

Oracleでは、ネストされたテーブルに対してこの操作を使用すると、テーブル内の要素がまばらであるために「未定義」になります。

警告

第2、第3バージョンはVarraysには適用されませんのでご注意ください。

Oracle

簡潔にするため、このサンプルでは要素数のみをチェックしていますが、各コレクションの内容を表示するように変更することもできます。

 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は既存の ARRAY からの削除をサポートしていません。このため、唯一の回避策は、 DELETE の元のパラメーターに応じて新しい ARRAY を再構築することです。

注釈

要素の更新のための機能を実装するために UDF が追加されたことに注意してください。

この UDF は、後の改訂で追加される予定です。

 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

このメソッドは、ネストされたテーブルまたはVarrayに新しい要素を追加するために使用します。バリアントは3種類あります。

  • .EXTEND はnull要素を挿入します。

  • .EXTEND(n)は「n」個のnull要素を挿入します。

  • .EXTEND(n, i)は、「i」に要素のコピーを「n」個挿入します。

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

注釈

要素の更新のための機能を実装するために UDF が追加されたことに注意してください。

この UDF は、後の改訂で追加される予定です。

 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

このメソッドは、ネストされたテーブルやVarrayから最後の要素を削除するために使用します。バリアントには2種類あります。

  • .TRIM は最後の要素を削除します。

  • .TRIM(n)は最後の「n」個の要素を削除します。

注釈

この機能は、 ARRAY_SLICE を使用して実装できます。

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

CALL collection_trim();
Copy
DBMS OUTPUT
-----------
2
2

Copy

LIMIT

このメソッドはVarrayの上限を返します。

このメソッドはSnowflakeではサポートされていません。

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

CALL collection_limit();
Copy
DBMS OUTPUT
-----------
5
6

Copy

PRIOR/NEXT

このメソッドは、インデックスを指定すると、その前後のインデックスを返します。先行/後続がない場合はnullを返します。コレクションをたどるときによく使われます。

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メソッドはSnowflakeではサポートされていません

Snowflakeは、スペースが制限されたvarrayをサポートしていません。そのため、このメソッドはサポートされていません。

Related EWIs

関連する EWIs なし。

ネストされたテーブル配列型定義

警告

このセクションは進行中であり、情報は将来変更される可能性があります。

注釈

このセクションは PL/SQL バージョンのネストされたテーブル配列のためのものです。スタンドアロンバージョンについては ネストされたテーブル型定義を参照してください。

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

データベースでは、ネストされたテーブルは、不特定多数の行を順不同に格納する列型です。

データベースから PL/SQL ネストされたテーブル変数にネストされたテーブル値を取り出すと、 PL/SQL は1から始まる連続したインデックスを行に与えます。これらのインデックスを使用すると、ネストされたテーブル変数の個々の行にアクセスできます。構文は variable_name(index) です。データベースからネストされたテーブルを格納したり取得したりする際に、ネストされたテーブルのインデックスや行の順序が安定しない可能性があります。

(Oracle PL/SQL 言語リファレンス NESTED TABLES)

翻訳のために、型定義は ARRAY 半構造化データ型 に置き換えられ、その使用はあらゆる操作にわたって適宜変更されます。ネストされたテーブルとVarraysの翻訳が同じであることに注意してください。

ネストされたテーブル配列型を定義するための構文は以下の通りです。

type_definition := TYPE IS TABLE OF datatype;

Copy

この型の変数を宣言するには

variable_name collection_type;

Copy

サンプルソースパターン

ネストされたテーブル配列の定義

これは、異なるネストされたテーブル配列を作成する方法と、変数の定義を移行する方法を示しています。

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

ネストされたテーブルの繰り返し

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

注釈

要素の更新のための機能を実装するために UDF が追加されたことに注意してください。

この UDF は、後の改訂で追加される予定です。

 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

既知の問題

1.現在、変換されていません

SnowConvert はこれらの要素の翻訳をサポートしていません。

2.インデックスの修正が必要です

Oracleのインデックスは1から始まりますが、Snowflakeでは0から始まります。

関連 EWIs

関連する EWIs なし。

記録型定義

警告

このセクションは進行中であり、情報は将来変更される可能性があります。

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

記録変数は、フィールドと呼ばれる内部コンポーネントが異なるデータ型を持つことができる複合変数です。記録変数の値とそのフィールドの値は変更可能です。

記録変数全体をその名前で参照します。record.field という構文で記録フィールドを参照します。

記録変数はこれらの方法で作成できます。

  • 記録型を定義し、その型の変数を宣言します。

  • %ROWTYPE を使用して、データベーステーブルまたはビューの完全行または部分行を表す記録変数を宣言します。

  • %TYPE を使用して、以前に宣言された記録変数と同じ型の記録変数を宣言します。

(Oracle PL/SQL 言語リファレンス RECORD VARIABLES)

翻訳のために、型定義は OBJECT 半構造化データ型 に置き換えられ、その使用はあらゆる操作にわたって適宜変更されます。

記録型を定義するための構文は以下の通りです。

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

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

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

Copy

この型の変数を宣言するには

variable_name { record_type
              | rowtype_attribute
              | record_variable%TYPE
              };

Copy

サンプルソースパターン

注釈

わかりやすくするため、出力コードの一部を省略しています。

記録の初期化と割り当て

このサンプルは、プロシージャの途中で再割り当てされる記録変数を使用して、2つの新しい行を挿入しようとしています。

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

再割り当てが、列が既に存在する場合に更新する OBJECT_INSERT で置き換えられ、 VALUES 句が SELECT で置き換えられていることに注意してください。

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

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

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

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

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

    END;
$$;

CALL record_procedure();

SELECT * FROM
    record_table;
Copy
COL1|COL2|
----+----+
 1.5|   1|
 2.5|   2|

Copy

%ROWTYPE Record and Values Record

操作は構造を定義するものであるため、これらの定義は OBJECT データ型に置き換えることができますが、記録を「そのまま」挿入することはサポートされていないため、記録の値を分解する必要があります。

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

最後に、情報を追加するために変数 OBJECT を初期化する必要があることに注意してください。

 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

記録へのデータ取得

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

カーソル定義に OBJECT_CONSTRUCT が追加されていることに注意してください。これは OBJECT を抽出するためのもので、これを使用して FETCH ステートメントをシームレスに移行できます。

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

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

CREATE OR REPLACE PROCEDURE load_cursor_record ()
RETURNS VARCHAR
LANGUAGE SQL
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'
EXECUTE AS CALLER
AS
$$
    DECLARE
        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

SELECT INTO への記録変数の割り当て

この変換は、 SELECT 列を引数として記録を初期化する OBJECT୧_CONTRUCT 関数を利用することで行われます。

補助コードのサンプル

 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

既知の問題

1.以下の機能は現在変換されていません。

  • 記録へのデータ取得。

  • ネストされた記録(記録の中の記録)。

  • 記録内のコレクション。

関連 EWIs

  1. SSC-EWI-0036: データ型が別のデータ型に変換されました。

  2. SSC-EWI-0056: 作成タイプがサポートされていません

  3. SSC-FDM-0006: Snowflakeで数値タイプ列が同様に動作しない場合があります。

  4. SSC-FDM-OR0042: タイムスタンプに変換された日付タイプの動作が異なります。

  5. SSC-FDM-OR0035: DBMS_OUTPUT.PUTLINE UDF の実装を確認してください。

  6. SSC-PRF-0003: ループ内のフェッチは複雑なパターンとみなされるため、Snowflakeのパフォーマンスが低下する可能性があります。

配列型定義

警告

このセクションは進行中であり、情報は将来変更される可能性があります。

注釈

このセクションは PL/SQL バージョンのVarrays用です。スタンドアロンバージョンについては 配列型定義を参照してください。

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

varray(可変サイズ配列)は、要素数が0(空)から宣言された最大サイズまで変化する配列です。

varray変数の要素にアクセスするには、 variable_name(index) という構文を使います。インデックス の下限は1で、上限は現在の要素数です。要素の追加や削除によって上限は変わりますが、最大サイズを超えることはありません。データベースからvarrayを格納したり取り出したりするとき、そのインデックスと要素の順序は安定したままです。

(Oracle PL/SQL 言語リファレンス VARRAYS)

翻訳のために、型定義は ARRAY 半構造化データ型 に置き換えられ、その使用はあらゆる操作にわたって適宜変更されます。ネストされたテーブルとVarraysの翻訳が同じであることに注意してください。

varray型を定義するための構文は以下の通りです。

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

Copy

この型の変数を宣言するには

variable_name collection_type;

Copy

サンプルソースパターン

Varray定義

これは、3つの異なる方法でvarrayを作成する方法と、これらの変数の定義を移行する方法を示しています。

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の反復

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

注釈

要素の更新のための機能を実装するために UDF が追加されたことに注意してください。

この UDF は、後の改訂で追加される予定です。

 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

既知の問題

1.現在、変換されていません

SnowConvert はこれらの要素の翻訳をサポートしていません。

2.インデックスの修正が必要です

Oracleのインデックスは1から始まりますが、Snowflakeでは0から始まります。

3.配列密度はオリジナルと一致しない場合があります

ARRAY データ型はまばらになる可能性があるため、配列の追加や削除を行う際には注意が必要です。密度が気になる場合は、このような操作の後に ARRAY_୧COMPACT()を使用すると便利です。

関連 EWIs

  1. SSC-EWI-0058: この関数は現在Snowflake Scriptingではサポートされていません。

  2. SSC-EWI-0062: カスタムタイプの使用がバリアントに変更されました。

  3. SSC-EWI-0073: 機能同等性レビュー保留中。

  4. SSC-EWI-OR0108: 次の割り当てステートメントはSnowflake Scriptingでサポートされていません。

  5. SSC-FDM-OR0035: DBMS_OUTPUT.PUTLINE UDF の実装を確認してください。

コレクション一括操作

警告

このセクションは進行中であり、情報は将来変更される可能性があります

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

一括 SQL の機能である BULK COLLECT 句は、 SQL から PL/SQL までの結果を、一度に1つではなくバッチで返します。

BULK COLLECT 句は、次の場合に出現します。

  • SELECT INTO ステートメント

  • FETCH ステートメント

  • 次の RETURNING INTO 句:

    • DELETE ステートメント

    • INSERT ステートメント

    • UPDATE ステートメント

    • EXECUTE IMMEDIATE ステートメント

BULK COLLECT 句を使用すると、前述の各ステートメントは、1回の操作で結果セット全体を取得し、1つまたは複数のコレクション変数に格納します(これは、ループステートメントを使用して一度に1つの結果行を取得するよりも効率的です)。

(Oracle PL/SQL 言語リファレンス BULK COLLECT CLAUSE)

このセクションでは、Bulk句を使用した SELECTs および FETCH カーソルの回避策をいくつか示します。

サンプルソースパターン

ソーステーブル

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

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

Bulk Collect句を使用した EXECUTE IMMEDIATE には回避策がありません。

注釈

なお、 FETCH カーソルはほぼそのまま使用できますが、パフォーマンスの問題から、可能な限り SELECT ステートメントに変更することをお勧めします。

 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 ステートメントケース

この場合、翻訳仕様は RESULTSETs を使用します。WITH、 SELECT、 BULK COLLECT INTO ステートメントのドキュメントはこちらをご覧ください。

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

既知の問題

1.FETCH カーソルの回避策における重いパフォーマンスの問題

Fetchカーソルの回避策は、仮テーブルのために重いパフォーマンスが要求されます。SELECT ステートメントに手動で移行することをお勧めします

2.Execute immediateステートメントは変換されません

これらは SnowConvert ではサポートされていませんが、手動で SELECT ステートメントに変更することができます。

関連 EWIs

  1. SSC-EWI-0058: この関数は現在Snowflake Scriptingではサポートされていません。

  2. SSC-EWI-0062: カスタムタイプの使用がバリアントに変更されました。

  3. SSC-EWI-0073: 機能同等性レビュー保留中

  4. SSC-EWI-OR0036: タイプ解決の問題で、文字列と日付の間で算術演算が正しく動作しない場合があります。

  5. SSC-EWI-OR0108: 次の割り当てステートメントはSnowflake Scriptingでサポートされていません。

  6. SSC-FDM-OR0035: DBMS_OUTPUT.PUTLINE UDF の実装を確認してください。

  7. SSC-PRF-0001: このステートメントには、カーソルフェッチの一括操作の使用があります。

  8. SSC-EWI-0030: 以下のステートメントには動的 SQL の使用法があります

WITH、 SELECT、および BULK COLLECT INTO ステートメント

このセクションは翻訳仕様です。情報は将来変更される可能性があります。

注釈

わかりやすくするため、出力コードの一部を省略しています。

説明

このセクションは、 BULK COLLECT INTO ステートメントを使用する SELECT ステートメントに続く WITH ステートメントの翻訳仕様です。詳細情報については、以下のドキュメントをご覧ください。

サンプルソースパターン

注釈

わかりやすくするため、出力コードの一部を省略しています。

以下の例では、以下のクエリを使用しています。

 -- 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.プロシージャ内部の単純なケース

これは結果セットデータ型を使用するアプローチです。ユーザー定義型の見直しが必要です。RESULTSETs の詳細情報については、以下の Snowflakeドキュメント を参照してください。

以下の例ではユーザー定義型を使用し、テーブルとして間接的に宣言しています。この場合の翻訳では、Snowflakeのデータ型として RESULTSET を実装します。結果セットは変数に格納され、 TABLE() 関数でラップして返す必要があります。

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

注釈

クエリは結果を返しませんが、予想される収集情報は、例で使用した IT 給与情報です。

IT_Salary

75000

80000

RESULTSETs の制限の一つは、テーブルとして使えないことです。例: select * from my_result_set; (これはエラーです。詳細は以下の ドキュメント をご参照ください)。

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.反復の単純なケース: FOR LOOP ステートメント

次のケースは、 FOR...LOOP との反復のための翻訳を定義することです。この場合、ユーザー定義型は暗黙のうちにテーブルであり、カーソルを使用して反復することが可能です。詳しくは以下のドキュメントをご覧ください。

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

IT 部門の平均給与: 77500

Known Issues

1.結果セットの制限。

RESULTSET データ型の使用には制限があります。詳しくは、以下の Snowflakeドキュメント をご覧ください。マーク可能な制限は以下の通りです。

  • 型 RESULTSET の列を宣言する。

  • 型 RESULTSET のパラメーターを宣言する。

  • ストアドプロシージャの戻り型を RESULTSET として宣言する。

2.Bulk Collect句を含む実行ステートメントはサポートされていません。

以下の ドキュメントを確認してください。

Related EWIs

  1. SSC-EWI-0058: この関数は現在Snowflake Scriptingではサポートされていません。

  2. SSC-EWI-0062: カスタムタイプの使用がバリアントに変更されました。

  3. SSC-EWI-0073: 機能同等性レビュー保留中

  4. SSC-EWI-OR0036: タイプ解決の問題で、文字列と日付の間で算術演算が正しく動作しない場合があります。

  5. SSC-EWI-OR0072: プロシージャメンバーはサポートされていません

  6. SSC-EWI-OR0104: 使用できないコレクション変数です。

  7. SSC-FDM-0006: Snowflakeで数値タイプ列が同様に動作しない場合があります。

  8. SSC-FDM-OR0035: DBMS_OUTPUT.PUTLINE UDF の実装を確認してください。

HELPERS

一括カーソルヘルパー

注釈

デフォルトの FORALL の変換 もご覧ください。

カーソルは、カーソルの状態に関するさまざまな情報を持つ OBJECT でシミュレートされます。カーソルのクエリの結果セットを格納する仮テーブルが作成されます。

これらのプロシージャのほとんどは、カーソルの状態を更新した新しいオブジェクトを返します。

INIT_CURSOR

この関数は、基本的なカーソル情報を持つ新しいオブジェクトを初期化します

 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

これらのプロシージャは、カーソルのクエリで仮テーブルを作成します。バインディングをサポートするオプションのオーバーロードがあります。

 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

このプロシージャは、カーソルの結果セットを格納していた仮テーブルを削除し、カーソルのプロパティを初期状態にリセットします。

 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 ヘルパー

Oracleは様々な種類のシナリオに対して FETCH ステートメントを実行することができるため、それぞれのケースを処理するためにオーバーロードを持つ複数のプロシージャが作成されました。これらのヘルパーは、取得した値を CURSOR オブジェクトの RESULT プロパティに保存します。

オーバーロードの中には、 LIMIT 句を使用した場合と使用しなかった場合のバリエーションがあります。他のオーバーロードは、 FETCH ステートメントが、クエリの列名と異なる列名の記録を持つ、または含む変数に対して実行される場合に必要な、 COLUMN_NAMES 引数を持ちます。

FETCH_BULK_COLLECTION_RECORDS

これらのプロシージャは、 FETCH BULK が記録のコレクションに行われる場合に使用されます。

 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

これらのプロシージャは、 FETCH ステートメントが1つまたは複数のコレクションに行われる場合に使用されます。列はこの FETCH 操作で指定されるので、特定の COLUMN_NAMES に対するオーバーライドは必要ありません。

 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

これらのプロシージャは、 FETCH BULK がコレクションの記録に行われる場合に使用されます。

 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