跳到主要内容

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 + vectorscale、tencentdb_ai、zhparser / pg_jieba(中文分词)、TimescaleDB、Apache AGE、PL/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 包装为匿名代码块重试。匿名代码块需要 BEGIN ... END 与动态 EXECUTE,因此这里显式使用 LANGUAGE plpgsql;普通函数示例仍默认使用 LANGUAGE SQL:

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

-- 失败时包装为 DO $$ 代码块重试
DO LANGUAGE plpgsql $$
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 LANGUAGE plpgsql $$ 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 LANGUAGE plpgsql $$ BEGIN EXECUTE '...'; END $$ 包装;注意单引号转义。该匿名代码块依赖 BEGIN 和动态 EXECUTE,因此需要 LANGUAGE plpgsql
  • 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 策略同时设置 USING 和 WITH 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)

详细文档入口​

框架快速入门​

下一步​