Translation reference to convert Teradata CURSOR statement to Snowflake Scripting
Description
A cursor is a data structure that is used by stored procedures at runtime to point to a resultset returned by an SQL query. For more information check here.
DECLARE cursor_name [ SCROLL | NO SCROLL ] CURSOR [ WITHOUTRETURN |WITHRETURN [ ONLY ] [ TO [ CALLER | CLIENT ] ] ]FOR cursor_specification [ FOR [ READ ONLY | UPDATE ] ] | statement_name;
FETCH [ [ NEXT | FIRST ] FROM ] cursor_name INTO [ variable_name | parameter_name ] [ ,...n ];
OPEN cursor_name [ USING [ SQL_identifier | SQL_paramenter ] [ ,...n ] ];
CLOSE cursor_name ;
Sample Source Patterns
Setup Data
The following code is necessary to execute the sample patterns present in this section.
CREATETABLEvEmployee( PersonID INT, LastName VARCHAR(255), FirstName VARCHAR(255));CREATETABLEResTable( Column1 VARCHAR(255));INSERT INTO vEmployee(PersonID, LastName, FirstName) VALUES (1, 'Smith', 'Christian');INSERT INTO vEmployee(PersonID, LastName, FirstName) VALUES (2, 'Johnson', 'Jhon');INSERT INTO vEmployee(PersonID, LastName, FirstName) VALUES (3, 'Brown', 'William');INSERT INTO vEmployee(PersonID, LastName, FirstName) VALUES (4, 'Williams', 'Gracey');INSERT INTO vEmployee(PersonID, LastName, FirstName) VALUES (5, 'Garcia', 'Julia');INSERT INTO vEmployee(PersonID, LastName, FirstName) VALUES (6, 'Miller', 'Peter');INSERT INTO vEmployee(PersonID, LastName, FirstName) VALUES (7, 'Davis', 'Jannys');CREATETABLETEST_TABLE ( ColumnA NUMBER, ColumnB VARCHAR(8), ColumnC VARCHAR(8));SELECT*FROM TEST_TABLE;INSERT INTO TEST_TABLE VALUES (1, '1', '1');INSERT INTO TEST_TABLE VALUES (2, '2', '2');
REPLACE PROCEDURE CursorsTest()BEGINDECLARE val1 VARCHAR(255);DECLARE empcursor CURSORFORSELECT LastNameFROM vEmployeeORDER BY PersonID;OPEN empcursor;FETCH NEXT FROM empcursor INTO val1;FETCH NEXT FROM empcursor INTO val1;INSERTINTO ResTable(Column1) VALUES (val1);CLOSE empcursor;END;CALL CursorsTest();SELECT*FROM ResTable;
Johnson
Snowflake Scripting
CREATE OR REPLACE PROCEDURE PUBLIC.CursorsTest ()RETURNS VARCHARLANGUAGE SQLEXECUTE AS CALLERAS$$BEGIN LET val1 VARCHAR(255); LET empcursor CURSORFORSELECT LastNameFROM PUBLIC.vEmployee ORDER BY PersonID;OPEN empcursor;FETCH NEXT FROM empcursor INTO val1;FETCH NEXT FROM empcursor INTO val1;INSERTINTO PUBLIC.ResTable (Column1) VALUES (:val1);CLOSE empcursor;END;$$;CALL CursorsTest();SELECT*FROM PUBLIC.ResTable;
Johnson
Single Returnable Cursor
The following procedure is intended to return one result set since it has the DYNAMIC RESULT SETS 1 property in the header, the cursor has the WITH RETURN property and is being opened in the body.
Teradata
REPLACEPROCEDURE spSimple ()DYNAMIC RESULT SETS1BEGINDECLARE result_set CURSORWITHRETURN ONLY FORSELECT*FROM vEmployee;OPEN result_set;END;CALL spSimple();
The following procedure is intended to return multiple results when DYNAMIC RESULT SETS property in the header is greater than 1, the procedure has multiple cursors with the WITH RETURN property and these same cursors are being opened in the body.
Teradata
REPLACEPROCEDURE spTwoOrMore()DYNAMIC RESULT SETS2BEGINDECLARE result_set CURSORWITHRETURN ONLY FORSELECT*FROM SampleTable2;DECLARE result_set2 CURSORWITHRETURN ONLY FORSELECT Column11 FROM SampleTable1;OPEN result_set2;OPEN result_set;END;CALL spTwoOrMore();
The following cursor uses binding variables as the were condition to perform the query.
Teradata
REPLACEPROCEDURE TestProcedure (IN param1 NUMBER, param2 VARCHAR(8), param3 VARCHAR(8))DYNAMIC RESULT SETS1BEGINDECLARE cursorExample CURSORWITHRETURN ONLY FORSELECT*FROM TEST_TABLEWHERE ColumnA = param1 AND ColumnB LIKE param2 and ColumnC LIKE param3;OPEN cursorExample; END;CALL TestProcedure(2, '2', '2');
It is a type of loop that uses a cursor to fetch rows from a SELECT statement and then performs some processing on each row.
Teradata
REPLACEPROCEDURE TestProcedure ()DYNAMIC RESULT SETS1BEGINFOR fUsgClass AS cUsgClass CURSORFORSELECT columnA FROM TEST_TABLE DOINSERT INTO ResTable(Column1) VALUES (fUsgClass.columnA);ENDFOR;END;CALL TestProcedure();SELECT*FROM ResTable;
|Column1|
+-------+
| 1|
| 2|
Snowflake Scripting
CREATEORREPLACEPROCEDURE TestProcedure ()RETURNSVARCHARLANGUAGESQLEXECUTEASCALLERAS$$BEGIN LET cUsgClass CURSORFORSELECT columnA FROM TEST_TABLE;FOR fUsgClass IN cUsgClass DOINSERT INTO ResTable (Column1)VALUES (:temp_fUsgClass_columnA);ENDFOR;END;$$;CALL PUBLIC.TestProcedure();SELECT*FROM ResTable;
|Column1|
+-------+
| 1|
| 2|
Cursor Fetch inside a Loop
It allows one to retrieve rows from a result set one at a time and perform some processing on each row.
Teradata
REPLACEPROCEDURE teradata_fetch_inside_loop() DYNAMIC RESULT SETS1BEGINDECLARE col_name VARCHAR(255);DECLARE col_int INTEGERDEFAULT1;DECLARE cursor_var CURSORFORSELECT columnA FROM TEST_TABLE;WHILE (col_int <>0) DO FETCH cursor_var INTO col_name;INSERT INTO ResTable(Column1) VALUES (cursor_var.columnA);SET col_int =0;ENDWHILE;END;CALL teradata_fetch_inside_loop();SELECT*FROM ResTable;
|Column1|
+-------+
| 2|
Snowflake Scripting
CREATEORREPLACEPROCEDURE teradata_fetch_inside_loop ()RETURNSVARCHARLANGUAGESQLEXECUTEASCALLERAS$$BEGIN LET col_name VARCHAR(255); LET col_int INTEGERDEFAULT1; LET cursor_var CURSORFORSELECT columnA FROM TEST_TABLE;WHILE (col_int <>0) LOOP --** MSC-WARNING - MSCCP0006 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **
FETCH cursor_var INTO col_name;INSERT INTO ResTable (Column1)VALUES (cursor_var.columnA); col_int :=0;ENDLOOP;END;$$;CALL teradata_fetch_inside_loop();SELECT*FROM ResTable;
|Column1|
+-------+
| 2|
Known Issues
The following parameters are not applicable in Snowflake Scripting.
1. Declare
[ SCROLL/NO SCROLL ] Snowflake Scripting only supports FETCH NEXT.
[ READ-ONLY ] This is the default in Snowflake Scripting.
[ UPDATE ].
2. Fetch
[ NEXT ] This is the default behavior in Snowflake Scripting.
[ FIRST ].
Related EWIs
MSCEWI1081: Snowflake Scripting procedures cannot return more than one result set
MSCCP0003: This statement has usages of cursor for loop
MSCCP0006: Fetch inside a loop is considered a complex pattern, this could degrade Snowflake performance