前端转全栈 03:数据库与 SQL 入门——把数据真正存下来

前端全栈tutorial数据库sqlpostgressupabase

系列目录:本文是「前端转全栈:Next.js + Supabase 实战」系列的第 3 篇。前两篇讲了心智模型和 HTTP,这一篇进入「存储」——数据库与 SQL。


很多前端同学把数据库想得特别玄乎。其实——数据库就是一个会听话的 Excel:有表格、有列、有行,你用一种叫 SQL 的语言命令它「把符合条件的行拿来」。


一、把数据库想成 Excel

| 概念 | Excel 类比 | 说明 | |------|-----------|------| | 数据库(Database) | 一个工作簿文件 | 比如本站的 postgres 库 | | 表(Table) | 一张工作表 | commentsviews 各是一张表 | | 字段/列(Column) | 表头的一列 | contentcreated_at | | 记录/行(Row) | 表格里的一行 | 一条具体评论 | | 主键(Primary Key) | 行号且唯一 | 每条记录的唯一身份证 |


二、本站真实的建表语句

看本站 supabase/schema.sqlcomments 表的定义:

CREATE TABLE IF NOT EXISTS comments (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  post_slug TEXT NOT NULL,
  author_name TEXT NOT NULL,
  author_avatar TEXT,
  content TEXT NOT NULL,
  user_id UUID REFERENCES auth.users(id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ DEFAULT now()
);

逐列拆解:

  • id UUID PRIMARY KEY DEFAULT gen_random_uuid():主键,自动生成唯一 UUID。
  • post_slug TEXT NOT NULLNOT NULL 表示必填,不填数据库直接报错。
  • author_avatar TEXT:没有 NOT NULL,表示可空。
  • user_id UUID REFERENCES auth.users(id)外键,指向 Supabase 自带的用户表,表示「这条评论属于哪个用户」。
  • created_at TIMESTAMPTZ DEFAULT now():默认取当前时间。

TIMESTAMPTZ 是「带时区的时间戳」,存 UTC。千万别用裸 TIMESTAMP,否则跨时区会乱。


三、关系:为什么需要外键

一个博客有「文章」和「评论」,评论必须属于某篇文章——这就是一对多关系

posts (1) ────< comments (多)
                  │
                  └── user_id 指向 users (1)

外键(REFERENCES)保证数据不「悬空」:你不能插入一条 user_id 不存在的评论。这就是数据库的约束力,比你在代码里写 if 判断可靠得多。

ON DELETE SET NULL 表示:如果用户被删了,评论的 user_id 置空但评论保留——这是一种业务取舍。


四、SQL 四大操作:增删改查(CRUD)

查(Read)—— 你最常用的

-- 查某篇文章的所有评论,按时间倒序
SELECT * FROM comments
WHERE post_slug = 'frontend-fullstack-01-mindset'
ORDER BY created_at DESC;

对应到本站 route.ts 的 GET:

const { data } = await supabase
  .from("comments")
  .select("*")
  .eq("post_slug", postSlug)
  .order("created_at", { ascending: false })

看到没?Supabase 的查询语法就是 SQL 的「链式翻译」,底层还是这条 SQL。

增(Create)

INSERT INTO comments (post_slug, content, author_name, user_id)
VALUES ('xxx', '很棒', '小明', 'uuid-here');

改(Update)

UPDATE comments SET content = '修改后的内容'
WHERE id = 'uuid-here';

删(Delete)

DELETE FROM comments WHERE id = 'uuid-here';

⚠️ UPDATE / DELETE 永远记得带 WHERE,否则会改/删全表。这是新手最惨的事故之一,生产环境尤甚。


五、索引:让查询快 100 倍

WHERE post_slug = ... 这种查询,如果表很大,数据库得逐行扫。给常用查询列加索引:

CREATE INDEX IF NOT EXISTS idx_comments_post_slug
  ON comments (post_slug);

索引就像书的目录——查某章直接翻到,而不是从头读。但索引会拖慢写入、占空间,只为高频查询列建


六、前端视角的三个提醒

  1. 永远别在前端拼 SQL。前端只能发请求,SQL 在服务端 / 数据库层执行。谁在前端写 SQL 谁就是安全漏洞制造机。
  2. 数据库是真相来源。缓存、前端状态都可能错,数据库里的才是准的。
  3. 用 Supabase 不用自己装数据库。站点后台直接开 SQL Editor 把 schema.sql 粘进去执行即可建好表,零运维。

总结

  • 数据库 ≈ 会听话的 Excel:表、列、行、主键。
  • 外键保证关系不悬空;NOT NULL / 默认值约束数据质量。
  • CRUD = SELECT / INSERT / UPDATE / DELETE,UPDATE/DELETE 必带 WHERE。
  • 索引加速查询,但按需建。
  • 本站的 supabase/schema.sql 就是你最好的建表范本。

下一篇,我们把「前端(Next.js)」和「服务端」打通——Next.js 服务端:Server/Client Components 与 Route Handlers


练习:在 Supabase SQL Editor 里执行 schema.sql 建好表,然后手动插一条评论,再用 SELECT * FROM comments; 查出来,感受「数据真的落库了」。

Comments

Sign in to leave a comment.