ToolJet 数据库查询实战指南:GUI 模式、SQL 编辑器、联表与 JSON 查询全解析
【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 🚀项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet
本指南以 ToolJet 开源仓库中 querying-tooljet-db.md 为核心骨架编写。ToolJet Database(以下简称 TJDB)是 ToolJet 内置的托管式 PostgreSQL 数据库,可直接作为数据源在查询面板中使用。读完本文,你将掌握:通过 GUI 模式完成增删改查与聚合分组、在 SQL 编辑器中安全执行 DML 语句、处理外键约束、实现多表 Join、格式化日期时间列,以及查询 JSON 类型字段的完整方法。
ToolJet Database 与其他数据源的使用体验完全一致——只需在查询面板添加一条查询并选择ToolJet Database作为数据源,即可通过GUI 模式(可视化表单)或SQL 编辑器(手写 SQL)两种方式操作数据。后端实现上,GUI 模式通过 TooljetDbDataOperationsService 将操作翻译为 PostgREST 请求,而 SQL 模式则经由 node-sql-parser 做 AST 解析与白名单校验后,直连工作区专属的 PostgreSQL schema 执行,两层路径都值得深入理解。
GUI 模式:可视化操作数据
GUI 模式适合不熟悉 SQL 的用户,也适合把操作绑定到按钮、表单等组件事件上,实现"零代码"数据交互。
- 打开查询面板,点击+Add按钮新建查询,数据源选择ToolJet Database;
- 通过编辑器顶部的切换开关选择GUI mode;
- 选择要查询的表与操作(operation),并根据所选操作填写对应参数;
- 点击Run执行查询。
注意:所选操作必须符合目标表的列约束(如必填字段、数据类型、外键等),否则执行会报错。
GUI 模式下可选操作与后端run()方法中的操作分派一一对应(见 tooljet-db-data-operations.service.ts):list_rows、create_row、update_rows、delete_rows、join_tables、sql_execution,以及面向批量写入的bulk_update_with_primary_key与bulk_upsert_with_primary_key。前端的对应编辑器组件集中在 frontend/src/AppBuilder/QueryManager/QueryEditors/TooljetDatabase/ 目录下(ListRows.jsx、CreateRow.jsx、UpdateRows.jsx、DeleteRows.jsx、JoinTable.jsx等)。
List Rows(列出记录)
返回表中的全部记录,是 GUI 模式下最常用的操作。全部参数均为可选:
- Filter(过滤):选择列、操作符(operator)与值来过滤记录。GUI 上的操作符最终由 PostgrestQueryBuilder 翻译成 PostgREST 语法,支持
eq(等于)、neq(不等于)、gt/gte/lt/lte(大小比较)、like/ilike(模糊匹配)、is(空值判断)、in(在集合内)、contains/containedBy(包含关系)、全文检索textSearch等; - Sort(排序):选择列与排序方向(升序 ascending / 降序 descending),对应后端
order=column.asc形式的查询参数; - Limit(限制):限制返回的记录条数。后端会对 limit 做整数校验(listRows 实现),非整数会抛出 "Limit should be a valid integer" 错误;
- Aggregate(聚合):对一组值执行计算并返回单个结果,可用函数为Count与Sum。注意限制:
- Sum 仅适用于数值列;
- Count 仅统计非空值;
- 后端实现见 buildAggregateAndGroupByQuery,聚合会生成
table_column_sum:column.sum()形式的 PostgREST 别名查询;
- Group By(分组):按指定列的值进行分组。使用约束:
- 必须先添加至少一个聚合条件才能使用;
- 可选择一个或多个分组列;
- 结果按所选列的值组合(唯一组合)分组。
从源码看,过滤条件会先经过hasNullValueInFilters检查:除is操作符外,任何值为null的过滤条件都会被拒绝(tooljet-db-data-operations.service.ts),提示改用IS操作符判断空值——这是 GUI 模式下值得留意的行为细节。
Create Row(创建记录)
向表中插入新记录,支持一次创建单条或多条记录。
必填参数:
- Columns(列):选择要写入的列并填写值;点击+Add column按钮可以追加新的列字段。
后端createRow会将表单中所有非空列组装成{ column: value }对象,并通过 PostgREST 代理以POST方式发送到/api/tooljet-db/proxy/{tableId}(createRow 实现)。
Update Row(更新记录)
更新表中已有记录,支持一次更新单条或多条记录。
必填参数:
- Filter(过滤):通过列 + 操作符 + 值指定要更新的目标记录;
- Columns(列):选择要修改的列并填写新值。
后端对应update_rows,通过buildPostgrestQuery将过滤条件拼进查询串,并以PATCH方式提交更新体(updateRows 实现)。
Delete Row(删除记录)
从表中删除记录,支持一次删除单条或多条记录。
必填参数:
- Filter(过滤):通过列 + 操作符 + 值指定要删除的目标记录;
- Limit(限制):限制删除的记录条数(默认值为 1)。
后端deleteRows有一个安全设计:如果既没有过滤条件也没有 limit,操作会被直接拒绝(返回 "Please provide a where filter or a limit to delete rows"),防止误删整表数据(deleteRows 实现)。GUI 模式要求至少提供过滤条件,而这一后端兜底逻辑同样保护了 SQL 之外的所有调用路径。
SQL 编辑器:直接编写 DML 语句
ToolJet 的SQL 编辑器允许你手写标准 SQL 查询 ToolJet Database,语法基于 PostgreSQL。它当前明确只支持 DML(数据操纵语言)命令:
- 支持的命令:
- SELECT:检索数据;
- INSERT:插入新记录;
- UPDATE:修改已有数据;
- DELETE:删除记录。
- 受限命令:
- DDL(数据定义语言):
CREATE、ALTER、TRUNCATE、DROP、RENAME等一律不允许; - DCL(数据控制语言):
GRANT、REVOKE同样被禁止。
- DDL(数据定义语言):
这一限制并非只停留在文档层面。后端 checkCommandAllowlist 定义了一个白名单['select', 'insert', 'update', 'delete', 'transaction'],任何 SQL 经 node-sql-parser 解析成 AST 后,若type不在白名单内就会抛出 "This SQL functionality is restricted."。也就是说,即便绕过界面直接调用 API,DDL/DCL 也无法执行。
使用步骤
- 在查询面板点击+Add新建查询,选择ToolJet Database;
- 在查询编辑器中选择SQL模式标签页;
- 在编辑器中编写 SQL 语句;
- 点击Run执行。
示例:
SELECT * FROM users WHERE age > 30SQL 模式的底层执行链路
了解 SQL 模式如何执行,有助于你写出更符合平台预期的查询。从 sqlExecution 的实现可以看到完整链路:
- 模式开关检查:
isSQLModeDisabled()返回true时直接拒绝执行。判断逻辑为环境变量TJDB_SQL_MODE_DISABLE === 'true'或当前版本为 Cloud 版(tooljet_db.helper.ts)。自托管(Self-hosted)环境默认启用 SQL 模式; - 建立租户连接:读取工作区的 TJDB 配置,解密数据库密码,并定位工作区专属 schema(格式为
workspace_{organizationId},SQL 模式禁用时回退为public,见 findTenantSchema); - SQL 解析:使用
node-sql-parser的 PostgreSQL 方言解析语句,语法错误会返回 "Syntax error encountered"; - 命令白名单校验:按
checkCommandAllowlist拦截非 DML 语句; - 表存在性验证:
verifyTablesExistInWorkspace会核对 SQL 中引用的每个表是否确实存在于当前工作区,否则抛出 "Table: xxx not found"; - 权限验证:
validateSchemaAndTablePrivileges通过 PostgreSQL 的has_schema_privilege/has_table_privilege检查租户用户对 schema 与表的访问权限; - 表名替换:
parseTableNameInAST将 AST 中的逻辑表名替换为内部表 ID,随后重新生成 SQL 并执行; - 执行完成后销毁连接,错误则统一封装为 ToolJetDatabaseError 返回。
值得注意的是,SQL 模式支持事务(transaction在白名单中),适合需要多语句原子操作的场景。
处理带外键约束的表
ToolJet Database 支持表间外键(Foreign Key)关系。当对带外键约束的表执行创建、更新或删除时,必须保证不违反外键约束:
- 在源表(source table)中创建/更新记录时,外键值必须已存在于目标表中,否则操作失败并返回错误信息;
- 在目标表(target table)中删除记录时,必须确保该记录没有被源表引用,否则同样会失败。
多表 Join(联表查询)
通过Join操作可以将 ToolJet Database 中的两张或多张表连接起来查询。
必填参数
**From(连接来源)**部分包含以下参数:
- Selected Table(选中表):选择要参与连接的主表;
- Type of Join(连接类型):可选
Inner Join(内连接)、Left Join(左连接)、Right Join(右连接)、Full Outer Join(全外连接); - Joining Table(连接表):选择要与主表连接的另一张表。如果选中表与其他表存在外键关系,这些表会以带外键图标的形式列出;
- On(连接条件):分别选择主表列与连接表列作为连接键。目前仅支持
=操作符。若两表存在外键关系,两侧列会自动填充到下拉框中; - AND / OR 条件:每个 Join 下方可通过+Add more按钮添加多个连接条件,条件之间用
AND或OR组合。
可选参数
- Filter(过滤):与List rows操作支持相同的过滤操作,添加条件(列 + 操作符 + 值)即可;
- Sort(排序):选择列与升/降序排序响应;
- Limit(限制):限制返回的记录条数;
- Offset(偏移):跳过前 N 条记录,用于分页(与 Limit 搭配);
- Select(选择列):选择响应中要返回的列,默认返回全部列。
后端实现上,joinTables与前几种操作不同:它不经过 PostgREST 代理,而是将 Join 配置 JSON 交给TooljetDbTableOperationsService的表操作流程生成查询(joinTables 实现)。源码中还会对 From、Select/Aggregate 等必填区块做空值校验,并清理空的过滤/排序/分组条件,因此提交空的 Join 配置会得到明确的 "Input can't be empty" 或区块级错误提示。
将日期时间列映射到 Table 组件
ToolJet Database 中的日期时间列以ISO 8601 格式存储。查询返回时该列默认也以 ISO 8601 格式显示。若想在 Table 组件中以更可读的格式展示,请按以下步骤操作:
- 将查询连接到 Table 组件,打开其属性面板;
- 在Columns部分选中存储日期时间的列;
- 将该列的类型从String改为Date Picker;
- 在日期格式区域,按需打开Enable date(启用日期)与Enable time(启用时间)开关;
- 在**转换(transformation)**字段中:
{{cellValue}}变量保存着 ISO 8601 格式的原始值,先用{{new Date(cellValue)}}将其转换为 Date 对象,再按需格式化。
这种"先new Date()再格式化"的思路充分利用了 ToolJet 内建的双花括号表达式能力,可以搭配任意日期格式化函数实现自定义展示。
查询 JSON 数据类型
ToolJet Database 支持将列设置为JSON 数据类型,用于存储数组、嵌套对象等结构化数据,非常适合保存配置、日志等复杂结构。查询 JSON 列的方式取决于数据结构是扁平还是嵌套。
扁平 JSON 对象(Flat JSON Object)
扁平 JSON 指所有键值对都处于同一层级、没有嵌套的 JSON 结构——每个键唯一,所有值都是直接数据条目。
操作步骤:
- 从查询面板添加ToolJet DB作为数据源;
- 选择GUI 模式(也可选择 SQL 模式);
- 选择表名;
- 从下拉框选择所需操作;
- 点击 Filter 前的+ Add Condition按钮;
- 选择包含 JSON 数据的列、期望的操作符并输入值;
- 在列名下方的输入框中,通过在键名前加
->>来指定要访问的键,例如->>city。
响应示例:
[ { "id":1, "json":{ "id":101, "age":30, "city":"Los Angeles", "name":"Alice Johnson", "email":"alice@example.com", "country":"USA" } } ]嵌套 JSON 对象(Nested JSON Object)
嵌套 JSON 指部分值本身又是 JSON 对象或数组的多层级结构,能够表达元素之间复杂的层次关系。
操作步骤:
- 从查询面板添加ToolJet DB作为数据源;
- 选择GUI 模式(也可选择 SQL 模式);
- 选择表名;
- 从下拉框选择所需操作;
- 点击 Filter 前的+ Add Condition按钮;
- 选择包含 JSON 数据的列、期望的操作符并输入值;
- 在列名下方的输入框中,通过在每个键名前加
->来指定完整的 JSON 路径,例如->user->preferences->settings->notifications->sms->alerts->appointments->cancellations。
技巧:
->用于访问嵌套 JSON 字段(返回 JSON 值),->>用于访问文本(返回文本值)。扁平对象取文本用->>,嵌套对象逐层下钻用->。
响应示例:
[ { "id": 102, "name": "Michael Brown", "age": 25, "email": "michael@example.com", "user": { "preference": { "settings": { "notification": { "sms": { "alert": false } } } } } }, { "id": 104, "name": "David Miller", "age": 35, "email": "david@example.com", "user": { "preference": { "settings": { "notification": { "sms": { "alert": false } } } } } } ]JSON 路径语法与 PostgreSQL 原生的->/->>运算符一致。在 buildPostgrestQuery 中可以看到,过滤条件支持可选的jsonpath字段:当提供了jsonpath时,查询列名会被拼接为column->>city这样的形式(即column + jsonpath),这正是 GUI 界面中输入->>city后底层的处理方式——理解这一点,你就明白为什么 SQL 模式下可以直接写出WHERE contenteditable="false">【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 🚀项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考