Databricks DE ยท Topic 8.5

Unity Catalog Functions

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.

scalar UDFRETURNS TABLE (UDTF)LANGUAGE PYTHONGRANT EXECUTE

The one-liner

UC functions persist business logic in Unity Catalog (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.
๐Ÿ“ Analogy: a saved formula in a shared spreadsheet โ€” define 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.

Scalar vs table function โ€” click each

Scalar UDF (a value)
UDTF (a table)
Returns one value per row โ†’ use in 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 a whole table (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);

1 ยท Python UDF (governed, persistent)

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
$$;

2 ยท Governance & masks/filters

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;

3 ยท Can you run it? โ€” toggle the grants

โ–ธ calling prod.util.bmi(...) needs the USE chain + EXECUTE

USE CATALOG prodno
USE SCHEMA prod.utilno
EXECUTE ON FUNCTION prod.util.bmino
๐Ÿ”’ cannot execute function

Scalar vs UDTF vs Python

Scalar UDFTable function (UDTF)Python UDF
Returnsone valuea table (RETURNS TABLE)one value
Used inSELECT/WHEREFROMSELECT/WHERE
LanguageSQL or PythonSQLPython
Perffast (SQL)fast (SQL)slower (per-row)

Why it matters

๐Ÿงฎ Real-world use case: define 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).

Uses, edge cases & limitations

Common gotchas