如何设置Product.Label.MAXIMAL_CHARACTERS_COUNT适配VARCHAR字节存储限制?
与CHAR类型不同,VARCHAR值以1字节或2字节的长度前缀加数据的形式存储。长度前缀表示值的字节数。若值所需字节数不超过255,列使用1字节长度前缀;若可能超过255,则使用2字节长度前缀。
我们以电商系统为例探讨该问题。以下是产品实体的定义(即使没学过TypeScript也能看懂):
import { FIXED_CHARACTERS_COUNT_IN_UNIVERSAL_UNIQUE_ID__VERSION_4 } from "fundamental-constants"; type Product = { readonly ID: Product.ID; label: string; price__dollars__withoutTaxes: number; }; namespace Product { export type ID = string; export namespace ID { export const TYPE: StringConstructor = String; export const REQUIRED: boolean = true; export const FIXED_CHARACTERS_COUNT: number = FIXED_CHARACTERS_COUNT_IN_UNIVERSAL_UNIQUE_ID__VERSION_4; } export namespace Label { export const TYPE: StringConstructor = String; export const REQUIRED: boolean = true; export const MINIMAL_CHARACTERS_COUNT: number = 2; export const MAXIMAL_CHARACTERS_COUNT: number = 127; } export namespace Price__Dollars__WihtoutTaxes { export const TYPE: NumberConstructor = Number; export const REQUIRED: boolean = true; export const MINIMAL_VALUE: number = 0; } }
前端输入验证、后端请求验证及数据库定义都要遵循上述业务规则,其中产品标签要求包含2至127个字符:

假设上述值从未在前后端硬编码,而是通过引用获取:
<!-- BAD: 最大字符数被硬编码 --> <label for"PRODUCT_LABEL--INPUT">请输入2-127个字符。</label> <input type="text" maxlen="127" id="PRODUCT_LABEL--INPUT" /> <!-- GOOD: 最大字符数通过引用获取(无论使用何种模板引擎)--> <label for"PRODUCT_LABEL--INPUT">请输入 {{ Product.Label.MINIMAL_CHARACTERS_COUNT }}-{{ Product.Label.MAXIMAL_CHARACTERS_COUNT }} 个字符。</label> <input type="text" maxlen="{{ Product.Label.MAXIMAL_CHARACTERS_COUNT }}" id="PRODUCT_LABEL--INPUT" />
定义数据库时(不管用原生SQL、GUI工具还是ORM),我们会把Products表的label列设为VARCHAR类型,最大长度为127个字符(同样是引用Product.Label.MAXIMAL_CHARACTERS_COUNT而非硬编码127)。
此时假设卖家输入了接近127个字符的产品标签,但包含双字节字符。前后端验证都通过了,但服务器尝试把产品保存到数据库时,却触发了label值超出最大长度的异常!
问题
Product.Label.MAXIMAL_CHARACTERS_COUNT应设置为哪个值?(再次说明,该值会被前后端共同引用)
答案
应设置为63。
原因如下:
- 核心冲突:前后端验证的是字符数量,而MySQL的VARCHAR列长度默认限制的是字节数量。双字节字符(如中文、日文等)每个占2字节,若原常量设为127,当输入接近127个双字节字符时,总字节数会远超数据库VARCHAR列的字节限制,触发存储异常。
- 适配存储规则:若保持数据库用该常量作为字节数限制,按最坏情况(所有字符都是双字节)计算,最大允许的字符数为
127 // 2 = 63,此时总字节数为126,刚好不超过127字节的限制,同时兼容单字节字符的存储需求,避免出现前后端验证通过但数据库存储失败的情况。
内容的提问来源于stack exchange,提问作者Takeshi Tokugawa YD
相关产品推荐
相关产品推荐

