SnowConvert AI - Oracle - DML STATEMENTS¶
Descrição ¶
As extensões de instrução DML diferem das instruções DML normais porque podem usar elementos de PL/SQL como coleções e registros. Até o momento, alguns desses elementos não são compatíveis com o Snowflake Scripting. Se uma instrução não for suportada, um EWI será adicionado durante a conversão. Outras instruções DML serão convertidos como se não estivessem dentro de um procedimento.
Extensão da instrução INSERT¶
Referência de tradução para converter a extensão de instrução Oracle INSERT para o Script Snowflake
Nota
Algumas partes do código de saída foram omitidas por motivos de clareza.
Descrição¶
A extensão PL/SQL da instrução SQL
INSERTpermite especificar um nome de registro navalues_clausedasingle_table_insertem vez de especificar uma lista de colunas nainsert_into_clause.(Extensão da instrução INSERT da referência de linguagem Oracle PL/SQL)
O Snowflake INSERT INTO difere do Snowflake Scripting nas restrições de variáveis; é necessário que os nomes sejam precedidos por dois pontos «:» para vincular o valor das variáveis.
Recomendações¶
Nota
Esse código foi executado para uma melhor compreensão dos exemplos:
Oracle¶
CREATE TABLE numbers_table(num integer, word varchar2(20));
Snowflake¶
CREATE OR REPLACE TABLE PUBLIC.numbers_table (num integer,
word VARCHAR(20));
Extensão da instrução INSERT de caso simples¶
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 ;
Resultado¶
NUM |
WORD |
|---|---|
10 |
ten |
11 |
onze |
Script 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;
Resultado¶
NUM |
WORD |
|---|---|
10 |
ten |
11 |
onze |
Problemas conhecidos¶
1. Records are not supported by Snowflake Scripting¶
Como os registros não são suportados pelo script Snowflake, em vez de usar o registro VALUES, cláusula , é necessário mudá-la para uma cláusula SELECT e dividir as colunas do registro. Para obter mais informações, consulte a Seção de definição do tipo de registro.
Instrução MERGE¶
Referência de tradução para converter a instrução Oracle MERGE para Script Snowflake
Nota
Algumas partes do código de saída foram omitidas por motivos de clareza.
Descrição¶
A instrução
MERGEé usada para selecionar linhas de uma ou mais fontes para atualização ou inserção em uma tabela ou exibição. É possível especificar condições para determinar se é necessário atualizar ou inserir na tabela ou exibição de destino. Essa instrução é uma maneira conveniente de combinar múltiplas operações. Permite evitar várias instruçõesINSERT,UPDATEeDELETEDML.MERGEé uma instrução determinística. Não é possível atualizar a mesma linha da tabela de destino várias vezes na mesma instruçãoMERGE. (Referência de linguagem Oracle PL/SQL, instrução MERGE)
Sintaxe 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
Sintaxe de script 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> [ , ... ] )
Amostra de padrões da origem¶
Amostra de dados auxiliares¶
Nota
Esse código foi executado para uma melhor compreensão dos exemplos:
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
);
Caso simples da instrução 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;
Resultado¶
PERSON_ID |
FIRST_NAME |
LAST_NAME |
TITLE |
|---|---|---|---|
1 |
John |
Smith |
Mr |
2 |
Alice |
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;
Resultado¶
PERSON_ID |
FIRST_NAME |
LAST_NAME |
TITLE |
|---|---|---|---|
1 |
John |
Smith |
Mr |
2 |
Alice |
Jones |
Mrs. |
3 |
Jane |
Doe |
Miss |
4 |
Dave |
Brown |
Mr |
Instrução MERGE com DELETE e cláusula where¶
Para encontrar uma equivalência entre a instrução DELETE e a cláusula where, é necessário reordenar e implementar algumas alterações na instrução de mesclagem do Snowflake.
Alterações necessárias:¶
Substitua DELETE where_clause do Oracle por uma nova matchedClause do Snowflake com a instrução AND predicate
Substitua where_clause de merge_insert_clause do Oracle por uma instrução AND predicate no Snowflake notMatchedClause
Oracle¶
MERGE INTO bonuses D USING (
SELECT
employee_id,
salary,
department_id
FROM
hr.employees
WHERE
department_id = 80
) S ON (D.employee_id = S.employee_id)
WHEN MATCHED THEN
UPDATE
SET
D.bonus = D.bonus + S.salary *.01 DELETE
WHERE
(S.salary > 8000)
WHEN NOT MATCHED THEN
INSERT
(D.employee_id, D.bonus)
VALUES
(S.employee_id, S.salary *.01)
WHERE
(S.salary <= 8000);
SELECT * FROM bonuses ORDER BY employee_id;
Resultado¶
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;
Resultado¶
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 |
Aviso
Em alguns casos, as alterações aplicadas podem não funcionar como esperado, como no exemplo a seguir:
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;
Resultado¶
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;
Resultado¶
PERSON_ID |
FIRST_NAME |
LAST_NAME |
TITLE |
|---|---|---|---|
1 |
John |
Smith |
Mr |
2 |
Alice |
Jones |
Mrs. |
4 |
Dave |
Brown |
Mr |
Problemas conhecidos¶
1. Oracle’s error_logging_clause is not supported¶
Não há equivalente para a cláusula de registro de erros no Snowflake Scripting.
2. Changed applied do not work as expected¶
Às vezes, as alterações aplicadas para obter a equivalência funcional entre a instrução de mesclagem do Oracle e do Snowflake não funcionam como esperado.
EWIs relacionados¶
SSC-FDM-0006: A coluna do tipo número pode não se comportar de forma semelhante no Snowflake.
SSC-FDM-OR0018: A instrução de mesclagem pode não funcionar como esperado
Instrução SELECTINTO¶
Referência de tradução para converter a instrução Oracle SELECT INTO para Script Snowflake
Nota
Algumas partes do código de saída foram omitidas por motivos de clareza.
Descrição¶
A instrução
SELECTINTOrecupera valores de uma ou mais tabelas do banco de dados (como faz a instrução SQLSELECT) e os armazena em variáveis (o que não é feito pela instrução SQLSELECT). (Instrução SELECT INTO da referência de linguagem Oracle PL/SQL)
Sintaxe Oracle SELECT INTO¶
SELECT [ { DISTINCT | UNIQUE } | ALL ] select_list
{ into_clause | bulk_collect_into_clause } FROM rest-of-statement ;
Sintaxe da cláusula Oracle Into¶
INTO { variable [, variable ]... | record )
Sintaxe de Oracle Bulk Collect¶
BULK COLLECT INTO { collection | :host_array }
[, { collection | :host_array } ]...
Sintaxe do Script 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> ... ]
[...]
Amostra de padrões da origem¶
Amostra de dados auxiliares¶
Nota
Esse código foi executado para uma melhor compreensão dos exemplos:
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"}}'
;
Caso simples da instrução SELECTINTO¶
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;
Resultado¶
AUX_NUM |
AUX_WORD |
|---|---|
1 |
um |
Script 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;
Resultado¶
|AUX_NUM|AUX_WORD|
|-------|--------|
|1 |one |
Problemas conhecidos¶
1. BULK COLLECT INTO is not supported¶
O Script Snowflake não oferece suporte à cláusula BULK COLLECT INTO. Entretanto, é possível usar ARRAY_AGG para construir uma nova variável. Para obter mais informações, consulte a Seção de operações em massa de coleção.
2. Collections and records are not supported¶
O Script Snowflake não oferece suporte ao uso de coleções nem registros. É possível migrá-los usando tipos de dados semiestruturados, conforme explicado nesta seção.
EWIs relacionados¶
Sem EWIs relacionados.
Solução alternativa para simular o uso de registros¶
Aviso
Esta página está obsoleta, mas foi deixada para fins de compatibilidade. Se quiser ver a seção atualizada, consulte Coleções e registros
Descrição¶
Esta seção descreve como simular o comportamento dos registros Oracle em instruções SELECT e INSERT, usando RESULTSET e CURSORS do Snowflake Scripting.
Snowflake Scripting RESULTSET e CURSOR¶
Sintaxe do Snowflake RESULTSET¶
<resultset_name> RESULTSET [ DEFAULT ( <query> ) ] ;
LET <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
LET <resultset_name> RESULTSET [ { DEFAULT | := } ( <query> ) ] ;
Recomendações¶
Nota
Nos exemplos a seguir, esse código foi executado para melhor compreensão dos exemplos:
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"}}'
;
Usando RESULTSET e Cursores em vez de Registros¶
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;
Resultado¶
AUX_NUM |
AUX_WORD |
|---|---|
1 |
um |
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;
using 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;
$$;
Resultado¶
AUX_NUM |
AUX_WORD |
|---|---|
1 |
um |
Problemas conhecidos¶
1. Limitation in the use of RESULTSET¶
RESULTSET é muito limitado em seu uso. Se a instrução table(result_scan(last_query_id()), deve ser usada logo após a execução da consulta RESULTSET. Para obter mais informações, consulte este link.
EWIs relacionados¶
SSC-EWI-0036: Tipo de dados convertido em outro tipo de dados.
SSC-EWI-0056: Criar tipo não suportado.