SnowConvert AI - Oracle - DML STATEMENTS

説明

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

INSERT ステートメント拡張

Oracle INSERT ステートメント拡張をSnowflakeスクリプトに変換するための翻訳リファレンス

注釈

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

説明

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

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

推奨事項

注釈

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

Oracle

CREATE TABLE numbers_table(num integer, word varchar2(20));
Copy
Snowflake
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

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

既知の問題

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

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

MERGE ステートメント

Oracle MERGE ステートメントをSnowflakeスクリプトに変換するための翻訳リファレンス

注釈

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

説明

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

Oracle 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
Snowflakeスクリプト MERGE 構文
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

サンプルソースパターン

サンプル補助データ

注釈

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

Oracle
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
Snowflake
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

アリス

Jones

Mrs.

3

Jane

Doe

Miss

4

Dave

Brown

Mr

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

アリス

Jones

Mrs.

3

Jane

Doe

Miss

4

Dave

Brown

Mr

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

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

警告

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

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

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

アリス

Jones

Mrs.

4

Dave

Brown

Mr

既知の問題

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

Oracle SELECT INTO ステートメントをSnowflakeスクリプトに変換するための翻訳リファレンス

注釈

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

説明

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

Oracle SELECT INTO 構文

SELECT [ { DISTINCT | UNIQUE } | ALL ] select_list
    { into_clause | bulk_collect_into_clause } FROM rest-of-statement ;
Copy
Oracle Into句構文
INTO { variable [, variable ]... | record )
Copy
Oracle Bulk Collect構文
BULK COLLECT INTO { collection | :host_array }
  [, { collection | :host_array } ]...
Copy
Snowflakeスクリプト SELECT INTO 構文
SELECT [ { ALL | DISTINCT } ]
    {
          [{<object_name>|<alias>}.]*
        | [{<object_name>|<alias>}.]<col_name>
        | [{<object_name>|<alias>}.]$<col_position>
        | <expr>
        [ [ AS ] <col_alias> ]
    }
    [ , ... ]
    INTO :<variable> [, :<variable> ... ]
    [...]
Copy

サンプルソースパターン

サンプル補助データ

注釈

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

Oracle
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
Snowflake
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

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スクリプトは BULK COLLECT INTO 句をサポートしていません。ただし、 ARRAY_AGG を使って新しい変数を構築することは可能です。詳細は コレクション一括操作セクション を参照してください。

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

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

関連 EWIs

関連 EWIs はありません。

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

警告

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

説明

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

Snowflake Scripting RESULTSET および CURSOR

Snowflake RESULTSET 構文
<resultset_name> RESULTSET [ DEFAULT ( <query> ) ] ;

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

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

推奨事項

注釈

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

Oracle

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

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

Cursorの使用

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

既知の問題

1.RESULTSET の使用制限

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

関連 EWIs

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

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