--- title: "Function" sidebarTitle: "Function" description: "Create, describe, alter, list, and drop registered functions with SQL." icon: function keywords: ["create function", "drop function", "show functions", "sql", "udf"] availability: embedded: unavailable enterprise: available --- [SQL runs in LanceDB Enterprise.](/sql) ## CREATE FUNCTION {#create} ```sql SQL icon="database" CREATE FUNCTION f(x int64) RETURNS int64 LANGUAGE python AS 'def f(x): return x * 2' WITH (pip = 'numpy==1.26.4', python_version = '3.11') ``` A function takes more than one parameter; each one binds a separate column or literal where the function is called: ```sql SQL icon="database" CREATE FUNCTION ratio(numerator float64, denominator float64) RETURNS float64 LANGUAGE python AS 'def ratio(numerator, denominator): return numerator / denominator' ``` Parameter and result types are Arrow type names, not SQL ones: `int64`, `float64`, `utf8`, `bool`, `date32`, and lists such as `list` or `fixed_size_list`. `BIGINT` is refused. A parameter accepts nulls unless it is declared `NOT NULL`. The body is Python source. Its dependencies are declared with it and are part of the **immutable function version**. Changing one produces a new version rather than altering the registered one, so a column filled by an earlier version is unaffected. | Option | | | --- | --- | | `pip` | pip requirements for the worker environment | | `conda` | conda packages instead of pip | | `conda_channels` | channels in priority order; requires `conda` | | `apt` | OS packages to install in the worker environment | | `image` | a specific container image to run the worker in, such as `'host/repo@sha256:...'` | | `python_version` | worker Python version; `3.12` when omitted, whatever Python you send the statement from | | `gpu` | `'true'` when every execution needs a GPU | | `gpu_class` | which configured GPU class to run on, when `gpu = 'true'` | | `result_stability` | `'input_and_context'` or `'per_call'` | | `batch_size` | maximum rows per Function call | | `row_timeout_seconds` | per-row (or per-batch, for a vectorized Function) execution timeout | **Errors and limits** | | | | --- | --- | | `LANGUAGE` other than `python` | refused | | `pip` and `conda` together | refused (pick one) | | `conda_channels` without `conda` | refused | | `gpu` set to anything but `'true'` | refused | | An empty body | refused | | Any other option | refused, and the message lists what is supported | **Enterprise job type:** `create_function`. Registration returns a job because the function is baked into an image before the version becomes usable. ## Artifact registration {#artifact} `CREATE FUNCTION name FROM ''` accepts the artifact, signature, runtime, optional secret bindings, and result stability produced by the SDK's registration request. Omit its `name` property because the SQL identifier supplies it. Escape apostrophes in the JSON as doubled apostrophes. By default, the command waits for its internal image-build job to publish the version, then returns one UTF-8 `definition` column containing FunctionVersion JSON. `WITH (wait = false)` instead returns the existing image-build registry job ID in `job_id`, with `operation` and `status` columns. The SDK's ordinary registration handle has type `query` and uses the SQL query UUID as its single `id`; the internal image-build job has type `create_function`. ## DESCRIBE and ALTER FUNCTION {#describe-alter} ```sql DESCRIBE FUNCTION embed WITH (version = '1', include_source = true) ``` DESCRIBE returns one `definition` JSON column for the exact version. `include_source` defaults to false; source-inclusive reads report an omission when the stored artifact exceeds the inline source limit. `ALTER FUNCTION name FROM ''` accepts a `reference` with name, namespace, object ID, location, version, and manifest digest, plus optional `metadata` and `disabled` updates. The command checks that reference before appending a revision and returns the resulting `definition` JSON. ## Call it {#call} Once registered, a function is callable by name in any query, the same as a built-in scalar function: ```sql SQL icon="database" SELECT id, f(x) AS doubled FROM my_table ``` This is also the fastest way to check a new registration before binding it to a column: call it over a few rows, or over literal arguments, before committing to [a computed column](/sql/ddl/table#computed-column) that fills from it. ## SHOW FUNCTIONS {#show} ```sql SQL icon="database" SHOW FUNCTIONS SHOW FUNCTIONS HISTORY IN "analytics" WITH (name = 'embed', limit = 100) SHOW FUNCTIONS HISTORY WITH (after_name = 'embed', after_version = '1', limit = 100) ``` `SHOW FUNCTIONS` returns the highest published numeric revision for each name. Add `HISTORY` to list every published revision, as Python's `list_functions()` does. Rows are ordered by name and numeric revision, so `2` comes before `10`. `after_name` and `after_version` must be supplied together for keyset pagination. `limit` bounds the response; `include_definition = false` omits the optional definition JSON. ## DROP FUNCTION {#drop} ```sql SQL icon="database" DROP FUNCTION embed WITH (version = '1') DROP FUNCTION IF EXISTS embed WITH (version = '1') ``` DROP removes only the requested revision from lookup and listing. Other published revisions and their grants remain available. Dropping the last visible revision releases the name and object binding; physical cleanup continues separately. The result reports `dropped` or `not_found`. `IF EXISTS` allows a missing name or a repeated drop of a previously published revision. A revision that was never published under an existing name is an error. All function object commands retain shared results even when general query-result copying is disabled, so asynchronous polling can resume on another query node. ## What to read next {#next} Registering one from the SDK, and diagnosing environment mismatches. Filling a column with a function instead of an expression.