LET keyword is not needed for assignment statements when the variable has been declared before. Check Snowflake Assignment documentation for more information.
Transformation for some data types needs to be updated, it may cause different results. For example, NUMBER to NUMBER rounds the value and the decimal point is lost. There is already a work item for this issue.
--** SSC-FDM-0007 - MISSING DEPENDENT OBJECT "employees" **CREATEORREPLACEPROCEDURE pinvalid (out_parameter OUTNUMBER(38,18))RETURNSVARCHARLANGUAGESQLCOMMENT='{ "origin": "sf_sc", "name": "snowconvert", "version": { "major": 0, "minor": 0, "patch": "0" }, "attributes": { "component": "oracle", "convertedOn": "07/16/2025", "domain": "no-domain-provided" }}'EXECUTEASCALLERAS$$
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;
END;
$$;
Currently, transformation for cursor, collection, record, and user-defined type variables are not supported by Snow Scripting. Therefore assignment statements using these variables are commented and marked as not supported. Changing these variables to Snowflake semi-structured data types could help as a workaround in some scenarios.
The CALL Specification is not supported in Snowflake Scripting since this is part of the development libraries for C and JAVA, not a SQL statement, therefore this statement is not transformed.
CREATEORREPLACEPROCEDURE caseExample1 (grade NUMBER(38,18))RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
CREATEORREPLACEPROCEDURE caseExample2 (grade NUMBER(38,18))RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
The basic unit of a PL/SQL source program is the block, which groups related declarations and statements.
A PL/SQL block is defined by the keywords DECLARE, BEGIN, EXCEPTION, and END. These keywords divide the block into a declarative part, an executable part, and an exception-handling part. Only the executable part is required. (PL/SQL Anonymous Blocks (https://livesql.oracle.com/apex/livesql/file/tutorial_KS0KNKP218J86THKN85XU37.html))
The BEGIN...END block in Oracle can have the following characteristics:
When calling a procedure or user-defined function (UDF), generating code is needed to support the equivalence as call_results variable. In this case, is used to print the information.
DECLARE
age NUMBER(38,18):=18;
call_results VARIANT;BEGINIF(: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.'));ENDIF;RETURN call_results;END;
When calling a procedure or user-defined function (UDF), generating code is needed to support the equivalence as call_results variable. In this case, is used to print the information.
-- Procedure declarationCREATEORREPLACEPROCEDURE calculate_sum(
p_num1 INNUMBER,
p_num2 INNUMBER,
p_result OUTNUMBER)ISBEGIN-- Calculate the sum of the two numbers
p_result := p_num1 + p_num2;END;/-- Anonymous block with a procedure callDECLARE-- 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;/
-- Procedure declarationCREATEORREPLACEPROCEDURE calculate_sum (p_num1 NUMBER(38,18), p_num2 NUMBER(38,18), p_result OUTNUMBER(38,18))RETURNSVARCHARLANGUAGESQLCOMMENT='{ "origin": "sf_sc", "name": "snowconvert", "version": { "major": 0, "minor": 0, "patch": "0" }, "attributes": { "component": "oracle", "convertedOn": "07/16/2025", "domain": "no-domain-provided" }}'EXECUTEASCALLERAS$$
BEGIN
-- Calculate the sum of the two numbers
p_result := :p_num1 + :p_num2;
END;
$$;-- Anonymous block with a procedure callDECLARE-- 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;BEGINCALL-- Call the procedure with the input values and get the result
calculate_sum(:v_num1,:v_num2,:v_result);-- 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;
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 ***/!!!EXECUTEIMMEDIATE:lv_sql_txt;END;
The following example displays the usage of a cursor inside a BEGIN...END block. Review the following documentation to learn more: Cursor documentation.
When calling a procedure or user-defined function (UDF), generating code is needed to support the equivalence as call_results variable. In this case, is used to print the information.
When calling a procedure or user-defined function (UDF), generating code is needed to support the equivalence as call_results variable. In this case, is used to print the information.
When calling a procedure or user-defined function (UDF), generating code is needed to support the equivalence as call_results variable. In this case, is used to print the information.
CREATETABLE continue_testing_table_1 (iterator VARCHAR2(5));CREATEORREPLACEPROCEDURE continue_procedure_1
IS
I NUMBER:=0;
J NUMBER:=20;BEGINWHILE I <= J LOOP
I := I +1;CONTINUE;INSERTINTO continue_testing_table_1
VALUES(TO_CHAR(I));ENDLOOP;END;CALL continue_procedure_1();SELECT*FROM continue_testing_table_1;
CREATETABLE continue_testing_table_2 (iterator VARCHAR2(5));CREATEORREPLACEPROCEDURE continue_procedure_2
IS
I NUMBER:=0;
J NUMBER:=20;BEGINWHILE I <= J LOOP
I := I +1;CONTINUEWHENMOD(I,2)=0;INSERTINTO continue_testing_table_2 VALUES(TO_CHAR(I));ENDLOOP;END;CALL continue_procedure_2();SELECT*FROM continue_testing_table_2;
CREATEORREPLACEPROCEDURE continue_procedure_3
IS
I NUMBER:=0;
J NUMBER:=10;
K NUMBER:=0;BEGIN<<out_loop>>WHILE I <= J LOOP
I := I +1;INSERTINTO continue_testing_table_3 VALUES('I'||TO_CHAR(I));<<in_loop>>WHILE K <= J *2LOOP
K := K +1;CONTINUE out_loop WHEN K > J /2;INSERTINTO continue_testing_table_3 VALUES('K'||TO_CHAR(K));ENDLOOP in_loop;
K :=0;ENDLOOP out_loop;END;CALL continue_procedure_3();SELECT*FROM continue_testing_table_3;
CREATEORREPLACEPROCEDURE const_decl_proc ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
The exception declaration sometimes could be followed by the exception initialization, the current transformation takes both and merge them into the Snowflake Scripting exception declaration. The original PRAGMAEXCEPTION_INIT will be commented out.
1. The variable declarations with NOT NULL constraints are not supported by Snow Scripting.¶
The creation of variables with NOT NULL constraint throws an error in Snow Scripting.
2. The cursor declaration has no equivalent to Snowflake Scripting.¶
The Oracle cursor declaration is useless so it might be commented out in the output code. The cursor definition will be used instead and it will be converted to the Snowflake Scripting cursor declaration.
3. The exception code exceeds Snowflake Scripting limits.¶
Oracle exception code is being removed when it exceeds the Snowflake Scripting code limits. The exception code must be an integer between -20000 and -20999.
There are some Oracle declaration statements that are not supported by the Snowflake Scripting declaration block, so it might be commented out and a warning will be added.
A default parameter is a parameter that has a value in case an argument is not passed in the procedure or function call. Since Snowflake doesn’t support default parameters, SnowConvert AI inserts the default value in the procedure or function call.
In the declaration, the DEFAULT VALUE clause of the parameter is removed. Both syntaxes, the := symbol and the DEFAULT clause, are supported.
CREATEORREPLACETABLE 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"}}';CREATEORREPLACETABLE 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"}}';
In order to check that the functionality is being emulated correctly the following query is going to execute the procedure and a SELECT from the table mentioned before.
In order to check that the functionality is being emulated correctly the following query is going to execute the procedure and a SELECT from the table mentioned before.
Snowflake Scripting has support for this statement, albeit with some functional differences. For more information on the Snowflake counterpart, please visit Snowflake’s EXECUTE IMMEDIATE documentation.
Numeric Names for placeholders are currently not being recognized by SnowConvert AI, but there is a work item to fix this issue.
3. Argument Expressions are not supported by Snowflake Scripting¶
In Oracle it is possible to use Expressions as Arguments for the Using Clause; however, this is not supported by Snowflake Scripting, and they are commented out.
4. Dynamic SQL Execution queries may be marked incorrectly as non-runnable.¶
In some scenarios there an execute statement may be commented regardless of being safe or non-safe to run so please take this into account:
Please note parenthesis are required for parameters in the USING Clause in Snowflake Scripting.
CREATEORREPLACEPROCEDURE inserting_procedure_variable_execute_concatenation_parameter (param1 INTEGER)RETURNSVARCHARLANGUAGESQLEXECUTEASCALLERAS$$
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;
$$;
CREATETABLE exit_testing_table_1 (
iterator VARCHAR2(5));CREATEORREPLACEPROCEDURE exit_procedure_1
IS
I NUMBER:=0;
J NUMBER:=20;BEGINWHILE I <= J LOOP
I := I +1;EXIT;INSERTINTO exit_testing_table_1 VALUES(TO_CHAR(I));ENDLOOP;END;CALL exit_procedure_1();SELECT*FROM exit_testing_table_1;
CREATETABLE exit_testing_table_2 (
iterator VARCHAR2(5));CREATEORREPLACEPROCEDURE exit_procedure_2
IS
I NUMBER:=0;
J NUMBER:=20;BEGINWHILE I <= J LOOPEXITWHEN I >5;
I := I +1;INSERTINTO exit_testing_table_2 VALUES(TO_CHAR(I));ENDLOOP;END;CALL exit_procedure_2();SELECT*FROM exit_testing_table_2;
CREATETABLE exit_testing_table_3 (
iterator VARCHAR2(5));CREATEORREPLACEPROCEDURE exit_procedure_3
IS
I NUMBER:=0;
J NUMBER:=10;
K NUMBER:=0;BEGIN<<out_loop>>WHILE I <= J LOOP
I := I +1;INSERTINTO exit_testing_table_3 VALUES('I'||TO_CHAR(I));<<in_loop>>WHILE K <= J *2LOOP
K := K +1;EXIT out_loop WHEN K > J /2;INSERTINTO exit_testing_table_3 VALUES('K'||TO_CHAR(K));ENDLOOP in_loop;
K :=0;ENDLOOP out_loop;END;CALL exit_procedure_3();SELECT*FROM exit_testing_table_3;
CREATEORREPLACETABLE EXPRESSIONS_TABLE (col VARCHAR(30))COMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}';CREATEORREPLACEPROCEDURE EXPRESSIONS_SAMPLE ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
Snowflake Scripting supports FOR LOOP that loops a specified number of times. The upper and lower bounds must be INTEGER. Check more information in the Snowflake Scripting documentation.
Oracle FOR LOOP behavior can also be modified by using the statements:
CREATEORREPLACEPROCEDURE P3 ()RETURNSVARCHARLANGUAGESQLCOMMENT='{ "origin": "sf_sc", "name": "snowconvert", "version": { "major": 0, "minor": 0, "patch": "0" }, "attributes": { "component": "oracle", "convertedOn": "07/14/2025", "domain": "no-domain-provided" }}'EXECUTEASCALLERAS$$
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 ***/!!!
--** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
!!!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
--** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
LOOP
NULL;
END LOOP;
!!!RESOLVE EWI!!! /*** SSC-EWI-OR0103 - FOR LOOP FORMAT IS CURRENTLY NOT SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!
--** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
FOR i IN VALUES OF :l_employee_values
--** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **
LOOP
NULL;
END LOOP;
END;
$$;
Warning
Transformation for custom types is currently not supported for Snowflake Scripting.
Oracle allows multiple conditions in a single FOR LOOP however, Snowflake Scripting only allows one condition per FOR LOOP. Only the first condition is migrated and the others are ignored during transformation. Check SSC-FDM-OR0022.
--** SSC-FDM-OR0022 - FOR LOOP WITH MULTIPLE CONDITIONS IS CURRENTLY NOT SUPPORTED BY SNOWFLAKE SCRIPTING **FOR i INREVERSE1TO3LOOPNULL;ENDLOOP;
2. Mutable vs Inmutable Counter Variable
Oracle allows modifying the value of the FOR LOOP variable inside the loop. The current documentation includes this functionality but Snowflake recommends avoiding this. Modifying the value of this variable may not behave correctly in Snowflake Scripting.
3. Integer vs Float number for Upper or Lower Bound
Snowflake Scripting only allows an INTEGER or an expression that evaluates to an INTEGER as a bound for the FOR LOOP condition. Floating numbers will be rounded up or down and alter the original bound.
4. Oracle Unsupported Clauses
Oracle allows additional clauses to the FOR LOOP condition. Like the BY clause for a stepped increment in the condition. And the WHILE and WHEN clause for boolean expressions. These additional clauses are not supported in Snowflake Scripting and are ignored during transformation. Check SSC-EWI-OR0101.
!!!RESOLVE EWI!!!/*** SSC-EWI-OR0101 - FOR LOOP WITH "BY" CLAUSE IS CURRENTLY NOT SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!FOR i IN5TO15LOOPNULL;ENDLOOP;
5. Unsupported Formats
Oracle allows different types of conditions for a FOR LOOP. It supports boolean expressions, collections, records… However, Snowflake scripting only supports FOR LOOP with defined integers as bounds. All other formats are marked as not supported and require additional manual effort to be transformed. Check SSC-EWI-OR0103.
FORALL indexIN bounds_clause [ SAVE ][ EXCEPTIONS ] dml_statement ;
Warning
Snowflake Scripting has no direct equivalence with the FORALL statement, however can be emulated with different workarounds to get functional equivalence.
CREATEORREPLACETABLE 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"}}';INSERTINTO table1(column1, column2)VALUES(1,2);INSERTINTO table1(column1, column2)VALUES(2,3);INSERTINTO table1(column1, column2)VALUES(3,4);INSERTINTO table1(column1, column2)VALUES(4,5);INSERTINTO table1(column1, column2)VALUES(5,6);CREATEORREPLACETABLE 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"}}';INSERTINTO table2(column1, column2)VALUES(1,2);
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATEORREPLACEPROCEDURE SampleProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATESCHEMAIFNOTEXISTS 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 ISTABLEOF table1%ROWTYPE;CREATEORREPLACETEMPORARYTABLE MYPACKAGE_COLLECTIONVARIABLE ();CREATEORREPLACEPROCEDURE InsertIntoPackage (param integer)RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
BEGIN
DELETE FROM
MYPACKAGE_COLLECTIONVARIABLE;
INSERT INTO MYPACKAGE_COLLECTIONVARIABLE
(
SELECT
:param,
:param
FROM
DUAL
);
END;
$$;CREATEORREPLACEPROCEDURE InsertUsingPackage ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;BEGINCALL
InsertIntoPackage(:param_value);CALL
InsertUsingPackage();RETURN call_results;END;select*from
table2;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
--Generated by SnowConvert---------------CREATEORREPLACETRANSIENTTABLE target_staging_table(
Id INTPRIMARYKEY,Name VARCHAR2(10)NOTNULL,
DepartmentID INTREFERENCES parent_table(Id))COMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}';--Generated by SnowConvert---------------CREATEORREPLACEPROCEDURE procedure_example (DEPARTMENT_ID_IN INT!!!RESOLVE EWI!!!/*** SSC-EWI-OR0129 - TYPE ATTRIBUTE 'source_table.DepartmentID%TYPE' COULD NOT BE RESOLVED, SO IT WAS TRANSFORMED TO VARIANT ***/!!!)RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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*FROMerror_table;
--Generated by SnowConvert---------------CREATEORREPLACETRANSIENTTABLE target_staging_table(
Id INTPRIMARYKEY,Name VARCHAR2(10)NOTNULL,
DepartmentID INTREFERENCES parent_table(Id))COMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}';--Generated by SnowConvert---------------CREATEORREPLACEPROCEDURE procedure_example (DEPARTMENT_ID_IN INT!!!RESOLVE EWI!!!/*** SSC-EWI-OR0129 - TYPE ATTRIBUTE 'employees.DepartmentID%TYPE' COULD NOT BE RESOLVED, SO IT WAS TRANSFORMED TO VARIANT ***/!!!)RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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*FROMerror_table;
CREATEORREPLACEPROCEDURE ifExample1 ( flag NUMBER)ISBEGINIF flag =1THENINSERTINTO if_table(col1)VALUES('one');ENDIF;END;CALL ifExample1(1);SELECT*FROM if_table;
CREATEORREPLACEPROCEDURE ifExample3 ( flag NUMBER)ISBEGINIF flag =1THENINSERTINTO if_table(col1)VALUES('one');
ELSIF flag =2THENINSERTINTO if_table(col1)VALUES('two');
ELSIF flag =3THENINSERTINTO if_table(col1)VALUES('three');ENDIF;END;CALL ifExample3(3);SELECT*FROM if_table;
CREATEORREPLACEPROCEDURE ifExample4 ( flag NUMBER)ISBEGINIF flag =1THENINSERTINTO if_table(col1)VALUES('one');
ELSIF flag =2THENINSERTINTO if_table(col1)VALUES('two');
ELSIF flag =3THENINSERTINTO if_table(col1)VALUES('three');ELSEINSERTINTO if_table(col1)VALUES('Unexpected input.');ENDIF;END;CALL ifExample4(4);SELECT*FROM if_table;
CREATEORREPLACEPROCEDURE ifExample1 (flag NUMBER(38,18))RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
BEGIN
IF (:flag = 1) THEN
INSERT INTO if_table(col1) VALUES ('one');
END IF;
END;
$$;CALL ifExample1(1);SELECT*FROM
if_table;
CREATEORREPLACEPROCEDURE ifExample2 (flag NUMBER(38,18))RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
CREATEORREPLACEPROCEDURE ifExample3 (flag NUMBER(38,18))RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
CREATEORREPLACEPROCEDURE ifExample4 (flag NUMBER(38,18))RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
The following example shows the usage of the IS EMPTY statement. The statement is applied over a nested table which uses a UDT as the definition type. The output shows the name of the employees who do not have a phone number.
CREATETYPE phone_number_type ASOBJECT(phone_number VARCHAR2(30));/CREATETYPE phone_number_list ASTABLEOF phone_number_type;CREATETABLE employee (
emp_id NUMBER,
emp_name VARCHAR2(50),
phone_numbers_col phone_number_list
) NESTED TABLE phone_numbers_col STORE AS nested_tab returnasvalue;INSERTINTO employee VALUES(1,'John Doe',
phone_number_list(phone_number_type('1234567890')));/INSERTINTO employee VALUES(2,'Jane Smith',
phone_number_list());SELECT emp_name
FROM employee
WHERE phone_numbers_col ISEMPTY;
The Snowflake query shown below is the equivalence of the functionality of the IS EMPTY statement. Particularly, the IS EMPTY statement has a difference between a NULL and an EMPTY object.
Notice that the User-Defined Types are transformed to a VARIANT. The VARIANT type in Snowflake is able to store objects and arrays. Since a nested table is a sequence of information, the ARRAY type is the most suitable type to redefine them and verify is the object ARRAY is empty.
The ARRAY_SIZE equivalent solution also allows to ask for nullability of the nested table (transformed to VARIANT). In other words, the VARIANT type can also store NULLs and empty ARRAYs.
!!!RESOLVE EWI!!!/*** SSC-EWI-0056 - CUSTOM TYPES ARE NOT SUPPORTED IN SNOWFLAKE BUT REFERENCES TO THIS CUSTOM TYPE WERE CHANGED TO VARIANT ***/!!!CREATETYPE phone_number_type ASOBJECT(phone_number VARCHAR2(30));!!!RESOLVE EWI!!!/*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'NESTED TABLE' NODE ***/!!!CREATETYPE phone_number_list ASTABLEOF phone_number_type;CREATEORREPLACETABLE 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"}}';CREATEORREPLACEVIEWPUBLIC.employee_view
COMMENT='{ "origin": "sf_sc", "name": "snowconvert", "version": { "major": 0, "minor": 0, "patch": "0" }, "attributes": { "component": "oracle", "convertedOn": "" }}'ASSELECT
emp_id,
emp_name,
phone_numbers_col
FROM
employee;INSERTINTO 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 ***/!!!);INSERTINTO 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
WHEREARRAY_SIZE( phone_numbers_col)=0;
Nested tables are not currently supported. The best approach based on this equivalence is to handle nested tables as Variant but declare Arrays with JSON data inside and execute the PARSE_JSON Snowflake function to populate the nested information.
3. Insert statements are not supported for User-defined types.¶
Since User-defined types are not supported in consequence the Insert statements to these types are not supported. Specifically in nested tables, the INSERT INTO ... VALUES statement has to be changed to a INSERT INTO ...SELECT because the ARRAY_CONSTRUCT function is expected to be used in that pattern.
Since the nested tables should be equivalently transformed to VARIANT and behave as ARRAYs,the functionality and logic of implementing procedures and interaction with the data should be adapted.
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;
In Oracle, the LOCK TABLE statement allows to explicitly acquire a shared or exclusive table lock on the specified table. The table lock lasts until the end of the current transaction. Review more information here (https://docs.oracle.com/javadb/10.6.2.1/ref/rrefsqlj40506.html).
Notice that in this example the LOCK TABLE statement has been deleted. This is because Snowflake handles locking in a different method through transactions.
FORALL indexIN bounds_clause [ SAVE ][ EXCEPTIONS ] dml_statement ;
Warning
Snowflake Scripting has no direct equivalence with the FORALL statement, however can be emulated with different workarounds to get functional equivalence.
CREATEORREPLACEPROCEDURE 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 ***/!!!)RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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*fromerror_table;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
CREATEORREPLACEPROCEDURE myProcedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;
An output parameter is a parameter whose value is passed out of the stored procedure/function module, back to the calling PL/SQL block. Since the output parameters are not supported by Snowflake Scripting, a solution has been implemented in order to emulate their functionality.
In order to check that the functionality is being emulated correctly the following query is going to execute the procedure and a SELECT from the table mentioned before.
CREATEORREPLACEPROCEDURE procedure_udtype_out_params (
p_employee_id NUMBER,
p_address OUT address_type
)ASBEGIN-- 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;
Cursor out parameters are not supported in Snowflake; despite that, a workaround that emulates Oracle’s behavior is applied to the transformed code. The procedure with the out parameters generates a temporary table with a dynamic name, and the procedure call will define the name of the temp table as a string to create the table within the procedure call.
Records are not natively supported in Snowflake; however, a workaround was used to emulate them as output parameters. By defining an OBJECT variable instead of the record, we could emulate the record’s field structure by assigning the out parameter result to each object property. Additionally, for each record field assigned as an out parameter, a new variable with the field type will be generated.
Packages are not supported in Snowflake, so their local members, like variables or constants, should also be preserved using a workaround. In this scenario, the package variable would be emulated using a session variable that would be updated after setting a local variable with the output parameter result.
1. Procedures with output parameters inside packages may not work correctly¶
Currently, there is an issue collecting the semantic information of procedures that reside inside packages, which is why the transformation for output parameters may work partially or not work at all. There is already a work in progress to resolve this issue.
As seen in the transformation, when retrieving the value from the called procedures, an implicit cast is performed from VARIANT to the type specified by the variable. Since there are a lot of possible data types, some casts may fail or contain different data.
SnowScript’s nested procedures do not support output parameters. To replicate this functionality in Snowflake, a RETURN type must be created based on the output parameters.
If there’s only one output parameter, that parameter will be returned at the end. In cases with multiple output parameters, an object construct will be generated containing their values. During the call, these values will be assigned to a variable, and subsequently, these results will be assigned to the corresponding variables or parameters.
Snowflake only permits one level of nesting for nested procedures. Therefore, a nested procedure within another nested procedure is not supported. If this occurs, the transformation will include the error !!!RESOLVE EWI!!! /*** SSC-EWI-0111 - ONLY ONE LEVEL OF NESTING IS ALLOWED FOR NESTED PROCEDURES IN SNOWFLAKE. ***/!!!
Nested procedure arguments do not support default clauses. Therefore, if a nested procedure call omits an optional parameter, the default value for that argument must be submitted within the procedure call. SnowConvert AI automatically identifies these scenarios and fills the procedure calls appropriately.
Snowflake does not support the overloading of nested procedures. If this occurs, the EWI SSC-EWI-0112 - NESTED PROCEDURE OVERLOADING IS NOT SUPPORTED will be added.
In Snowflake, a nested procedure definition requires empty parentheses () to be syntactically valid when it has no parameters; contrary to Oracle, where they are not needed. SnowConvert AI will add these automatically during translation.
In Oracle PL/SQL, the NOCOPY keyword is an optimization hint for OUT and IN OUT procedure parameters. By default, Oracle passes these parameters by value, creating an expensive copy of the data during the call and copying it back upon completion. This can cause significant performance overhead for large data structures.
NOCOPY instructs Oracle to pass by reference instead, allowing the procedure to directly modify the original data. This eliminates copying overhead and improves performance. However, changes are immediate and are not implicitly rolled back if an unhandled exception occurs within the procedure.
Therefore, we will remove the NOCOPY parameters option and add the FDM SSC-FDM-OR0050 - EXCEPTIONS WITH NOCOPY PARAMETERS MAY LEAD TO DATA INCONSISTENCY. This is because procedure execution terminates upon hitting an exception, preventing the RETURN statement from being reached. As a result, the variable in the caller’s declare block retains its initial values, as the procedure fails to successfully return a new value for assignment.
Our transformation efforts for nested procedures in Snowflake are limited to those nested directly within other procedures, supporting only one level of nesting. If the nesting level exceeds one, or if a procedure is nested within a standalone function, transformation is not supported, and the EWI !!!RESOLVE EWI!!! /*** SSC-EWI-0111 - ONLY ONE LEVEL OF NESTING IS ALLOWED FOR NESTED PROCEDURES IN SNOWFLAKE. ***/!!! will be added.
Additionally, overloading of nested procedures is not supported in Snowflake. In such cases, the EWI !!!RESOLVE EWI!!! /*** SSC-EWI-0112 - NESTED PROCEDURE OVERLOADING IS NOT SUPPORTED. ***/!!! will be added.
Transformation for nested procedures within anonymous blocks is currently pending. The EWI !!!RESOLVE EWI!!! /*** SSC-EWI-OR0057 - TRANSFORMATION FOR NESTED PROCEDURE OR FUNCTION IS NOT SUPPORTED IN THIS SCENARIO ***/!!! will be added.
Procedure calls can be migrated to Snowflake as long as there are no optional parameters and their order matches the formal parameters. Please note that Procedure invocations get migrated to a Call statement.
This sample contains manual intervention for some functional differences and is used to explain them. For more information on these differences, please check the Known Issues section below.
-- Procedure with optional parametersCREATEORREPLACEPROCEDURE proc_optional_parameters
--** SSC-FDM-0041 - DEFAULT PARAMETERS WERE REORDERED TO THE END OF THE PARAMETER LIST TO MATCH SNOWFLAKE REQUIREMENTS. CALLERS USING POSITIONAL ARGUMENTS MAY NEED TO BE UPDATED **(param1 INTEGER, param2 INTEGERDEFAULT8, param3 INTEGER)RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
$$;CREATEORREPLACEPROCEDURE calling_procedure ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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;
Snowflake requires default parameters to appear at the end of the parameter list. SnowConvert AI automatically reorders them and emits an SSC-FDM-0041 notice. When positional callers are detected, they are converted to named arguments.
2. Named parameters are accepted, but not functionally equivalent¶
Named parameters are supported in Snowflake. When default parameters are reordered, SnowConvert AI automatically converts positional call sites to use named arguments to preserve the original semantics.
3. Calling Subprograms with Out Parameters is not supported¶
Snowflake does not have support for parameter modes, however, a solution is being implemented to emulate their functionality. To get more information about the transformation for output parameters please go to the following article Output Parameters.
The statement is fully supported by Snowflake Scripting, but please take into account that there might be some differences when having some Commit and Rollback Statement.
RAISE<exception_name>;
Snowflake Scripting has support for this statement.
Call completed.-----------------------------------------------------------------------Error starting at line :31incommand-CALL simple_exception_throw_handle(1)Error report -
ORA-06510: PL/SQL: unhandleduser-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 106510.00000-"PL/SQL: unhandled user-defined exception"*Cause: Auser-defined exception was raised by PL/SQL code, but
not handled.*Action: Fix the problem causing the exceptionorwrite an exceptionhandlerfor this condition.Or you may need tocontact your
application administrator or DBA.-----------------------------------------------------------------------Error starting at line :33incommand-CALL simple_exception_throw_handle(2)Error report -
ORA-06510: PL/SQL: unhandleduser-defined exception
ORA-06512: at"SYSTEM.SIMPLE_EXCEPTION_THROW_HANDLE", line 14
ORA-06510: PL/SQL: unhandleduser-defined exception
ORA-06512: at"SYSTEM.SIMPLE_EXCEPTION_THROW_HANDLE", line 7
ORA-06512: at line 106510.00000-"PL/SQL: unhandled user-defined exception"*Cause: Auser-defined exception was raised by PL/SQL code, but
not handled.*Action: Fix the problem causing the exceptionorwrite an exceptionhandlerfor this condition.Or you may need tocontact your
application administrator or DBA.
CREATEORREPLACEPROCEDURE simple_exception_throw_handle (param1 INTEGER)RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS$$
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 issueCALL simple_exception_throw_handle(0);--Throws my_exceptionCALL simple_exception_throw_handle(1);--Throws my_exception, catches then raises second my_other_exceptionCALL simple_exception_throw_handle(2);
The procedure RAISE_APPLICATION_ERROR lets you issue user-defined ORA- error messages from stored subprograms. That way, you can report errors to your application and avoid returning unhandled exceptions (Oracle documentation (https://docs.oracle.com/cd/B19306_01/appdev.102/b14261/errors.htm)).
The error_number is a negative integer in the range -20000 .. -20999 and message is a character string up to 2048 bytes long.
If the optional third parameter is TRUE, the error is placed on the stack of previous errors. If the parameter is FALSE (the default), the error replaces all previous errors.
The equivalent statement in Snowflake is the RAISE clause, nevertheless, it is required to declare the user-defined exception as a variable before calling the RAISE statement for it.
The following example shows the translation commented out in the procedure body. It is because the code is outside the applicable code limits in Snowflake. The solution is to change the exception code for an available code in the query section.
As is widely acknowledged, non-scalar user-defined functions (UDFs) in Oracle are converted into Snowflake stored procedures to accommodate more intricate functionalities.
This transformation also alters the way the function is invoked, transitioning from a traditional function call to a stored procedure call.
For additional details regarding the invocation of stored procedures, refer to the documentation accessible here: PROCEDURE CALL.
When a function call is embedded within a query, the invocation process becomes more intricate due to Snowflake’s limitation of not being able to call procedures directly within queries. To overcome this limitation, the procedure invocation is moved outside the query, and the result is assigned to a variable. This variable is then referenced within the query, thereby achieving functional equivalence. This approach allows for the execution of more complex behaviors within Snowflake queries while adhering to the procedural constraints.
1. Unsupported Usage of UDFs in Queries with Query Dependencies¶
When calling User-Defined Functions (UDFs) within queries with query dependencies, scenarios involving embedded functions with columns as arguments are not supported. This limitation arises because the column values cannot be accessed from outside the query. Examples of unsupported scenarios include:
BEGINSELECT
sum_to_varchar_function(ext.col1, ext.col2)-- columns as arguments not supportedINTO
result_value
FROM example_table ext;END;
The supported scenarios include function calls with other types of arguments such as literal values, external variables, or parameters. For instance:
BEGINSELECT
sum_to_varchar_function(100, param1)INTO
result_value
FROM example_table ext;END;
In the supported scenarios, the function can effectively be migrated.