如果您一直在通过向表单添加自定义字段来自定义 ERPNext,您可能会遇到以下情况:
- 当您尝试提交单据时,新添加的自定义字段会导致服务器错误,或者
- 添加字段后,ERPNext 拒绝保存。
本文解释了为什么会发生这种情况,并引导您通过实用的方法来解决它——无需数据库知识。
这些错误意味着什么
当您达到限制时,ERPNext 可能会在屏幕上显示以下两种错误之一:
错误 1:“INSERT INTO 中的未知列”
当您在添加新的自定义字段后提交表单时,会出现此错误。ERPNext 试图保存数据库中尚不存在的列的数据,这表明底层表已达到其结构限制,并且新字段无法正确注册。
错误 2:“行大小过大”
这个错误更直接。数据库表的行已超过其允许的最大大小65,535 字节。
为什么会发生这种情况?
在 ERPNext(和 Frappe)中,每个表单(称为DocType)都对应数据库中的一个表。该表单上的每个字段都是该表中的一个列。
可以把它想象成一个电子表格:每一行在空间耗尽之前只能容纳有限数量的列。MySQL(ERPNext 使用的数据库)对每个表行强制执行 65,535 字节的硬性行大小限制。MySQL 在技术上每个表最多支持 4,096 列,但在实践中,行大小限制会首先被达到。
以下是一个具体示例,说明该限制被达到的速度有多快:
- 数据、链接、选择、动态链接、密码和只读类型的字段在数据库中存储为
VARCHAR(140) 列。
- 使用
utf8mb3 字符集的 VARCHAR(140) 列,每个值最多分配 420 字节(140 个字符 × 每个字符 3 字节)。
- 这意味着一个表在达到限制之前,最多只能容纳大约 65,535 ÷ 420 = ~156 个这样的列。
相关的表单/文档类型已经包含许多内置字段。安装自定义应用程序会添加更多字段。一旦接近这个上限,即使再添加一个自定义字段也可能使其超出限制,从而导致上面显示的提交错误。
功能性解决方案
有几种方法可以解决这个问题,从快速修复到结构性更改。如果您只需要多一点空间,请从快速修复开始;如果您需要添加更多字段,请选择结构性方案。
修复 1:创建一个单独的 DocType 并将其链接到主 DocType
当您需要添加一组不同的相关字段(例如,特定部门、流程或合规性要求的字段)时,这是最佳的长期方法。
步骤:
- 转到自定义 > DocType(或在搜索栏中搜索“新建 DocType”)。
- 创建一个包含您所需所有字段的新 DocType。
- 在新的 DocType 中,添加一个指向主 DocType(您原本想在其中添加所有字段的 DocType)的链接字段,这会将每条记录与其父级“库存录入”关联起来。
- (可选)在“库存录入”的自定义表单上添加一个链接字段,指回您的新 DocType,以便于导航。
为什么有效: 您的新 DocType 拥有自己独立的数据库表,具有自己的行大小预算,完全独立于“库存录入”的表。
修复 2:创建一个子表并将其添加到“库存录入”
当您的额外字段代表重复的数据行时,此方法效果最佳。例如,质量检查清单或项目列表,类似于“库存录入”中“项目”表的工作方式。
步骤:
- 转到自定义 > DocType 并创建一个新的 DocType。启用“是子表”复选框。
- 将所有字段作为列添加到此子表中。
- 转到自定义表单 > 库存录入。
- 添加一个类型为表的新字段,并将其选项设置为您新创建的子 DocType。
为什么有效: 子表存储在其自己的独立数据库表中,完全规避了父表单的行大小限制。
技术性修复
修复 1:将某些字段转换为基于文本的类型
文本、小文本、文本编辑器或代码类型的字段在 MySQL 中以不同方式存储(作为 TEXT 或 BLOB 列)。与 VARCHAR 列不同,它们的内容存储在主要行之外——它们在行本身中仅占用 9–12 字节,而不是最多 420 字节。
该怎么做: 在自定义表单中,找到当前使用“数据”、“链接”或“选择”等类型且值较长或不需要进行筛选/排序的任何自定义字段,并将其字段类型替换为小文本或文本。每次转换都会释放大量行空间,并允许添加更多字段。
修复2:减少现有字段的“长度”属性
创建数据类型自定义字段时,ERPNext 默认设置长度为140。这直接控制了 MySQL 为该列分配的字节数。对于输入内容较短的字段(例如,一个永远不会超过20个字符的代码字段),减少其长度可以按比例释放空间。
操作方法:在自定义表单中,打开每个自定义字段的设置,将长度值降低到实际需要的数值。例如,将长度从140改为20,该列的分配空间将从420字节减少到仅60字节。
修复3:使用 Trim Tables 移除未使用的自定义字段
从自定义表单中删除的自定义字段不会自动从数据库表中移除——它们的列仍然存在,继续占用行空间。
如果您确定不再需要某些旧自定义字段中的数据,可以通过运行 trim-tables bench 命令永久删除这些列:
https://frappeframework.com/docs/user/en/bench/reference/trim-tables
注意:此操作不可逆。这些列中存储的任何数据都将被永久删除。在运行此命令之前,请务必进行数据库备份。
选择正确的解决方案
| 您的情况 |
推荐方法 |
| 您需要许多新的单值字段(表单中的一个值) |
创建单独的链接文档类型 |
| 您需要每个库存条目中重复的数据行 |
创建子表 |
| 少数几个字段使您超出限制 |
将某些字段转换为小文本/文本,或减少字段长度 |
| 您已删除自定义字段,但其列仍然存在 |
运行 trim-tables 以回收空间 |