ToolJet Database 主键完全指南:单字段与复合主键的创建、修改和删除
【免费下载链接】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
主键(Primary Key)是 ToolJet Database 中唯一标识每条记录、保证数据完整性并支撑高效查询与索引的基石。本文以 ToolJet Database 的官方主键文档为主体,完整讲解单字段主键与复合主键的创建流程、约束与限制,以及主键的修改、删除操作,并结合仓库源码(前端编辑器与后端表操作服务)深入剖析主键在底层是如何被校验和执行的。读完本文,你将能在 ToolJet Database 编辑器中熟练设计符合业务需求的主键方案,并理解为什么某些列不能设为主键、为什么被外键引用的表不能随意修改主键。
ToolJet Database 中主键的定位
ToolJet Database 是 ToolJet 内置的托管式数据库,无需额外搭建即可在应用内直接维护数据表(见 tooljet-database.md)。在官方功能清单中,主键被明确列为一项核心能力:
- 唯一标识每条记录,确保数据完整性;
- 支撑高效的查询与索引;
- 作为外键关系的参照基础,与其他表建立关联并维护引用完整性。
从数据模型层面看,ToolJet Database 底层基于 PostgreSQL(通过 PostgREST 暴露为 RESTful API)。当你通过数据库编辑器创建一张新表时,系统会自动生成一个名为id、数据类型为serial的列并默认将其设为主键。serial类型用于生成连续的整数序列,天然适合作为表的自增主键(参见 />
关于新建表时列配置抽屉中的Primary Key选项,database-editor.md 做了补充说明:该复选框可以将列设为主键,且允许多列同时勾选以构成复合主键。因此单字段主键本质上就是复合主键在列数为 1 时的特例。
约束(Constraints)
- 主键列不能包含 NULL 值;
- 主键列的值在所有行中必须唯一。
这两条约束共同保证了主键可以作为表中每一条记录的唯一标识符,也是外键引用该列时引用完整性得以成立的前提。
限制(Limitations)
- 每张表必须至少有一个主键:这是 ToolJet Database 的硬性要求,因此你不能把一张表的主键全部取消而不指定新的主键列;
- 主键列不能使用 Boolean 数据类型。
为什么 Boolean 不能设为主键
Boolean 类型只有true、false(以及null)三种取值,最多无法提供超过两个不同的非空值,显然无法唯一标识大量记录。这一点在数据类型的约束兼容性表中得到了系统化体现:根据>数据类型
从前端源码也可以印证这一限制:在 ColumnForm.jsx 中,当所选数据类型为boolean时会提示"Foreign key relation cannot be created for boolean type column",而主键的约束同样对 Boolean 关闭。也就是说,主键候选列只能从上表允许的数值与字符串类型中选择。
创建复合主键
当单一列不足以唯一标识一条记录时,ToolJet Database 允许你将多个列组合成一个复合主键(Composite Primary Key),通过多列取值的组合来唯一标识每条记录,为数据建模提供更大的灵活性与控制力。
操作步骤
- 创建或编辑一张已有的表;
- 勾选多个列的 Primary 复选框,将它们共同设为主键;
- 系统会自动为这些列添加主键约束(组合成一个复合主键);
- 点击Save changes(编辑表)或Create(新建表)按钮提交。
约束(Constraints)
- 复合主键中的任何一列都不能包含 NULL 值;
- 所有复合主键列的值组合,在每一行中必须唯一。
注意与单字段主键的差异:复合主键的唯一性是基于列组合判定的,例如(a, b)为复合主键时,(1, 'x')与(1, 'y')可以共存,但(1, 'x')不能出现两次。
限制(Limitation)
- 复合主键中的列同样不能是 Boolean 数据类型。
源码中的复合主键处理
后端表操作服务在多个环节对复合主键进行了显式校验。例如在 tooljet-db-table-operations.service.ts 中,创建外键时会抛出'Foreign key cannot be created as the referenced column is in the composite primary key.'——即外键不能引用目标表中属于复合主键组成部分的列,这是复合主键带来的一个关键联动限制。此外,在 tooljet-db-table-operations.service.ts 附近,服务会遍历列约束并收集所有is_primary_key为真的列到pkColumnList,用于后续的删除/更新/插入操作中定位记录,这正是"复合主键参与数据行定位"的实现证据。
修改主键
表创建完成后,你依然可以重新指定主键列,前提是新选定的列必须满足主键约束:如果该列已经包含数据,则现有值必须满足"非空且唯一"的要求。此外有一个重要的联动限制:
如果目标表的主键正被其他源表作为外键引用,则不能更新或修改该主键。
这是因为修改被引用的主键会破坏引用完整性(Referential Integrity)——源表中的外键值将无法继续对应到有效记录。
操作步骤
- 编辑一张已有的表;
- 勾选你希望设为新主键的列的Primary复选框;
- 系统自动为该列添加主键约束;
- 取消勾选原主键列的 Primary 复选框(原列的约束仍然存在,但不再是主键);
- 点击Save changes保存。
从源码层面看,这一流程在后端会被解析为"列约束变更":在 tooljet-db-table-operations.service.ts 中,服务会读取新旧列的constraints_type.is_primary_key标志,并通过ALTER TABLE ... DROP CONSTRAINT/ADD CONSTRAINT之类的 DDL 同步到 PostgreSQL,同时保证serial类型的自动生成逻辑不被破坏。值得注意的是,主键列会自动隐式具备唯一性,因此当某列既设为主键又勾选了 Unique 时,服务端在生成约束时会用isUnique: is_unique && !is_primary_key_column做去重处理(见同文件 L558-L559),避免重复添加冗余的唯一约束。
删除主键
通过Edit Table面板可以删除已有的主键列。由于每张表必须至少保留一个主键,因此删除流程要求你先指定替代主键:
操作步骤
- 编辑一张已有的表;
- 先选择另一列作为新的主键,勾选其 Primary 复选框;
- 确认新主键生效后,回到原来的主键列;
- 取消勾选原主键列的 Primary 复选框,移除其主键状态;
- 移除主键约束后,即可将该列从表中删除。
同样地,如果目标表的主键正被用作任何源表的外键,则不能删除该主键。这条限制与"修改主键"的限制一脉相承,目的都是防止外键引用悬空、维护引用完整性。
与之呼应,table-operations.md 的 Delete Column 一节也明确指出:"如果某列正被用作主键,则不能删除该列;必须先移除该列的主键约束后再删除。"换言之,删除主键列是"先解除主键约束、再删列"的两步操作,UI 上会阻止你直接删除仍是主键的列。
主键与外键、批量上传等机制的联动
理解主键的价值,需要把它放在 ToolJet Database 的整体约束体系中看:
- 主键是外键的引用目标:外键要求源表列的值必须与目标表的主键列(或唯一约束列)的值匹配(见 database-editor.md 的 Column Constraints 一节)。因此被引用的主键不能随意修改或删除,详见 foreign-key.md。
- 批量上传依赖主键做去重与更新:在 tooljet-db-bulk-upload.service.ts 中,CSV 批量导入会基于主键执行插入/更新逻辑:若 CSV 中出现重复主键,会抛出
Duplicate primary key found on row[...](L112);若数据未提供serial类型主键列的值,则走普通INSERT让 PostgreSQL 自动生成(L512-L524),反之则走UPSERT更新已有记录。这正是"主键唯一标识记录"在数据写入链路中的直接应用。 - 行级操作依赖主键定位记录:数据操作服务在更新/删除记录时要求指定主键列,否则会返回
'No primary key columns specified'错误(见 tooljet-db-data-operations.service.ts),说明主键是 ToolJet Database 进行行级寻址的基础。
主键设计实践建议
结合本文的约束与联动规则,在设计 ToolJet Database 表结构时可以遵循以下原则:
- 优先保留默认的
serial自增主键:新建表默认生成的id列开箱即用,适合大多数业务表; - 需要业务自然键时,选择
varchar、int、bigint或float列,避开boolean、date with time、jsonb(它们不支持主键约束); - 只有单列确实无法唯一标识记录时,才使用复合主键,并牢记"外键不能引用复合主键列"的限制,若后续需要被其他表引用,应另行设计唯一约束列;
- 修改或删除主键前,先排查外键引用:凡是被外键引用的主键,必须先将外键关系移除或改用其他引用目标,才能变更主键;
- 利用 Export Schema 保留表结构备份:在调整主键等结构前,可先通过表的 kebab 菜单导出 JSON 格式的表结构(见 table-operations.md 的 Export Schema 一节),以便回滚或迁移。
小结
主键是 ToolJet Database 数据建模的枢纽:新建表默认自带serial类型的id主键,编辑器通过一个Primary复选框即可完成单字段主键、复合主键的创建以及主键的修改与删除;约束层面要求主键列非空、唯一、禁用 Boolean 类型,且每表至少保留一个主键;与外键、批量上传、行级操作的联动规则则在服务端源码中得到了完整实现与校验。掌握这些规则,你就能在 ToolJet 中设计出既灵活又严谨的数据结构。
【免费下载链接】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),仅供参考