Databricks DE ยท Topic 8.5
Reusable, governed functions registered in UC by 3-level name โ scalar UDFs (a value), table functions/UDTFs (a table), and Python UDFs โ shared across queries and controlled by GRANT EXECUTE. This deep dive walks each with verified SQL.
catalog.schema.fn): a scalar UDF returns one value (SELECT/WHERE), a UDTF (RETURNS TABLE) returns a table (FROM). Governed by GRANT EXECUTE; they also power column masks & row filters.bmi(weight,height) once, everyone reuses it by name, and you control who can run it. A UDTF returns a whole sheet, not one cell.SELECT/WHERE.
CREATE FUNCTION prod.util.bmi(w DOUBLE, h DOUBLE) RETURNS DOUBLE DETERMINISTIC RETURN w/(h*h); SELECT id, prod.util.bmi(weight, height) AS bmi FROM patients;
RETURNS TABLE) โ use in FROM like a parameterized view.
CREATE FUNCTION prod.util.top_orders(region STRING, n INT) RETURNS TABLE (order_id BIGINT, amount DECIMAL(10,2)) RETURN SELECT order_id, amount FROM prod.sales.orders WHERE region = top_orders.region ORDER BY amount DESC LIMIT n; SELECT * FROM prod.util.top_orders('West', 10);
For logic SQL can't express; the body is dollar-quoted. Runs per-row in Python โ slower than SQL/built-ins, keep off hot paths.
CREATE OR REPLACE FUNCTION prod.util.normalize_phone(p STRING) RETURNS STRING LANGUAGE PYTHON AS $$ import re return re.sub(r'\D', '', p) if p else None # strip non-digits $$;
Calling a function needs USE CATALOG + USE SCHEMA + EXECUTE (same chain as 8.2). The same kind of UDF is what column masks (8.3) & ABAC policies (8.4) attach.
GRANT EXECUTE ON FUNCTION prod.util.bmi TO `analysts`; -- a mask function consumed by 8.3 column masks / 8.4 ABAC policies CREATE OR REPLACE FUNCTION prod.util.mask_email(e STRING) RETURNS STRING RETURN CASE WHEN is_account_group_member('pii_readers') THEN e ELSE '***@***' END;
โธ calling prod.util.bmi(...) needs the USE chain + EXECUTE
| Scalar UDF | Table function (UDTF) | Python UDF | |
|---|---|---|---|
| Returns | one value | a table (RETURNS TABLE) | one value |
| Used in | SELECT/WHERE | FROM | SELECT/WHERE |
| Language | SQL or Python | SQL | Python |
| Perf | fast (SQL) | fast (SQL) | slower (per-row) |
prod.util.mask_email(email) once; reuse in queries and attach it as a column mask. A UDTF prod.util.top_orders(region, n) lets analysts call SELECT * FROM prod.util.top_orders('West', 10).DETERMINISTIC only if it truly is (don't mark functions using current_*).RETURNS TABLE, in FROM).DETERMINISTIC โ wrong cached results.