---
id: functions
title: Functions
description: Creating and using Postgres functions.
---

import Tabs from '@theme/Tabs';
import TabsPanel from '@theme/TabsPanel';


Postgres has built-in support for [SQL functions](https://www.postgresql.org/docs/current/sql-createfunction.html). 
These functions live inside your database, and they can be [used with the API](/docs/reference/javascript/rpc).

## Quick demo

<iframe
  className="w-full video-with-border"
  width="640"
  height="385"
  src="https://www.youtube-nocookie.com/embed/MJZCCpCYEqk"
  frameBorder="1"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
  allowFullScreen
></iframe>

## Creating Functions 

Supabase provides several options for creating database functions. You can use the Dashboard or create them directly using SQL. 
We provide a SQL editor within the Dashboard, or you can [connect](/docs/guides/database/connecting/connecting-to-postgres) to your database 
and run the SQL queries yourself.


1. Go to the "SQL editor" section.
2. Click "New Query".
3. Enter the SQL to create or replace your Database function.
4. Click "Run" or cmd+enter (ctrl+enter).

## Examples

### Data set

For this guide we'll use the following example data:


<Tabs
defaultActiveId="Data"
values={[
  {label: 'Data', value: 'Data'},
  {label: 'SQL', value: 'SQL'},
]}>

<TabsPanel id="SQL" label="SQL">

```sql
create table planets (
  id serial primary key,
  name text
);

insert into planets (id, name) 
values 
  (1, 'Tattoine'),
  (2, 'Alderaan'),
  (3, 'Kashyyyk');

create table people (
  id serial primary key,
  name text,
  planet_id bigint references planets
);

insert into people (id, name, planet_id) 
values 
  (1, 'Anakin Skywalker', 1),
  (2, 'Luke Skywalker', 1),
  (3, 'Princess Leia', 2),
  (4, 'Chewbacca', 3);
```

</TabsPanel>
<TabsPanel id="Data" label="Data">

<h4>Planets</h4>

| id    | name | 
| ----  | ---- | 
|    1 | Tattoine | 
|    2 | Alderaan  | 
|    3 | Kashyyyk | 

<h4>People</h4>

| id    | name | planet_id |
| ----  | ---- | ---- | 
|    1 | Anakin Skywalker | 1 | 
|    2 | Luke Skywalker  | 1 | 
|    3 | Princess Leia | 2 | 
|    4 | Chewbacca | 3 | 

</TabsPanel>

</Tabs>

### Basic function

A basic example which returns a string "hello world".

```sql
create or replace function hello_world() -- 1
returns text -- 2
language sql -- 3
as $$  -- 4
  select 'hello world';  -- 5
$$; --6

```

<details>
<summary>Show/Hide Details</summary>
  
At it's most basic a function has the following parts:

1. `create or replace function hello_world()`: The function declaration, where `hello_world` is the name of the function. You can use either `create` when creating a new function or `replace` when replacing an existing function. Or you can use `create or replace` together to handle either.
2. `returns text`: The type of data that the function returns. If it returns nothing, you can `returns void`. 
3. `language sql`: The language used inside the function body. This can also be a procedural language: `plpgsql`, `plv8`, `plpython`, etc.
4. `as $$`: The function wrapper. Anything enclosed inside the `$$` symbols will be part of the function body.
5. `select 'hello world';`: A simple function body. The final `select` statement inside a function body will be returned if there are no statements following it.
6. `$$;`: The closing symbols of the funciton wrapper.

</details>

#### Execute

<Tabs
defaultActiveId="SQL"
values={[
  {label: 'SQL', value: 'SQL'},
  {label: 'JS', value: 'JS'},
  {label: 'Dart', value: 'Dart'},
]}>

<TabsPanel id="SQL" label="SQL">

```sql
select hello_world();
```

</TabsPanel>
<TabsPanel id="JS" label="JS">

```js 
const { data, error } = supabase
  .rpc('hello_world')
```

Reference: [rpc()](/docs/reference/javascript/rpc)

</TabsPanel>
<TabsPanel id="Dart" label="Dart">

```dart 
final res = await supabase
  .rpc('hello_world')
  .execute();
```

Reference: [rpc()](/docs/reference/dart/rpc)

</TabsPanel>

</Tabs>


### Return table sets

A basic example which return all the `planets` in our example data set.

```sql
create or replace function get_planets() 
returns setof planets
language sql
as $$
  select * from planets;
$$;
```

#### Execute 

Because this function returns a table set, we can also apply filters and selectors. For example, if we only wanted the first planet:

<Tabs
defaultActiveId="SQL"
values={[
  {label: 'SQL', value: 'SQL'},
  {label: 'JS', value: 'JS'},
  {label: 'Dart', value: 'Dart'},
]}>

<TabsPanel id="SQL" label="SQL">

```sql
select *
from get_planets()
where id = 1;
```

</TabsPanel>
<TabsPanel id="JS" label="JS">

```js 
const { data, error } = supabase
  .rpc('get_planets')
  .eq('id', 1)
```

Reference: [rpc()](/docs/reference/javascript/rpc)

</TabsPanel>
<TabsPanel id="Dart" label="Dart">

```dart 
final res = await supabase
  .rpc('get_planets')
  .eq('id', 1)
  .execute();
```

Reference: [rpc()](/docs/reference/dart/rpc)

</TabsPanel>

</Tabs>


### With parameters

A basic example which will insert a new planet into the `planets` and return the new ID. Note that this time we're using the `plpgsql` language.

```sql
create or replace function add_planet(name text) 
returns bigint
language plpgsql
as $$
declare 
  new_row bigint;
begin
  insert into planets(name)
  values (add_planet.name)
  returning id into new_row;

  return new_row;
end;
$$;
```

#### Execute 

Because this function returns a table set, we can also apply filters and selectors. For example, if we only wanted the `name` of the first planet:

<Tabs
defaultActiveId="SQL"
values={[
  {label: 'SQL', value: 'SQL'},
  {label: 'JS', value: 'JS'},
  {label: 'Dart', value: 'Dart'},
]}>

<TabsPanel id="SQL" label="SQL">

```sql
select * from add_planet('Jakku');
```

</TabsPanel>
<TabsPanel id="JS" label="JS">

```js 
const { data, error } = supabase
  .rpc('add_planet', { name: 'Jakku' })
```

Reference: [rpc()](/docs/reference/javascript/rpc)

</TabsPanel>
<TabsPanel id="Dart" label="Dart">

```dart 
final res = await supabase
  .rpc('add_planet', params: { 'name': 'Jakku' })
  .execute();
```

Reference: [rpc()](/docs/reference/dart/rpc)

</TabsPanel>

</Tabs>


## Resources

- PostgreSQL Official Docs: [Chapter 9. Functions and Operators](https://www.postgresql.org/docs/current/functions.html)
- PostgreSQL Reference: [CREATE FUNCTION](https://www.postgresql.org/docs/9.1/sql-createfunction.html)
