第 7 期:告别外挂数据库 — 内置 Data Tables 的 CRUD 实战
Data Tables 是什么?
n8n 2.0 引入的 Data Tables 是一个内置的轻量级持久化存储。你可以把它理解为"工作流专属的简易数据库"——无需配置 PostgreSQL、MongoDB 或 Google Sheets,直接在 n8n 界面中创建表、定义列、读写数据。
graph TB
subgraph "传统方案 (复杂)"
W1[n8n 工作流] -->|"API 调用"| EXT[(外部数据库
PostgreSQL / Airtable)]
EXT -->|"需要配置凭证"| W1
end
subgraph "Data Tables 方案 (简洁)"
W2[n8n 工作流] -->|"原生节点操作"| DT[(内置 Data Tables
零配置、零延迟)]
end
style DT fill:#22c55e,stroke:#16a34a,color:#fff
style EXT fill:#ef4444,stroke:#dc2626,color:#fff适用场景
| 场景 | 示例 | 传统方案 | Data Tables |
|---|---|---|---|
| 防重复执行 | 记录已处理的邮件 ID | Redis / 文件锁 | ✅ 一行表记录 |
| AI Prompt 管理 | 存储不同场景的系统提示词 | 代码硬编码 / 配置文件 | ✅ 表格化管理 |
| 简易 CRM | 跟踪客户状态 | Airtable / Google Sheets | ✅ 原生流转 |
| 统计计数 | 每日处理工单数 | PostgreSQL | ✅ 自增字段 |
创建 Data Table
sequenceDiagram
participant User as 👤 管理员
participant UI as 🖥️ n8n UI
participant DB as 💾 Data Tables
User->>UI: 点击左侧菜单 "Data Tables"
UI->>User: 显示表列表页面
User->>UI: 点击 "Create Table"
User->>UI: 输入表名: "processed_emails"
User->>UI: 添加列:
email_id (Text)
processed_at (DateTime)
status (Text)
UI->>DB: CREATE TABLE processed_emails (...)
DB-->>User: ✅ 表创建成功列类型支持
| 列类型 | 说明 | 示例值 |
|---|---|---|
| Text | 字符串 | "[email protected]" |
| Number | 数值 | 42, 3.14 |
| Boolean | 布尔值 | true, false |
| DateTime | 日期时间 | "2026-04-09T12:00:00Z" |
CRUD 操作详解
Create (创建记录)
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// Data Tables 节点: 插入新记录
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// 节点配置:
// - Operation: "Insert"
// - Table: "processed_emails"
// - Columns to Fill:
// - email_id: {{ $json.messageId }} ← 动态引用上游数据
// - processed_at: {{ $now.toISO() }} ← n8n 内置当前时间函数
// - status: "completed" ← 静态值
// 📤 输出 Item (包含自动生成的 row ID):
// {
// "json": {
// "id": "row_abc123", // 自动生成的行 ID
// "email_id": "msg_12345",
// "processed_at": "2026-04-09T12:00:00.000Z",
// "status": "completed"
// }
// }
Read (查询记录)
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// Data Tables 节点: 读取/查询记录
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// 方式1: 获取全部记录
// - Operation: "Get All Rows"
// - Table: "processed_emails"
// - 可选: Limit (限制返回条数)
// 方式2: 按条件查询
// - Operation: "Get All Rows"
// - Filter: email_id = {{ $json.currentEmailId }}
// - 用途: 检查某封邮件是否已被处理过 (防重复)
// 方式3: 按 ID 获取单条
// - Operation: "Get Row"
// - Row ID: {{ $json.rowId }}
Update (更新记录)
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// Data Tables 节点: 更新现有记录
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// - Operation: "Update Row"
// - Row ID: {{ $json.id }} ← 必须指定行 ID
// - Columns to Update:
// - status: "failed" ← 更新状态
// - processed_at: {{ $now.toISO() }} ← 更新时间
// - retry_count: {{ $json.retry_count + 1 }} ← 递增重试次数
Delete (删除记录)
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// Data Tables 节点: 删除记录
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// - Operation: "Delete Row"
// - Row ID: {{ $json.id }}
//
// ⚠️ 注意: 删除操作不可逆!
// 建议: 使用 "soft delete"(更新 status 字段为 "deleted")替代物理删除
实战:邮件去重处理工作流
graph TB
T[📧 Gmail Trigger
新邮件到达] --> Extract[Set: 提取 messageId]
Extract --> Query[Data Tables: 查询
email_id = messageId]
Query --> Check{If: 查询结果为空?}
Check -->|"✅ 新邮件 (未处理过)"| Process[处理邮件内容]
Check -->|"❌ 已处理过"| Skip[跳过: 不重复执行]
Process --> Record[Data Tables: 插入
记录已处理的 ID]
Record --> Notify[Slack: 通知处理完成]
style Check fill:#f59e0b,stroke:#d97706
style Query fill:#22c55e,stroke:#16a34a,color:#fff
style Record fill:#22c55e,stroke:#16a34a,color:#fff// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// 去重检查的 If 条件表达式
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// Data Tables "Get All Rows" 返回匹配的行数组
// 如果长度为 0,说明这是一封新邮件,之前没有处理过
{{ $json.length === 0 }}
// 或者更安全的写法:
{{ $input.all().length === 0 }}
Data Tables vs 外部数据库
| 维度 | Data Tables | PostgreSQL / MySQL | Google Sheets |
|---|---|---|---|
| 配置复杂度 | ⭐ 零配置 | ⭐⭐⭐⭐ 需额外容器 | ⭐⭐ 需 OAuth |
| 数据容量 | 50MB (默认) | 无限 | 500万单元格 |
| 查询能力 | 基础过滤 | SQL 全功能 | 简单过滤 |
| 并发性能 | 中等 | 高 | 低 |
| 适用阶段 | 原型/轻量生产 | 大规模生产 | 协作与展示 |
💡 选型建议: Data Tables 适合 80% 的轻量级场景。当你发现需要 JOIN 查询、索引优化或数据量超过万级时,再考虑迁移到 PostgreSQL。
下一步
在 Ep 08 中,我们将学习 n8n 与外部世界通信的主力节点——HTTP Request,掌握身份认证、分页轮询与并发控制的关键技巧。