数据库函数

Postgres内置了对SQL函数的支持。 这些函数存在于你的数据库中,它们可以与API一起使用

快速演示

开始使用

Supabase 为创建数据库函数提供了几个选项。你可以使用仪表板或直接使用 SQL 创建它们。 我们在 Dashboard 中提供了一个 SQL 编辑器,或者你可以 连接 到数据库并自己运行SQL查询。

  1. 进入 SQL编辑器栏。
  2. 点击 新查询
  3. 输入创建或替换数据库功函数的SQL。
  4. 点击 运行或cmd+enter (ctrl+enter)。

简单的函数

让我们创建一个基本的数据库函数,返回一个字符串 hello world.

1create or replace function hello_world() -- 1
2returns text -- 2
3language sql -- 3
4as $$  -- 4
5  select 'hello world';  -- 5
6$$; --6
显示/隐藏细节

最基本的是,一个函数有以下部分:

  1. create or replace function hello_world()。函数声明,其中hello_world是函数的名称。你可以在创建一个新的函数时使用create,或者在替换一个现有函数时使用replace。或者你可以同时使用create或replace来处理这两种情况。
  2. returns text: 函数返回的数据类型。如果它什么都不返回,你可以returns void
  3. language sql': 在函数主体中使用的语言。这也可以是一种程序性语言:plpgsql, plv8, plpython`等。
  4. as $$: 函数包装器。任何包含在$$符号中的东西都将是函数主体的一部分。
  5. select 'hello world';: 一个简单的函数体。如果函数体中的最后一条select语句后面没有语句,将被返回。
  6. $$;: 函数封装器的结束符号。

函数创建后,我们有几种 "执行 "函数的方法--可以直接在数据库中使用SQL,也可以使用其中一个客户端库。

1select hello_world();

返回数据集

数据库函数也可以从数据表或视图中返回数据集。

例如,如果我们有一个数据库,里面有一些星球大战的数据。

Planets

idname
1Tattoine
2Alderaan
3Kashyyyk

People

idnameplanet_id
1Anakin Skywalker1
2Luke Skywalker1
3Princess Leia2
4Chewbacca3

我们可以创建一个函数,返回所有的星球:

1create or replace function get_planets()
2returns setof planets
3language sql
4as $$
5  select * from planets;
6$$;

因为这个函数返回一个表集,我们也可以应用过滤器和选择器。例如,如果我们只想要第一个星球:

1select *
2from get_planets()
3where id = 1;

传递参数

让我们创建一个函数,在planets表中插入一个新的行星并返回新的ID。注意,这次我们使用的是plpgsql语言。

1create or replace function add_planet(name text)
2returns bigint
3language plpgsql
4as $$
5declare
6  new_row bigint;
7begin
8  insert into planets(name)
9  values (add_planet.name)
10  returning id into new_row;
11
12  return new_row;
13end;
14$$;

再一次,你可以在数据库中使用select查询来执行这个函数,或者使用客户端库。

1select * from add_planet('Jakku');

建议

数据库函数vs边缘函数#

对于数据密集型的操作,使用数据库函数,它在你的数据库中执行并可以使用REST和GraphQL API远程调用。

对于需要低延迟的使用情况,使用边缘函数,它是全局分布的,可以用Typescript编写。

安全性 definervs invoker#

Postgres允许你指定是作为调用函数的用户(invoker),还是作为函数的创建者(definer)来执行函数。比如说:

1create function hello_world()
2returns text
3language plpgsql
4security definer set search_path = public
5as $$
6begin
7  select 'hello world';
8end;
9$$;

最好的做法是使用security invoker(这也是默认的)。如果你使用security definer,你必须设置search_path。 这限制了潜在的损害,如果你允许访问执行该函数的用户不应该有的模式。

函数的权限

默认情况下,数据库函数可以由任何角色执行。你可以通过改变默认权限来限制这一点,然后选择哪些角色可以执行功能。

1ALTER DEFAULT PRIVILEGES REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC;
2
3-- Choose which roles can execute functions
4GRANT EXECUTE ON FUNCTION hello_world TO authenticated;
5GRANT EXECUTE ON FUNCTION hello_world TO service_role;

资源

深度挖掘

创建数据库函数

使用JavaScript调用数据库函数#

使用数据库函数来调用外部API#