六维教程

Supabase 数据关联查询

前面学的都是单表操作,真实产品几乎都是多张表配合使用。这一篇学习用外键建模数据关系,再用一行代码完成多表联查。

为什么要多张表

设想一个博客,如果所有数据放一张表,文章表里塞作者昵称和头像,会出现两个问题

  1. 作者改昵称后,历史文章里的作者信息不会跟着变
  2. 数据重复存储,白白浪费存储空间

正确做法是分开两张表,文章只存作者 ID,查文章时再根据 ID 关联出作者信息。这就是关系型数据库最擅长的场景。

外键

外键(Foreign Key)是连接两张表的桥梁。给 posts 表加一个 user_id 列,声明它引用 profiles 表的 id 列

create table public.posts (
  id bigint generated always as identity primary key,
  title text not null,
  content text,
  user_id uuid references public.profiles (id)
);
说明
id 自增主键,bigint 类型适合业务表
title 文章标题
content 文章内容
user_id 作者,外键指向 profiles.id

references 关键字就是外键声明,它告诉数据库,这一列的值必须来自另一张表里真实存在的 ID。传一个不存在的作者 ID 会被拒绝,数据库从源头保证数据不乱。

插入测试数据

插入两篇文章,分别指向两个测试用户

insert into posts (title, content, user_id)
values
  ('第一篇文章', '内容一', '11111111-1111-1111-1111-111111111111'),
  ('第二篇文章', '内容二', '22222222-2222-2222-2222-222222222222');

一次请求拿全部信息

关键操作来了。查询文章时,在 select 里用括号写上关联表,Supabase 会把作者信息一起返回

const { data, error } = await supabase
  .from('posts')
  .select('*, author:profiles(*)')

console.log(data)

返回结果里,每篇文章多了一个 author 字段,里面是完整的作者对象

[
  {
    id: 1,
    title: '第一篇文章',
    user_id: '11111111-1111-1111-1111-111111111111',
    author: {
      id: '11111111-1111-1111-1111-111111111111',
      username: '小明',
      age: 18
    }
  }
]

语法拆解

, author:profiles()’ 由三部分组成

部分 含义
* 取文章全部字段
author: 给关联结果起个别名,返回里叫 author 而不是 profiles
profiles(*) 关联 profiles 表并取全部字段

不写别名也可以,直接写 profiles(*),返回的字段名就是表名。起别名是为了让数据结构更符合业务直觉。

Supabase 是通过外键自动发现关联关系的,所以建表时把外键写对,前端联查就不用额外配置。

只取关联表的某些字段

// 只要作者昵称
const { data } = await supabase
  .from('posts')
  .select('title, author:profiles(username)')

一对多和多对一

关系 例子 建模方式
多对一 多篇文章属于一个作者 文章表存作者 ID
一对多 一个作者有多篇文章 同一张表反着查
多对多 一篇文章有多个标签 中间表存两个 ID

本教程的场景是典型的多对一。一对多查询,比如查某作者的全部文章,本质就是文章表按作者过滤

const { data } = await supabase
  .from('posts')
  .select('*')
  .eq('user_id', '11111111-1111-1111-1111-111111111111')

关联查询与 RLS

关联查询同样受 RLS 约束,联合策略对两张表各自生效。如果用户没有权限读作者那行,author 字段会是 null。设计公开文章时,记得给作者资料表也配置公开读策略,否则页面会缺作者信息。

下一篇学习文件存储,把用户的头像图片真正存进 Supabase。

下一篇 Supabase Storage 文件存储

上一篇
Supabase 行级安全策略 RLS
下一篇
Supabase Storage 文件存储