SnowConvert AI - Oracle - DML STATEMENTS¶
説明¶
DML ステートメントの拡張は、コレクションや記録などの PL/SQL 要素を使用できるため、通常の DML ステートメントとは異なります。今のところ、これらの要素のいくつかはSnowflake Scriptingではサポートされていません。1つのステートメントがサポートされていない場合、翻訳中に EWI が追加されます。その他の DML ステートメントは、プロシージャ内にないものとして翻訳されます。
INSERT ステートメント拡張¶
Oracle INSERT ステートメント拡張をSnowflakeスクリプトに変換するための翻訳リファレンス
注釈
わかりやすくするため、出力コードの一部を省略しています。
説明¶
SQL
INSERTステートメントの PL/SQL 拡張を使用すると、single_table_insertのvalues_clauseで、insert_into_clauseで列リストを指定する代わりに、記録名を指定できます。(Oracle PL/SQL 言語リファレンス INSERT ステートメント拡張)
Snowflake INSERT INTO はSnowflake Scriptingと異なり、変数の制約があります。変数の値をバインドするためには、名前の前にコロン「:」を付ける必要があります。
推奨事項¶
注釈
このコードは例の理解を深めるために実行されました。
Oracle¶
CREATE TABLE numbers_table(num integer, word varchar2(20));
Snowflake¶
CREATE OR REPLACE TABLE PUBLIC.numbers_table (num integer,
word VARCHAR(20));
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 ;
結果¶
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;
結果¶
NUM |
WORD |
|---|---|
10 |
ten |
11 |
eleven |
既知の問題¶
1.記録はSnowflake Scriptingではサポートされていません¶
記録はSnowflakeスクリプトでサポートされていないため、 VALUES RECORD 句を使用する代わりに、 SELECT 句に変更し、記録の列を分割する必要があります。詳細は 記録の種類定義セクション を参照してください。
MERGE ステートメント¶
Oracle MERGE ステートメントをSnowflakeスクリプトに変換するための翻訳リファレンス
注釈
わかりやすくするため、出力コードの一部を省略しています。
説明¶
MERGEステートメントは、1つ以上のソースから行を選択し、テーブルまたはビューに更新または挿入するために使用されます。対象のテーブルやビューを更新するか挿入するかを決定する条件を指定できます。このステートメントは、複数の操作を組み合わせる便利な方法です。これにより、複数のINSERT、UPDATE、DELETEDML ステートメントを回避できます。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
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> [ , ... ] )
サンプルソースパターン¶
サンプル補助データ¶
注釈
このコードは例の理解を深めるために実行されました。
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
);
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
);
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;
結果¶
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;
結果¶
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\clause の where\clause を、Snowflakeの notMatchedClause の AND 述語 ステートメントに置き換えます
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;
結果¶
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;
結果¶
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;
結果¶
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;
結果¶
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¶
SSC-FDM-0006:数値型の列はSnowflakeでは同様の動作をしない場合があります。
SSC-FDM-OR0018:Mergeステートメントが期待通りに動作しない可能性があります
SELECT INTO ステートメント¶
Oracle SELECT INTO ステートメントをSnowflakeスクリプトに変換するための翻訳リファレンス
注釈
わかりやすくするため、出力コードの一部を省略しています。
説明¶
SELECTINTOステートメントは、(SQLSELECTステートメントと同様に)1つ以上のデータベーステーブルから値を取得し、(SQLSELECTステートメントでは行わない)変数に格納します。(Oracle PL/SQL 言語リファレンス SELECT INTO ステートメント)
Oracle SELECT INTO 構文¶
SELECT [ { DISTINCT | UNIQUE } | ALL ] select_list
{ into_clause | bulk_collect_into_clause } FROM rest-of-statement ;
Oracle Into句構文¶
INTO { variable [, variable ]... | record )
Oracle Bulk Collect構文¶
BULK COLLECT INTO { collection | :host_array }
[, { collection | :host_array } ]...
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> ... ]
[...]
サンプルソースパターン¶
サンプル補助データ¶
注釈
このコードは例の理解を深めるために実行されました。
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));
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"}}'
;
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;
結果¶
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;
結果¶
|AUX_NUM|AUX_WORD|
|-------|--------|
|1 |one |
既知の問題¶
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> ) ] ;
推奨事項¶
注釈
以下の例では、このコードは例の理解を深めるために実行されました。
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));
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"}}'
;
記録の代わりに 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;
結果¶
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;
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;
$$;
結果¶
AUX_NUM |
AUX_WORD |
|---|---|
1 |
one |
既知の問題¶
1.RESULTSET の使用制限¶
RESULTSET の使用は非常に限られています。table(result_scan(last_query_id())) ステートメントの場合、 RESULTSET のクエリが実行された直後に使用する必要があります。詳細情報はこちらの リンク をご覧ください。
関連 EWIs¶
SSC-EWI-0036: データ型が別のデータ型に変換されました。
SSC-EWI-0056: 作成タイプがサポートされていません。