数据库不是一个巨大 Excel,而是一套受规则保护的数据系统
从一张 messages 表开始
| id | text | user_id | created_at |
|---|---|---|---|
| 41 | 早上好 | 7 | 2026-08-26 09:00 |
| 42 | 你好 | 9 | 2026-08-26 09:05 |
text
表 一类数据,例如 messages
行 一条具体留言
列 每条留言都有哪些字段
主键 唯一认出一行的 id为什么不能只用留言文字当 ID
两个人都可以写“你好”,文字也可以后来修改。稳定的唯一 ID 才能准确编辑、删除和建立关系。
text
DELETE /api/messages/42这里的 42 明确指向一条记录。
外键:把两张表连起来
users 表:
| id | name |
|---|---|
| 7 | 小月 |
| 9 | 小林 |
messages 的 user_id 指向 users 的 id。
text
users.id 7
↑
messages.user_id 7这样不必在每条留言重复保存完整用户资料。
四种最常见操作
SELECT:查询
sql
SELECT id, text, created_at
FROM messages
WHERE user_id = 7
ORDER BY created_at DESC;人话:从 messages 表取三个字段,只要用户 7 的留言,最新的排前面。
INSERT:新增
sql
INSERT INTO messages (text, user_id)
VALUES ('你好', 7);UPDATE:修改
sql
UPDATE messages
SET text = '修改后的留言'
WHERE id = 42 AND user_id = 7;WHERE 非常重要。没有范围的 UPDATE 可能改到整张表。
DELETE:删除
sql
DELETE FROM messages
WHERE id = 42 AND user_id = 7;既按留言 ID,也按当前用户限制,避免删除别人的留言。
SDK 只是把 SQL 包装成代码
Supabase JavaScript 可能写:
ts
const { data, error } = await supabase
.from('messages')
.select('id, text, created_at')
.eq('user_id', 7)
.order('created_at', { ascending: false })最终仍然表达:从哪张表取哪些列、满足什么条件、怎样排序。
Schema 和 Migration 是什么
Schema
数据库当前结构:有哪些表、列、类型、索引和关系。
Migration
对结构的一次可追踪修改,例如给 messages 新增 is_pinned 列。
不要只在生产数据库网页里手动改结构而不记录,否则团队和新环境不知道怎样得到同样结果。
数据类型为什么重要
text
text 留言文字
integer 数量
boolean 是否置顶
timestamp 创建时间
uuid 唯一标识把时间存成随意字符串,会让排序和时区处理更困难。
权限不是有账号就全部可读
后端或数据库策略应回答:
text
谁可以读取这条记录
谁可以创建
谁可以修改
谁可以删除Supabase 常使用 Row Level Security。前端可使用受限客户端访问,但管理员 Service Role Key 仍然只能留在可信后端。
数据库出错看什么
text
relation does not exist 表名错或迁移没执行
column does not exist 列名错或环境结构不同
duplicate key 唯一字段重复
violates foreign key 指向的关联记录不存在
permission denied 账号或策略不允许操作
connection refused 地址、端口、网络或服务状态问题“数据库没数据”先检查环境
你可能同时有:
text
本地开发数据库
测试数据库
正式生产数据库后端连到测试库,你却在生产控制台查看,就会觉得“保存没有发生”。先确认 DATABASE_URL 指向哪里,注意不要公开真实连接串。
UPDATE messages SET text = '完成' 没有 WHERE,会有什么风险?
答案:它可能修改 messages 表中的每一行。更新和删除前必须明确范围,并在重要环境中先确认查询条件。