SQL User-Defined Function Guide
SQL user-defined functions (SQL UDFs) let you encapsulate reusable computation logic in SQL expressions and call them just like built-in functions inside queries.
Choosing the Right Type
| Type | Best for | Limitations |
|---|---|---|
| SQL function (this guide) | Pure SQL logic: data cleansing, calculation formulas, conditional branching | SQL expressions only — cannot call external services |
| External function | Calling Python/Java code, external APIs, or ML models | Requires deploying an external service |
| Built-in function | Standard math, string, and date operations | Not customizable |
When to use a SQL function:
- The same computation logic appears repeatedly across multiple queries
- Business rules need to be maintained in one place (e.g., discount calculations, classification rules)
- You need to encapsulate complex CASE WHEN logic or multi-step calculations
SQL Commands Involved
| Command | Purpose |
|---|---|
CREATE FUNCTION | Create a scalar or table function |
CREATE OR REPLACE FUNCTION | Update an existing function definition |
DROP FUNCTION | Delete a function |
DESC FUNCTION | View a function definition |
SHOW EXTERNAL FUNCTIONS | List user-defined functions in the current SCHEMA |
Prerequisites
Scenario 1: Scalar Function — Encapsulating a Calculation Formula
Goal: Centrally manage discount calculation logic so it stays consistent wherever it is called.
| order_id | amount | discounted |
|---|---|---|
| 1 | 99.9 | 89.91 |
| 4 | 199.0 | 179.1 |
Scenario 2: Scalar Function — Encapsulating Classification Rules
Goal: Tier orders by amount with rules maintained in one place.
| order_id | amount | tier |
|---|---|---|
| 2 | 299.0 | Premium |
| 4 | 199.0 | Standard |
| 1 | 99.9 | Standard |
| 3 | 49.5 | Basic |
| 5 | 0.0 | Free |
Scenario 3: Scalar Function — Data Cleansing
Goal: Clean phone numbers by stripping non-numeric characters.
Scenario 4: Table Function — Returning Multiple Rows
A table function returns a virtual table and can be used in a FROM clause just like a regular table.
Goal: Generate a consecutive date sequence to populate a calendar dimension.
| dt |
|---|
| 2024-01-01 |
| 2024-01-02 |
| 2024-01-03 |
| 2024-01-04 |
| 2024-01-05 |
| dt | daily_revenue |
|---|---|
| 2024-01-01 | 99.9 |
| 2024-01-02 | 0 |
| 2024-01-03 | 348.5 |
| 2024-01-04 | 0 |
| 2024-01-05 | 199 |
Function Management
View a Function Definition
Returns the function name, creation time, full SQL definition, and more.
Update a Function
Use CREATE OR REPLACE FUNCTION to overwrite in place — no need to drop first:
Delete a Function
Notes
- Schema prefix is required: You must write
schema_name.function_namewhen calling a function, otherwise you will get a "function not found" error. You can change the resolution policy withSET cz.sql.remote.udf.lookup.policy = builtin_first— see SET (session parameters). - Default parameters must come last: Parameters with default values must be placed after parameters without default values.
- Table functions must use a query: The body of a
RETURNS TABLEfunction must be aSELECTstatement, not an expression. - DML is not supported in function bodies: SQL functions cannot execute INSERT/UPDATE/DELETE.
- Recursion is not supported: A function body cannot call itself — doing so results in a "function not found" error.
- Calling other user-defined functions: A function body can call other SQL functions in the same SCHEMA; use the SCHEMA prefix.
- Name collision with built-in functions: Call your custom function with the SCHEMA prefix; call the built-in function without a prefix. The two do not interfere with each other.
- NULL input: A NULL argument participates in CASE WHEN evaluation.
NULL >= 200is false, so the ELSE branch is taken. OR REPLACEandIF NOT EXISTScannot be used together: Combining them causes a syntax error.
