跳到主要内容

PostgreSQL 数据库

体验通知

CloudBase PostgreSQL 数据库已开放体验,欢迎试用。如需创建体验环境,请联系云开发团队。功能正在持续迭代完善,正式发布时间请关注官方公告。

CloudBase 提供了 PostgreSQL 数据库 服务,基于开源 PostgREST 构建,支持完整的 SQL 功能,并通过 表级 GRANT + 行级 RLS Policy 的双层权限模型,实现客户端可直连数据库的安全访问能力。

阅读前建议先了解 PG 模式概述,明确 PostgreSQL 在云开发环境中的整体定位。

其他数据库类型

CloudBase 还提供 文档型数据库MySQL 数据库,可根据业务需求选择合适的数据库类型。

使用 AI 管理关系型数据库和 SQL 操作

PG 模式:以 PostgreSQL 为中心

CloudBase PostgreSQL 数据库不只是"多了一个数据库选项",它代表了一种以 PostgreSQL 为中心的环境形态——PG 模式。在这种形态下,PostgreSQL 不仅承担业务数据存储,还作为统一基础设施,让账号、权限、云存储元数据都落到同一个数据库内:

  • 业务数据:直接存进 PostgreSQL 表,客户端通过 PostgREST 自动暴露的 RESTful API 直连读写
  • 权限模型:以 SQL 表达——表级 GRANT + 行级 RLS Policy 双层校验,请求自带 JWT 由数据库判定权限
  • 账号系统:用户数据存储在 auth schema,可以直接用 SQL 查询、关联到业务表
  • 云存储:文件元数据存储在 storage schema,权限同样用 RLS 表达,与业务数据共享一套权限语言

这意味着开发者只需掌握 SQL 一套表达方式,就能完成数据建模、权限设计、跨域协作。本章后续文档(快速上手、权限管理、RPC 等)默认就在这个上下文中讨论,不再重复 "PG 模式" 这一前缀。

能力速览

能力说明
完整 SQL表、视图、外键、索引、事务、触发器、存储过程、CTE、窗口函数、分区等
PostgREST RESTful API表 / 视图 / RPC 自动暴露为 REST 接口,支持筛选、排序、分页、关联查询、嵌套写入
双层权限GRANT(表级) + RLS Policy(行级),双重锁定
三种访问角色anon / authenticated / service_role
扩展生态pgvector + vectorscaletencentdb_aizhparser / pg_jieba(中文分词)、TimescaleDBApache AGEPL/V8
身份认证联动auth schema + JWT claims 可直接在 SQL 中读取用户身份
云存储联动storage schema 存储对象元数据,可与业务表 JOIN

如何启用

当您创建 CloudBase PostgreSQL 版本环境时,PostgreSQL 数据库会自动启用,无需手动创建或初始化数据库实例。

访问数据库的三种方式

1. 客户端 SDK(直连 + RLS)

最常用的方式。前端通过云开发 SDK 直接读写数据库,由 RLS 完成鉴权:

import cloudbase from '@cloudbase/js-sdk';

// 选择一种鉴权方式:
// (1) 使用 Publishable Key(前端可见):accessKey 传入即可,所有未显式登录的请求都以 anon 身份访问
const app = cloudbase.init({ env: '<env-id>', accessKey: '<Publishable Key>' });

// (2) 或不传 accessKey,前端调用 auth.signInAnonymously() / signInWithPassword() 等显式登录
// const app = cloudbase.init({ env: '<env-id>' });
// await app.auth.signInAnonymously();

const db = app.rdb();

// 查询(RLS 自动按登录用户过滤)
const { data } = await db
.from('todos')
.select('id, title, is_completed')
.eq('is_completed', false);

// 新增(owner_id 由数据库默认值自动填充为 JWT 的 sub)
await db.from('todos').insert({ title: '写一篇文档' });

⚠️ SDK 请求必须携带 JWT(Publishable Key、access_token 或 API Key 三选一)。未提供时网关会拒绝请求。

云开发提供了多种 SDK 供开发者操作 PostgreSQL 数据库:

SDK 类型适用平台
小程序 ClientSDK小程序
JS SDKWeb 浏览器
Node SDKNode.js 环境
HTTP API通用
提示

小程序 ClientSDK 获取 db 实例后,操作 PostgreSQL 数据库语法与 Web JS SDK 一致,具体语法请参考 JS SDK

2. REST API(PostgREST 规范)

适用于无 SDK 场景(其他后端、低代码平台、第三方系统)。

基础端点:

REST: https://<envId>.api.tcloudbasegateway.com/v1/rdb/rest/<table>
Auth: https://<envId>.api.tcloudbasegateway.com/auth/v1

认证头: Authorization: Bearer <Publishable Key | access_token | API Key>

调用示例:

# 列出商品(匿名,使用 Publishable Key)
curl "https://<envId>.api.tcloudbasegateway.com/v1/rdb/rest/products?select=id,name,price&order=price.desc" \
-H "Authorization: Bearer <Publishable Key>"

# 登录后下单(使用 access_token)
curl -X POST "https://<envId>.api.tcloudbasegateway.com/v1/rdb/rest/orders" \
-H "Authorization: Bearer <access_token>" \
-H "Prefer: return=representation" \
-H "Content-Type: application/json" \
-d '{"product_id":1,"quantity":2,"total_price":199.00}'

详见 HTTP API - PostgREST RESTful API

3. 云 API ExecutePGSql(管控面)

云 API ExecutePGSql 是管理员执行任意 SQL 的能力,常用于 CI/CD 自动化部署、数据库 schema 迁移、自动化建表等场景。

基本信息:

字段
接口名称ExecutePGSql
端点tcb.tencentcloudapi.com
Version2018-06-08
Region必填,与环境所在地域一致(如 ap-shanghai
签名方式TC3-HMAC-SHA256

请求体:

{
"EnvId": "<envId>",
"Sql": "<要执行的 SQL>",
"Role": "<可选,以指定的数据库角色执行;常用值:anon / authenticated / service_role>"
}

Role 参数可省略:

  • 省略时:以系统超级管理员角色 cloudbase_admin 执行,具备 SUPERUSER + BYPASSRLS 权限,可执行任意 DDL(包括 CREATE TABLE 等结构变更)和绕过所有 RLS 策略
  • 指定 Role 后(常用值:anon / authenticated / service_role):以指定角色执行 SQL,便于在管控面模拟特定角色调试 RLS 策略,验证策略是否符合预期。注意此时受 GRANT + RLS 约束

关于 DDL 语句:部分 DDL(CREATE / ALTER / DROP / GRANT / REVOKE / TRUNCATE / COMMENT 等)在通过 ExecutePGSql 直接执行时可能返回 InternalError遇到失败时,可将该 DDL 包装为匿名代码块重试:

-- 直接执行可能报错的 DDL
CREATE TABLE public.products (id serial PRIMARY KEY, name text);

-- 失败时包装为 DO $$ 代码块重试
DO $$ BEGIN EXECUTE 'CREATE TABLE public.products (id serial PRIMARY KEY, name text)'; END $$;

SQL 中的单引号 'EXECUTE '...' 内需转义为 ''

Python 示例(使用腾讯云 SDK):

pip install tencentcloud-sdk-python
import json, re
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.tcb.v20180608 import tcb_client, models

SECRET_ID = "<your SecretId>"
SECRET_KEY = "<your SecretKey>"
ENV_ID = "<your envId>"
REGION = "ap-shanghai"

_DDL_KEYWORDS = re.compile(
r"^\s*(CREATE|DROP|ALTER|GRANT|REVOKE|TRUNCATE|COMMENT|"
r"SET|RESET|LOCK|REINDEX|CLUSTER|VACUUM|ANALYZE)\b",
re.IGNORECASE,
)

def _wrap_ddl(sql: str) -> str:
return f"DO $$ BEGIN EXECUTE '{sql.replace(chr(39), chr(39)*2)}'; END $$"

def execute_sql(sql: str, role: str = None, retry_with_wrap: bool = True) -> dict:
cred = credential.Credential(SECRET_ID, SECRET_KEY)
http_profile = HttpProfile()
http_profile.endpoint = "tcb.tencentcloudapi.com"
client_profile = ClientProfile()
client_profile.httpProfile = http_profile
client = tcb_client.TcbClient(cred, REGION, client_profile)

body = {"EnvId": ENV_ID, "Sql": sql}
if role:
body["Role"] = role

try:
req = models.ExecutePGSqlRequest()
req.from_json_string(json.dumps(body))
return json.loads(client.ExecutePGSql(req).to_json_string())
except Exception as e:
# 部分 DDL 直接执行会失败,自动用 DO $$ 包装重试
if retry_with_wrap and _DDL_KEYWORDS.match(sql.strip()):
return execute_sql(_wrap_ddl(sql), role=role, retry_with_wrap=False)
raise

# DML 直接执行
print(execute_sql("SELECT 1"))

# DDL 自动重试(失败时用 DO $$ 包装)
execute_sql("""
CREATE TABLE public.products (
id serial PRIMARY KEY,
name text NOT NULL,
price numeric(10,2) NOT NULL
)
""")
execute_sql("ALTER TABLE public.products ENABLE ROW LEVEL SECURITY")
execute_sql("GRANT SELECT ON public.products TO anon")
使用限制
  • 每次 API 调用只能执行一条 SQL,不能用分号拼接多条;批量执行请按行/分号拆分后逐条调用
  • DDL 失败时使用 DO $$ BEGIN EXECUTE '...'; END $$ 包装;注意单引号转义
  • API 偶尔可能因后端短暂故障返回 InternalError,建议加入指数退避重试
  • 本接口属于管理员操作,权限高,仅在后端使用,不要暴露 SecretKey

双层权限模型

数据库权限由两层组成,请求两层都通过才会成功

请求 → JWT 解析 → 第一层:表级 GRANT(能执行哪些操作)
→ 第二层:RLS Policy(能访问哪些行)→ 返回结果

第一层:GRANT

-- 示例:匿名可读,登录用户可读写,管理员全部权限
GRANT SELECT ON public.orders TO anon;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.orders TO authenticated;
GRANT ALL ON public.orders TO service_role;

-- 使用 serial 主键时,还需授予序列权限
GRANT USAGE, SELECT ON SEQUENCE public.orders_id_seq TO authenticated;

第二层:RLS Policy

ALTER TABLE public.orders ENABLE ROW LEVEL SECURITY;

-- 匿名用户可见:仅公开订单(示例)
CREATE POLICY orders_anon_select ON public.orders
FOR SELECT TO anon
USING (is_public = true);

-- 登录用户可见:仅自己的
CREATE POLICY orders_auth_select ON public.orders
FOR SELECT TO authenticated
USING (buyer_id = (current_setting('request.jwt.claims', true)::json->>'sub'));

service_role 由于具备 BYPASSRLS,自动绕过 RLS Policy。只要在第一层 GRANT 了对应权限即可,无需为它写 Policy。

四种常见 RLS 模式

以下四种模式覆盖绝大多数业务场景,可以直接复用(命名沿袭传统模式云存储的同名权限模式,便于心智迁移):

模式典型场景权限效果
READONLY博客文章、产品目录所有人可读,仅创建者可写
PRIVATE私人笔记、个人设置仅创建者可读写(用户间完全隔离)
ADMINWRITE公告、系统配置所有人可读,仅管理员可写
ADMINONLY审计日志、后台配置仅管理员可读写

复杂场景(多租户 SaaS 协作、社交可见性、可见性跟随帖子等)可通过子查询 / EXISTS / OR 条件灵活表达。

详见 RLS 权限模式库基础权限管理

查询表达式(PostgREST 约定)

REST API 支持丰富的查询参数:

# 过滤
?category=eq.电子产品 # 精确匹配
?price=gte.1000&price=lte.5000 # 范围
?name=like.*iPhone* # 模糊
?status=in.(pending,paid) # IN

# 排序
?order=price.desc
?order=category.asc,price.desc

# 分页
?limit=10&offset=0

# 列选择
?select=id,name,price

# 关联查询(基于外键自动推断)
?select=*,products(name,price) # 订单 + 关联商品

常见报错处理

xxx.rdb is not a function

报错原因:当前使用的 CloudBase SDK 版本过旧,不支持 PostgreSQL 数据库操作。

解决方法:更新当前 SDK 到最新版本。

Generating default gateway base url failed: env not found

报错原因:微信基础库版本过低,不支持云开发 PostgreSQL 数据库功能。

解决方法:更新微信基础库到 3.8.9 版本以上。

在微信开发者工具中设置最低基础库版本:

  1. 打开「项目详情」
  2. 在「本地设置」中,将「调试基础库」设置为 3.8.9 或更高版本
  3. 在「基本信息」中,将「最低基础库版本」设置为 3.8.9 或更高版本
注意

更新基础库版本后,请确保小程序在低版本微信中的兼容性处理,或在小程序管理后台设置最低版本要求。

最佳实践与常见陷阱

推荐做法:

  1. 业务表归属字段使用 DEFAULT 绑定 JWT sub,禁止前端传入
  2. UPDATE 策略同时设置 USINGWITH CHECK
  3. GRANT + RLS 双重锁定:不希望某角色写就在 GRANT 层拦截
  4. 使用 serial / bigserial 主键时别忘记授予 SEQUENCE 的权限
  5. 清理测试数据时注意外键顺序:先删子表再删父表

常见陷阱:

  1. 启用 RLS 后忘记建 Policy → 所有非 service_role 请求都被拒
  2. 建了 Policy 但没 GRANT → 表级权限不通过
  3. 前端暴露 API Key → service_role BYPASSRLS,所有数据暴露
  4. UPDATE 只写了 USING 未写 WITH CHECK → 用户可以通过 UPDATE 篡改归属字段"窃取"数据
  5. 对匿名用户授予过多权限(除非有强诉求,anon 只给 SELECT

详细文档入口

框架快速入门

下一步