第 2 章 · PostgreSQL 数据库与数据表设计 章节摘要:Supabase 的核心是一套完整的 PostgreSQL 数据库,数据表设计是所有应用的地基。本章讲解关系型数据模型的基本概念、PostgreSQL 的常用数据类型、约束与主外键的作用,以及一对一、一对多、多对多等表关系的设计方法。掌握本章,你就能为任何业务场景设计出结构清晰、可扩展、数据完整的关系型数据模型,为后续的身份认证、行级安全与实时订阅等能力提供坚实的数据底座。
章节摘要:Supabase 的核心是一套完整的 PostgreSQL 数据库,数据表设计是所有应用的地基。本章讲解关系型数据模型的基本概念、PostgreSQL 的常用数据类型、约束与主外键的作用,以及一对一、一对多、多对多等表关系的设计方法。掌握本章,你就能为任何业务场景设计出结构清晰、可扩展、数据完整的关系型数据模型,为后续的身份认证、行级安全与实时订阅等能力提供坚实的数据底座。
阅读本章后,你将能够:
数据库设计决定了应用的可扩展性与数据质量。好的设计让查询高效、关系清晰、不易产生脏数据;糟糕的设计则会在数据量增长后带来各种隐患。本章围绕「如何把现实业务映射成表结构」展开,下面的 ER 示意图展示了一个典型应用中表与表之间通过主外键建立关联的方式。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 440" font-family="Microsoft YaHei, Arial, sans-serif"> <rect width="760" height="440" fill="#f6f8fb"/> <text x="380" y="34" text-anchor="middle" font-size="20" font-weight="700" fill="#1f2937">表与关系 ER 示意图(一对多 / 多对多)</text> <!-- 用户表 --> <g> <rect x="40" y="70" width="180" height="150" rx="8" fill="#ffffff" stroke="#3ecf8e" stroke-width="1.6"/> <rect x="40" y="70" width="180" height="30" rx="8" fill="#3ecf8e"/> <text x="130" y="90" text-anchor="middle" font-size="14" font-weight="700" fill="#ffffff">users 用户表</text> <text x="56" y="120" font-size="12" fill="#1f2937">🔑 id (UUID, 主键)</text> <text x="56" y="142" font-size="12" fill="#1f2937">email (文本, 唯一)</text> <text x="56" y="164" font-size="12" fill="#1f2937">name (文本)</text> <text x="56" y="186" font-size="12" fill="#1f2937">created_at (时间)</text> <text x="56" y="208" font-size="12" fill="#6b7280">…</text> </g> <!-- 订单表 --> <g> <rect x="290" y="70" width="180" height="170" rx="8" fill="#ffffff" stroke="#3ecf8e" stroke-width="1.6"/> <rect x="290" y="70" width="180" height="30" rx="8" fill="#3ecf8e"/> <text x="380" y="90" text-anchor="middle" font-size="14" font-weight="700" fill="#ffffff">orders 订单表</text> <text x="306" y="120" font-size="12" fill="#1f2937">🔑 id (UUID, 主键)</text> <text x="306" y="142" font-size="12" fill="#1f2937">🔗 user_id (外键)</text> <text x="306" y="164" font-size="12" fill="#1f2937">amount (数值)</text> <text x="306" y="186" font-size="12" fill="#1f2937">status (文本)</text> <text x="306" y="208" font-size="12" fill="#1f2937">created_at (时间)</text> <text x="306" y="230" font-size="12" fill="#6b7280">…</text> </g> <!-- 中间表:订单-商品 --> <g> <rect x="540" y="70" width="180" height="150" rx="8" fill="#ffffff" stroke="#3ecf8e" stroke-width="1.6"/> <rect x="540" y="70" width="180" height="30" rx="8" fill="#3ecf8e"/> <text x="630" y="90" text-anchor="middle" font-size="13" font-weight="700" fill="#ffffff">order_items 订单项</text> <text x="556" y="120" font-size="12" fill="#1f2937">🔑 id (UUID, 主键)</text> <text x="556" y="142" font-size="12" fill="#1f2937">🔗 order_id (外键)</text> <text x="556" y="164" font-size="12" fill="#1f2937">🔗 product_id (外键)</text> <text x="556" y="186" font-size="12" fill="#1f2937">quantity (整数)</text> <text x="556" y="208" font-size="12" fill="#6b7280">…</text> </g> <!-- 商品表 --> <g> <rect x="540" y="270" width="180" height="130" rx="8" fill="#ffffff" stroke="#3ecf8e" stroke-width="1.6"/> <rect x="540" y="270" width="180" height="30" rx="8" fill="#3ecf8e"/> <text x="630" y="290" text-anchor="middle" font-size="14" font-weight="700" fill="#ffffff">products 商品表</text> <text x="556" y="320" font-size="12" fill="#1f2937">🔑 id (UUID, 主键)</text> <text x="556" y="342" font-size="12" fill="#1f2937">name (文本)</text> <text x="556" y="364" font-size="12" fill="#1f2937">price (数值)</text> <text x="556" y="386" font-size="12" fill="#6b7280">…</text> </g> <!-- 关系连线 --> <g stroke="#6b7280" stroke-width="1.6" fill="none"> <!-- users 1 - N orders --> <path d="M 220 145 L 290 145" marker-end="url(#arrow)" marker-start="url(#arrow)"/> <text x="255" y="138" text-anchor="middle" font-size="11" fill="#374151">一对多</text> <!-- orders 1 - N order_items --> <path d="M 470 150 L 540 150" marker-end="url(#arrow)" marker-start="url(#arrow)"/> <text x="505" y="143" text-anchor="middle" font-size="11" fill="#374151">一对多</text> <!-- products 1 - N order_items --> <path d="M 630 270 L 630 220" marker-end="url(#arrow)" marker-start="url(#arrow)"/> <text x="650" y="248" font-size="11" fill="#374151">一对多</text> </g> <defs> <marker id="arrow" markerWidth="9" markerHeight="9" refX="6" refY="3" orient="auto"> <path d="M0,0 L6,3 L0,6 z" fill="#6b7280"/> </marker> </defs> <text x="380" y="420" text-anchor="middle" font-size="12" fill="#6b7280">users 与 orders 为一对多;orders 与 products 通过 order_items 联结表实现多对多</text> </svg>
本章按「概念 → 类型 → 约束 → 关系」的顺序展开:
建议按顺序学习,每一节都建立在前一节的概念之上。
本章与第 3 章(SQL 操作)共同构成数据层:先有合理的设计,才能高效地查询。同时,表结构也是第 4 章(Auth 用户表)、第 5 章(RLS 作用对象)、第 6 章(Realtime 监听对象)和第 9 章(向量列)的基础,可以说贯穿了整个 Supabase 体系。