This warning indicates that the statement uses cursor fetch bulk operations. These operations allow you to retrieve multiple rows of data from a cursor at once, instead of one row at a time. Using bulk operations improves performance by reducing the number of communications needed between the client and server.
This pattern can become complex if not implemented correctly. For example, retrieving too many rows in a single fetch operation can consume excessive memory. It’s crucial to maintain a balance between the number of rows fetched and the available memory resources.
Using collation in Snowflake can impact query performance, particularly in WHERE clauses. To learn more about how collation affects performance, please refer to the Performance Implications of Using Collation.
A warning has been generated to indicate that a column was created with case-insensitive collation. Using this column in queries may cause slower performance.
CREATETABLE exampleTable
(
col1 CHAR(10),
col2 CHAR(20)COLLATE'en-ci'/*** SSC-PRF-0002 - CASE INSENSITIVE COLUMNS CAN DECREASE THE PERFORMANCE OF QUERIES ***/)COMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"teradata"}}';
CREATE OR REPLACETABLE exampleTable (
col1 VARCHAR(50)COLLATEBINARY_CI/*** SSC-PRF-0002 - CASE INSENSITIVE COLUMNS CAN DECREASE THE PERFORMANCE OF QUERIES ***/,
col2 VARCHAR(50)COLLATEBINARY_CS)COMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}';
CREATE OR REPLACETABLE exampleTable (
col1 VARCHAR(50)COLLATE'EN-CI-AS'/*** SSC-PRF-0002 - CASE INSENSITIVE COLUMNS CAN DECREASE THE PERFORMANCE OF QUERIES ***/,
col2 VARCHAR(50)COLLATE'EN-CS-AS')COMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}';
If your application’s performance is significantly affected by case-insensitive collation, consider rewriting your code to avoid using it. However, if the performance impact is acceptable, you can ignore this warning.
This warning appears when a FETCH statement is detected within a loop. The FETCH statement retrieves and processes individual rows from a result set one at a time.
Processing large datasets using cursors within loops can become complex, especially when:
Multiple table joins are involved
Complex calculations are required
Large numbers of rows need to be processed
This pattern may lead to performance issues and can be difficult to maintain as the data volume grows.
CREATE OR REPLACEPROCEDURE transact_fetch_inside_loop ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"transact"}}'EXECUTEASCALLERAS
$$
DECLARE--** SSC-FDM-TS0013 - SNOWFLAKE SCRIPTING CURSOR ROWS ARE NOT MODIFIABLE **
cursor1 CURSORFORSELECT
col1
FROM
my_table;BEGINWHILE(1=0)LOOP--** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **FETCHCURSOR1INTO
:VARIABLE1;ENDLOOP;END;
$$;
To improve performance and avoid complex patterns, use set-based operations instead of loops. Replace row-by-row processing with SQL statements (SELECT, UPDATE, DELETE) that operate on multiple rows simultaneously using WHERE clauses. This approach is more efficient and easier to maintain.
This warning indicates that the statement contains cursor for loops. A cursor for loop is a programming structure that processes query results one row at a time, allowing you to work with individual records from a result set.
This warning helps identify potential performance issues in cursor FOR loops. Performance problems may arise when:
The SELECT statement within the cursor returns a large dataset
The loop contains complex operations
The loop contains nested loops
While SnowConvert AI can detect these patterns, you should review and optimize the code to ensure efficient execution.
CREATE OR REPLACEPROCEDURE oracle_cursor_for_loop ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"oracle"}}'EXECUTEASCALLERAS
$$
BEGINLET temporary_for_cursor_0 CURSORFOR(SELECT col1 FROM
sample_table
);--** SSC-PRF-0004 - THIS STATEMENT HAS USAGES OF CURSOR FOR LOOP **FOR r1 IN temporary_for_cursor_0 DONULL;ENDFOR;END;
$$;
This warning indicates that the statement contains nested cursors. A cursor is a database feature that lets you process rows from a query result one at a time. Nested cursors occur when you use one cursor inside another cursor’s loop, which can impact performance and should be used with caution.
Nested cursors can significantly slow down your code’s performance, particularly when working with large amounts of data. This is because each time a cursor operates, it needs to communicate with the database server, creating additional processing overhead and delays.
CREATEORALTERPROCEDURE procedureSample
ASBEGINDECLARE@outer_category_id INT,@outer_category_name NVARCHAR(50),@inner_product_name NVARCHAR(50);-- Define the outer cursorDECLARE outer_cursor CURSORFORSELECT category_id, category_name FROM categories;-- Open the outer cursorOPEN@outer_cursor;-- Fetch the first row from the outer cursorFETCHNEXTFROM outer_cursor INTO@outer_category_id,@outer_category_name;-- Start the outer loopWHILE@@FETCH_STATUS=0BEGINPRINT'Category: '+@outer_category_name;-- Define the inner cursorDECLARE inner_cursor CURSORFORSELECT product_name FROM products WHERE category_id =@outer_category_id;-- Open the inner cursorOPEN inner_cursor;FETCHNEXTFROM inner_cursor INTO@inner_product_name;WHILE@@FETCH_STATUS=0BEGINPRINT'Product: '+@inner_product_name +' Category: '+CAST(@outer_category_id ASNVARCHAR(10));-- Fetch the next row from the inner cursorFETCHNEXTFROM inner_cursor INTO@inner_product_name;END;-- Close the inner cursorCLOSE inner_cursor;DEALLOCATE inner_cursor;-- Fetch the next row from the outer cursorFETCHNEXTFROM outer_cursor INTO@outer_category_id,@outer_category_name;END;-- Close the outer cursorCLOSE outer_cursor;DEALLOCATE outer_cursor;END;
CREATE OR REPLACEPROCEDURE procedureSample ()RETURNSVARCHARLANGUAGESQLCOMMENT='{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},"attributes":{"component":"transact"}}'EXECUTEASCALLERAS
$$
DECLAREOUTER_CATEGORY_IDINT;OUTER_CATEGORY_NAMEVARCHAR(50);INNER_PRODUCT_NAMEVARCHAR(50);-- Define the outer cursor--** SSC-FDM-TS0013 - SNOWFLAKE SCRIPTING CURSOR ROWS ARE NOT MODIFIABLE **
outer_cursor CURSORFORSELECT
category_id,
category_name
FROM
categories;-- Define the inner cursor--** SSC-FDM-TS0013 - SNOWFLAKE SCRIPTING CURSOR ROWS ARE NOT MODIFIABLE **
inner_cursor CURSORFORSELECT
product_name
FROM
products
WHERE
category_id = :OUTER_CATEGORY_ID;BEGIN-- Open the outer cursor--** SSC-PRF-0005 - THE STATEMENT BELOW HAS USAGES OF NESTED CURSORS. **OPENOUTER_CURSOR;-- Fetch the first row from the outer cursorFETCH
outer_cursor
INTO
:OUTER_CATEGORY_ID,
:OUTER_CATEGORY_NAME;-- Start the outer loop-- Define the inner cursorWHILE(:FETCH_STATUS=0)LOOP!!!RESOLVEEWI!!!/*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'PRINT' NODE ***/!!!PRINT'Category: '+@outer_category_name;-- Open the inner cursorOPEN inner_cursor;--** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **FETCH
inner_cursor
INTO
:INNER_PRODUCT_NAME;WHILE(:FETCH_STATUS=0)LOOP!!!RESOLVEEWI!!!/*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'PRINT' NODE ***/!!!PRINT'Product: '+@inner_product_name +' Category: '+CAST(@outer_category_id ASNVARCHAR(10));-- Fetch the next row from the inner cursor--** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **FETCH
inner_cursor
INTO
:INNER_PRODUCT_NAME;ENDLOOP;-- Close the inner cursorCLOSE inner_cursor;!!!RESOLVEEWI!!!/*** SSC-EWI-0058 - FUNCTIONALITY FOR 'DEALLOCATE' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!DEALLOCATE inner_cursor;-- Fetch the next row from the outer cursor--** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **FETCH
outer_cursor
INTO
:OUTER_CATEGORY_ID,
:OUTER_CATEGORY_NAME;ENDLOOP;-- Close the outer cursorCLOSE outer_cursor;!!!RESOLVEEWI!!!/*** SSC-EWI-0058 - FUNCTIONALITY FOR 'DEALLOCATE' IS NOT CURRENTLY SUPPORTED BY SNOWFLAKE SCRIPTING ***/!!!DEALLOCATE outer_cursor;END;
$$;
CREATE OR REPLACEPROCEDURE procedureSample ()RETURNSVARCHARLANGUAGESQLCOMMENT='{ "origin": "sf_sc", "name": "snowconvert", "version": { "major": 0, "minor": 0, "patch": "0" }, "attributes": { "component": "oracle", "convertedOn": "07/02/2025", "domain": "no-domain-provided" }}'EXECUTEASCALLERAS
$$
BEGINDECLARE--** SSC-PRF-0009 - PERFORMANCE REVIEW - CURSOR USAGE **
outer_cursor CURSORFORSELECT category_id, category_name FROM
categories;--** SSC-PRF-0009 - PERFORMANCE REVIEW - CURSOR USAGE **
inner_cursor CURSORFORSELECT product_name FROM
products
WHERE category_id =?;
outer_category_id VARIANT!!!RESOLVEEWI!!!/*** SSC-EWI-OR0129 - TYPE ATTRIBUTE 'categories.category_id%TYPE' COULD NOT BE RESOLVED, SO IT WAS TRANSFORMED TO VARIANT ***/!!!;
outer_category_name VARIANT!!!RESOLVEEWI!!!/*** SSC-EWI-OR0129 - TYPE ATTRIBUTE 'categories.category_name%TYPE' COULD NOT BE RESOLVED, SO IT WAS TRANSFORMED TO VARIANT ***/!!!;
inner_product_name VARIANT!!!RESOLVEEWI!!!/*** SSC-EWI-OR0129 - TYPE ATTRIBUTE 'products.PRODUCT_NAME%TYPE' COULD NOT BE RESOLVED, SO IT WAS TRANSFORMED TO VARIANT ***/!!!;
call_results VARIANT;BEGIN--** SSC-PRF-0005 - THE STATEMENT BELOW HAS USAGES OF NESTED CURSORS. **OPEN outer_cursor USING('DEFAULT VALUE NOT FOUND');FETCH outer_cursor INTO
:outer_category_id,
:outer_category_name;--** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **LOOPIF(outer_category_id IS NULL)THENEXIT;ENDIF;--** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
call_results :=(CALLDBMS_OUTPUT.PUT_LINE_UDF('Category: '||NVL(:outer_category_name :: STRING,'')));OPEN inner_cursor USING(:outer_category_id);--** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **LOOP--** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **FETCH inner_cursor INTO
:inner_product_name;IF(inner_product_name IS NULL)THENEXIT;ENDIF;--** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
call_results :=(CALLDBMS_OUTPUT.PUT_LINE_UDF('Product: '||NVL(:inner_product_name :: STRING,'')||' Category: '||NVL(:outer_category_id :: STRING,'')));ENDLOOP;CLOSE inner_cursor;--** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **FETCH outer_cursor INTO
:outer_category_id,
:outer_category_name;ENDLOOP;CLOSE outer_cursor;RETURN call_results;END;END;
$$;
CREATE OR REPLACEPROCEDURE procedureSample ()RETURNSVARCHARLANGUAGESQLCOMMENT='{ "origin": "sf_sc", "name": "snowconvert", "version": { "major": 0, "minor": 0, "patch": "0" }, "attributes": { "component": "oracle", "convertedOn": "07/02/2025", "domain": "no-domain-provided" }}'EXECUTEASCALLERAS
$$
BEGINDECLARE
inner_category_id VARIANT!!!RESOLVEEWI!!!/*** SSC-EWI-OR0129 - TYPE ATTRIBUTE 'categories.category_name%TYPE' COULD NOT BE RESOLVED, SO IT WAS TRANSFORMED TO VARIANT ***/!!!;
inner_product_name VARIANT!!!RESOLVEEWI!!!/*** SSC-EWI-OR0129 - TYPE ATTRIBUTE 'products.product_name%TYPE' COULD NOT BE RESOLVED, SO IT WAS TRANSFORMED TO VARIANT ***/!!!;
inner_cursor_res RESULTSET;
call_results VARIANT;BEGINLET temporary_for_cursor_0 CURSORFOR(SELECT category_id, category_name FROM
categories
);--** SSC-PRF-0004 - THIS STATEMENT HAS USAGES OF CURSOR FOR LOOP **--** SSC-PRF-0005 - THE STATEMENT BELOW HAS USAGES OF NESTED CURSORS. **FOR outer_cursor IN temporary_for_cursor_0 DOLET inner_cursor CURSORFORSELECT product_name, category_id FROM
products
WHERE category_id = outer_cursor.category_id;OPEN inner_cursor;--** SSC-PRF-0008 - PERFORMANCE REVIEW - LOOP USAGE **LOOP--** SSC-PRF-0003 - FETCH INSIDE A LOOP IS CONSIDERED A COMPLEX PATTERN, THIS COULD DEGRADE SNOWFLAKE PERFORMANCE. **FETCH inner_cursor INTO
:inner_product_name,
:inner_category_id;IF(inner_product_name IS NULL)THENEXIT;ENDIF;--** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
call_results :=(CALL dbms_output.put_line('Category id: '||NVL(outer_cursor.category_id :: STRING,'')));--** SSC-FDM-OR0035 - CHECK UDF IMPLEMENTATION FOR DBMS_OUTPUT.PUT_LINE_UDF. **
call_results :=(CALL dbms_output.put_line('Product name: '||NVL(:inner_product_name :: STRING,'')));ENDLOOP;CLOSE inner_cursor;ENDFOR;RETURN call_results;END;END;
$$;
SELECT
category_id,
category_name,--** SSC-PRF-0006 - NESTED CURSOR INSIDE QUERY IS NOT SUPPORTED IN SNOWFLAKE. **CURSOR!!!RESOLVEEWI!!!/*** SSC-EWI-0108 - THE FOLLOWING SUBQUERY MATCHES AT LEAST ONE OF THE PATTERNS CONSIDERED INVALID AND MAY PRODUCE COMPILATION ERRORS ***/!!!(SELECT
product_id,NVL(
product_name :: STRING,'')||', '||NVL(category_id :: STRING,'')FROM
products e
WHERE
e.category_id = d.category_id
)EMP_CURFROM
categories d;
CREATEMULTISETTABLET_2008,NOFALLBACK,NOBEFOREJOURNAL,NOAFTERJOURNAL,CHECKSUM=DEFAULT,DEFAULTMERGEBLOCKRATIO(COL1NUMBER(20,0)NOT NULL,COL2INTEGER,COL3VARCHAR(4)CHARACTERSETLATINNOTCASESPECIFIC,COL4DATEFORMAT'YYYY-MM-DD')PRIMARYINDEX(COL1,COL2)PARTITION BY(RANGE_N(COL4BETWEENDATE'2010-01-01'ANDDATE'2025-12-31'EACHINTERVAL'1'YEAR),CASE_N(COL3='T',COL3='M',COL3='L'));-- PARTITION BY transformed to CLUSTER BY
This message appears when SnowConvert AI detects loop usage in procedural code. Loops such as LOOP, WHILE, and FOR can lead to row-by-row processing and may degrade performance in Snowflake, especially when the loop iterates over large datasets or contains complex logic. The message is informational and prompts a review of the pattern.
This message appears when SnowConvert AI detects a cursor declaration in procedural code. Cursors allow row-by-row processing of query results, which can lead to performance issues in Snowflake, especially when processing large datasets.
While cursors are valid in Snowflake Scripting, they introduce overhead because:
Each row is processed individually rather than as a set
Multiple round trips to the database may be required
Memory usage can be higher compared to set-based operations
This warning is informational and prompts a review of whether the cursor usage is necessary or can be replaced with more efficient set-based operations.
Snowflake supports the PARTITION BY clause in Iceberg tables, however, only Iceberg partition transforms (https://iceberg.apache.org/spec/#partition-transforms) are supported. When transforming paritioning into Iceberg tables, SnowConvert AI will generate the equivalent partition transforms for supported cases. When no partition transform equivalent can be generated for the partition expressions, the PARTITION BY will be removed from the table by commenting it out with this PRF.
This PRF is only generated when SnowConvert AI migrates tables into Iceberg tables using the Tables translation conversion setting.
Analyze the impact of partitioning in the performance of queries over the generated Iceberg tables, if the difference is neglible then this PRF can be safely ignored.