What you will be able to do
- Query VARIANT data in a staging table with dot and bracket notation, and explode arrays with FLATTEN
- Decide between a stored procedure and a UDF based on what the transformation logic has to do
- Explain how UDTFs and external functions work and what they mean for performance
- Use the SECURE keyword to hide a function's logic, and know what unauthorized users can still see
1.Staging tables and querying semi-structured data with FLATTEN
Many pipelines land raw data in a staging layer, transform it, and copy it into downstream tables. Snowflake's own description of a CDC consumer follows this pattern: a pipeline in which only the staging-table data that changed since the last extraction is transformed and copied onward. When the raw data is hierarchical, the staging table usually holds it in a VARIANT column. JSON, Avro, ORC and Parquet data is typically loaded this way. The documentation's example table, car_sales, has one VARIANT column, src, containing nested arrays and objects.
You read a VARIANT with path notation. Dot notation follows a path like column:level1.level2. Bracket notation uses column['level1']['level2'] with single-quoted element names. Column names are case-insensitive, but element names are case-sensitive, so src:salesperson.name and src:Salesperson.Name are different paths. Element names that break SQL identifier rules, such as names containing a space, must be double-quoted.
SELECT src:salesperson.name
FROM car_sales
ORDER BY 1;Data types matter when you put views over a staging table. In the documented output, the path query returns "Frank Beasley" with its JSON quotes still attached, and the page notes that with bracket notation values are retrieved as strings. A view that only projects paths therefore exposes semi-structured values, not typed relational columns. The provided sources go no further on how views and data types interact, for example on casting rules inside views.
Path notation works for single values. Arrays such as customer or vehicle need FLATTEN. FLATTEN is a table function that explodes a VARIANT, OBJECT or ARRAY into multiple rows. It produces a lateral view that can correlate with tables earlier in the FROM clause, which turns semi-structured data into a relational shape. Its optional arguments are PATH (which element to flatten), OUTER, RECURSIVE and MODE. OUTER defaults to FALSE, and in that case input rows that can't be expanded, for example because they have zero entries, are dropped from the output. With OUTER => TRUE, each such row produces one output row with NULL in KEY, INDEX and VALUE. For heavy querying of semi-structured data, the documentation suggests the search optimization service to improve performance.
Checkpoint 1 of 5· Check yourself
A staging table holds orders as VARIANT, and some orders have an empty line_items array. A FLATTEN over line_items must still return one row for every order. What do you set?
OUTER defaults to FALSE, which drops rows that can't be expanded. Setting it to TRUE keeps one row per such input, with NULL in KEY, INDEX and VALUE.
“If TRUE, exactly one row is generated for zero-row expansions (with NULL in the KEY, INDEX, and VALUE columns).”Source: docs.snowflake.com
2.Stored procedures vs UDFs for data processing
Once the logic outgrows a SELECT, you can extend Snowflake with your own code. There are two main tools, and their purposes differ. A stored procedure generally performs administrative operations by executing SQL statements, and returning a value is optional. A user-defined function (UDF) calculates and returns a value, which it always does explicitly.
| Need | Stored procedure | UDF |
|---|---|---|
| Run DDL or DML (delete old data, update rows, drop temp tables) | Yes | No |
| Be called inside a SQL statement and return a value the statement uses | No | Yes |
| Produce a value for every input row or every group | No | Yes |
| Branching, looping and dynamically built database operations | Yes | No |
A procedure can bundle many operations into one call. For example, it can run the same cleanup across several tables with a cut-off date passed in as a parameter. It can also run with owner's rights, which lets the owner delegate operations to users who couldn't otherwise perform them. You write the handler in Java, JavaScript, Python, Scala or Snowflake Scripting, create it with CREATE PROCEDURE, and invoke it with CALL. JavaScript and Snowflake Scripting handlers must be in-line, while Java, Python and Scala handlers can be in-line or staged. Procedures fit naturally into pipelines because tasks can run them. Dynamic tables can't call them.
CREATE OR REPLACE PROCEDURE myproc(from_table STRING, to_table STRING, count INT)
RETURNS STRING
LANGUAGE PYTHON
RUNTIME_VERSION = '3.12'
PACKAGES = ('snowflake-snowpark-python')
HANDLER = 'run'
as
$$
def run(session, from_table, to_table, count):
session.table(from_table).limit(count).write.save_as_table(to_table)
return "SUCCESS"
$$;Checkpoint 2 of 5· Check yourself
Each night, a pipeline has to delete rows older than N days from several staging tables, with N passed in at run time. Which object fits best?
Deleting data is a DML operation, which is the job of a stored procedure. A UDF returns a value inside a statement and doesn't perform DML, and a dynamic table only materializes a SELECT.
“You need to perform DDL or DML database operations”Source: docs.snowflake.com
3.UDTFs, external functions and their performance impacts
A scalar UDF returns one value per row. A user-defined table function (UDTF) returns a table. Using Java as the example, the handler class processes the rows passed to the UDTF and returns a tabular result. The rows are partitioned, either implicitly by Snowflake or explicitly in the call. The handler can have an initializer for partition-scoped state, a process method that handles each row, and an endPartition method that finishes the partition and can return a value for it. Implicit partitioning is best when the UDTF looks at each row in isolation and keeps no state across rows. For performance, Snowflake usually runs multiple instances of the handler in parallel. Remember the dynamic table limit from the pipeline side: a UDTF can appear in a dynamic table only inside a lateral join.
An external function calls code that runs outside Snowflake. Remote services can be written with any HTTP server stack, including serverless compute such as AWS Lambda. Snowflake reaches them through a proxy, configured with an API integration (CREATE API INTEGRATION) that stores the security information needed. To a SQL user, an external function behaves like any other UDF. It returns a value, which can be a VARIANT containing JSON. It accepts parameters, can be overloaded, and can appear in any clause where a UDF can, including inside a view definition or a larger expression.
select upper(zipcode_to_city_external_function(zipcode)) from address_table;These choices determine where a transformation can run. Since external functions and stored procedures are excluded from dynamic table definitions, logic that depends on them has to be orchestrated with tasks. The provided sources don't give detailed latency or batching figures for external functions.
Checkpoint 3 of 5· Match them up
Match each function type to its defining trait
Tap a term, then the definition that fits it.
UDFs return per-row values inside statements, UDTFs return tables, external functions delegate work to a remote HTTP service, and procedures carry out database operations.
“Your Java UDTF handler class processes rows received in the UDTF call and returns a tabular result.”Source: docs.snowflake.com
4.Secure functions: hiding definitions and sensitive data
Sometimes the logic itself is sensitive, such as proprietary scoring or computations that could reveal underlying data. Adding the SECURE keyword when you create a UDF or stored procedure limits who can see its definition and helps limit the sensitive data a UDF could expose. Only users granted a role that owns the function can see the definition details. Everyone else still sees enough to call the function correctly.
| Hidden from unauthorized users | Still visible to unauthorized users |
|---|---|
| Body (the handler code that comprises its logic) | Parameter types |
| List of imports | Return type |
| Handler name | Handler language |
| Packages list | Null handling and volatility |
In some cases, error messages related to secure functions may also be redacted. Secure functions sit alongside the other protections already covered. A stored procedure's choice of caller's rights or owner's rights determines what it can access, and Snowflake lists secure UDFs and procedures as the way to keep sensitive information from users who shouldn't see it.
Checkpoint 4 of 5· Exam question
A finance team currently maintains a nightly stored procedure and task pair that recomputes a summary table from three source tables using full recomputation logic the team wrote by hand. They want to replace this with a declarative object that automatically tracks dependencies and refreshes on a lag target, without them writing custom orchestration code. Which options correctly describe capabilities of the object they should adopt? (Select all that apply.)(Select 3)
Correct answers: A, B, C — A TARGET_LAG setting tells Snowflake how current the result must be, and Snowflake schedules refreshes to try to meet that freshness target automatically.; The refresh mode can be set to INCREMENTAL so only changed rows since the last refresh are reprocessed, reducing compute compared to full recomputation.; Setting TARGET_LAG to DOWNSTREAM on an intermediate object lets it refresh only when a dependent object actually needs the data, rather than on its own fixed schedule.
- A. Correct - dynamic tables use a TARGET_LAG parameter that expresses the maximum acceptable staleness, and Snowflake's scheduler works to refresh the table often enough to stay within that target.
- B. Correct - dynamic tables support an incremental refresh mode that processes only the rows affected by upstream changes since the previous refresh, which is typically far cheaper than a full recompute.
- C. Correct - setting TARGET_LAG to DOWNSTREAM on an intermediate dynamic table defers its refresh timing to whatever cadence its dependents require, avoiding redundant refreshes on a fixed schedule.
- D. Incorrect - dynamic tables cannot reference stored procedures or external functions in their defining query, which is a documented restriction distinguishing them from ordinary tables populated by procedural code.
- E. Incorrect - dynamic table costs include cloud services charges for dependency tracking and scheduling in addition to warehouse compute during refreshes, so cost is not limited to compute alone.
Checkpoint 5 of 5· Check yourself
A UDF is created with the SECURE keyword. A user whose role doesn't own it inspects the function. What can that user still see?
SECURE hides the body, imports, handler name and packages from non-owners. The signature (parameter and return types), handler language, null handling and volatility stay visible.
“When you specify that the UDF or procedure is secure, these details are visible only to authorized users”Source: docs.snowflake.com
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.FLATTEN returns a row for every input row, even when the array is empty.Why is that wrong?
OUTER defaults to FALSE, which drops rows that can't be expanded. Only OUTER => TRUE produces one NULL-filled row for each zero-row expansion.
Covered in Staging tables and querying semi-structured data with FLATTEN
2.A UDF is the right container for transformation steps that update or delete rows.Why is that wrong?
DDL and DML belong in stored procedures. A UDF's job is to calculate and return a value used inside a SQL statement.
3.Making a function SECURE hides everything about it, including its signature.Why is that wrong?
Only definition details such as the body, imports, handler name and packages are hidden. Parameter types, return type, language, null handling and volatility stay visible.
Covered in Secure functions: hiding definitions and sensitive data
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.
“only the data in staging tables that has changed since the last extraction is transformed and copied into other tables”
↩︎ Staging tables and querying semi-structured data with FLATTEN - 2.
“the column name is case-insensitive but element names are case-sensitive.”
↩︎ Staging tables and querying semi-structured data with FLATTEN“Enclose element names in single quotes. Values are retrieved as strings.”
↩︎ Staging tables and querying semi-structured data with FLATTEN“You can use the search optimization service to improve query performance.”
↩︎ Staging tables and querying semi-structured data with FLATTEN - 3.
“FLATTEN can be used to convert semi-structured data to a relational representation.”
↩︎ Staging tables and querying semi-structured data with FLATTEN“If TRUE, exactly one row is generated for zero-row expansions (with NULL in the KEY, INDEX, and VALUE columns).”
↩︎ Exam trap 1“If TRUE, exactly one row is generated for zero-row expansions (with NULL in the KEY, INDEX, and VALUE columns).”
↩︎ Checkpoint - 4.
“Generally to perform administrative operations by executing SQL statements.”
↩︎ Stored procedures vs UDFs for data processing“Calculate and return a value. A function always returns a value explicitly by specifying an expression.”
↩︎ Exam trap 2“You need to perform DDL or DML database operations”
↩︎ Checkpoint - 5.https://docs.snowflake.com/en/developer-guide/stored-procedure/stored-procedures-overviewOfficial docs
“Execute code with the privileges of the role that owns the procedure, rather than with the privileges of the role that runs the procedure.”
↩︎ Stored procedures vs UDFs for data processing“Ensure that sensitive information is concealed from users who should not have access to it.”
↩︎ Secure functions: hiding definitions and sensitive data - 6.https://docs.snowflake.com/en/user-guide/tasks-introOfficial docs
“Tasks can run SQL commands and stored procedures that use supported languages and tools”
↩︎ Stored procedures vs UDFs for data processing - 7.
“To improve performance, Snowflake usually executes multiple instances of the UDTF handler code”
↩︎ UDTFs, external functions and their performance impacts“Your Java UDTF handler class processes rows received in the UDTF call and returns a tabular result.”
↩︎ Checkpoint - 8.
“An API integration stores information, such as security information, that is needed to work with a proxy service or remote service.”
↩︎ UDTFs, external functions and their performance impacts“an external function behaves like any other UDF”
↩︎ UDTFs, external functions and their performance impacts - 9.
“Use UDTFs outside of lateral joins.”
↩︎ UDTFs, external functions and their performance impacts - 10.
“you can use the SECURE keyword when creating a user-defined function (UDF) and stored procedure.”
↩︎ Secure functions: hiding definitions and sensitive data“In some cases, error messages related to secure functions might be redacted.”
↩︎ Secure functions: hiding definitions and sensitive data“When you specify that the UDF or procedure is secure, these details are visible only to authorized users”
↩︎ Exam trap 3“When you specify that the UDF or procedure is secure, these details are visible only to authorized users”
↩︎ Checkpoint