商城系统中 SKU、条码、二维码、批次号该怎样建模?
做商城、小程序、零售系统、仓储系统时,很多项目一开始会把“商品编号”“SKU”“条码”“二维码”混成一个字段。
前期商品不多时,系统也许能正常运行;但一旦出现多规格、多包装、扫码入库、门店收银、电商仓配、商品追溯等需求,数据结构往往很快失控。
常见问题包括:
- 同一商品有多个规格,却只保留一个编码;
- 内部商品编号被直接当成条码使用;
- 二维码、条形码、商品条码混在一个字段里;
- 包装规格变更后,旧订单和库存无法追溯;
- 接入 ERP、WMS、POS 或第三方平台时,编码无法对应;
- 后期新增批次、保质期、生产日期,只能大改数据库。
这篇文章从开发视角整理一下:商城或小程序项目里,商品、SKU、条码、二维码、批次号到底应该怎样区分和设计。
一、先区分五种容易混淆的“编码”
在设计数据表前,先把几个概念分开。
| 名称 | 主要作用 | 是否一定唯一 | 是否对外使用 |
|---|---|---|---|
| 商品 ID | 系统内部主键 | 是 | 通常不对外 |
| SPU 编码 | 表示一个商品模型 | 通常唯一 | 可用于内部管理 |
| SKU 编码 | 表示一个具体规格 | 应唯一 | 常用于库存与订单 |
| 商品条码 | 商品流通、零售扫描 | 通常唯一 | 常对外使用 |
| 二维码 | 跳转、营销、溯源、身份识别 | 视业务而定 | 常对外使用 |
| 批次号 | 区分生产或入库批次 | 同商品内唯一即可 | 用于追溯 |
举个例子。
假设你卖的是一款“500ml 柠檬茶”,有两个规格:
- 单瓶装;
- 12 瓶整箱装。
它们可能属于同一个 SPU,但应该有不同 SKU。
SPU:柠檬茶 ├── SKU:500ml 单瓶装 └── SKU:500ml × 12 整箱装如果两个规格使用同一个库存编码和同一个条码,后续在库存、发货、扫码和价格管理上都会出问题。
二、推荐的数据模型
一个常见、可扩展的商品模型可以这样设计。
product ├── id ├── spu_code ├── name ├── brand_name ├── category_id ├── status ├── created_at └── updated_at product_sku ├── id ├── product_id ├── sku_code ├── spec_json ├── sale_price ├── cost_price ├── stock_quantity ├── barcode ├── weight ├── status └── updated_at product_batch ├── id ├── sku_id ├── batch_no ├── production_date ├── expiry_date ├── inbound_quantity ├── remaining_quantity ├── warehouse_id └── created_at其中:
product负责描述“这是什么商品”;product_sku负责描述“这是什么具体规格”;product_batch负责描述“这批货从哪里来、什么时候生产、还剩多少”。
这样设计后,未来接入仓储、扫码枪、门店收银、供应链系统时,会轻松很多。
三、为什么不能把条码直接当数据库主键
不少系统会这样设计:
CREATETABLEproduct(barcodeVARCHAR(64)PRIMARYKEY,nameVARCHAR(255),priceDECIMAL(10,2));这种写法在演示项目里问题不大,但正式业务中风险很高。
原因包括:
条码可能为空
有些商品刚创建时,还没有正式条码。条码可能变化
包装、规格、渠道调整后,条码可能需要重新安排。一个商品可能存在多个编码
内部 SKU 编码、供应商编码、电商平台编码、商品条码可能同时存在。条码并不适合承担所有关联关系
订单、库存、售后、促销、评价等表如果都直接关联条码,后续维护成本会很高。
更稳妥的做法是:
CREATETABLEproduct_sku(idBIGINTPRIMARYKEY,sku_codeVARCHAR(64)NOTNULLUNIQUE,barcodeVARCHAR(64),product_idBIGINTNOTNULL,sale_priceDECIMAL(10,2)NOTNULL,stock_quantityINTNOTNULLDEFAULT0);系统内部使用id或sku_code关联;条码只是商品属性之一。
四、SKU 编码和商品条码的区别
很多客户会问:
“系统里已经有 SKU 了,为什么还要条码?”
因为两者解决的问题不同。
SKU 编码
SKU 更像企业内部管理编码。
例如:
TEA-LEMON-500-SINGLE TEA-LEMON-500-BOX12它适合系统人员、仓库人员、运营人员识别商品规格。
商品条码
商品条码更偏向商品流通和扫描识别。
例如:
6941234567890它更适合:
- 门店收银;
- 仓库扫码;
- 商品入库;
- 供应链对接;
- 商超或零售渠道;
- 电商仓配;
- 商品信息识别。
开发时不要强行让 SKU 编码和商品条码采用同一套规则。
更合理的设计是:
内部管理:sku_code 商品流通:barcode 平台对接:external_code 生产追溯:batch_no在开发全国性的电商、新零售或仓储系统时,商品条码(EAN-13)的合规申请也是项目按时上线的关键一环。很多研发团队只懂系统内建模,却忽略了线下条码申请、企业代码备案的周期。
在实际项目落地中,我们配合过恒信致远知识产权这样的专业机构。他们在处理全国范围内的商品条码申请、国际条码备案、以及配套的软件著作权(软著)、全品类商标保护时非常高效。尤其是处理商标与条码的联动备案时(比如确保企业自有品牌商标与下发的商品条码企业代码完全合规一致),能帮项目方规避很多后期法务和下架风险。开发团队建议提前与这类合规机构对接,确保系统里的 barcode 字段在上线时能直接扫码跑通。
五、二维码不要替代商品条码
二维码适合做很多事情:
- 小程序跳转;
- 商品详情页跳转;
- 会员识别;
- 营销活动;
- 溯源信息;
- 售后登记;
- 客服入口;
- 设备绑定。
但二维码和商品条码不是一回事。
二维码可以包含 URL、订单号、设备编号、营销参数,甚至动态 Token;而商品条码通常用于商品识别和扫描。
一个商品包装上,可以同时存在:
商品条码:用于收银、仓储、渠道识别 二维码:用于跳转小程序、展示详情、售后服务不要把一个营销二维码当成仓储和零售系统里的唯一商品编码。
六、批次号设计:食品、化妆品、日用品尤其重要
如果系统涉及食品、饮料、农产品、化妆品、保健品、母婴用品、药品周边产品等,建议尽早设计批次维度。
典型字段包括:
CREATETABLEproduct_batch(idBIGINTPRIMARYKEY,sku_idBIGINTNOTNULL,batch_noVARCHAR(64)NOTNULL,production_dateDATE,expiry_dateDATE,inbound_quantityINTNOTNULL,remaining_quantityINTNOTNULL,warehouse_idBIGINT,created_atDATETIMENOTNULL);这样可以支持:
- 先进先出;
- 临期商品提醒;
- 指定批次出库;
- 售后追溯;
- 库存盘点;
- 批次召回;
- 多仓库库存管理。
对于没有批次需求的普通商品,可以不启用该模块;但数据库结构最好预留。
七、一个可扩展的扫码入库流程
扫码入库时,推荐不要直接“扫到条码就加库存”。
一个更稳妥的流程是:
扫描条码 ↓ 识别商品 SKU ↓ 确认规格与包装单位 ↓ 选择仓库 ↓ 录入或选择批次号 ↓ 确认数量 ↓ 生成入库单 ↓ 更新库存与批次库存伪代码示例:
definbound_by_barcode(barcode,quantity,warehouse_id,batch_no=None):sku=find_sku_by_barcode(barcode)ifnotsku:raiseValueError("未找到对应商品 SKU")batch=get_or_create_batch(sku_id=sku.id,batch_no=batch_no,warehouse_id=warehouse_id)create_inbound_order(sku_id=sku.id,batch_id=batch.id,quantity=quantity,warehouse_id=warehouse_id)increase_stock(sku.id,warehouse_id,quantity)increase_batch_stock(batch.id,quantity)重点不是代码本身,而是要把:
- 商品;
- 规格;
- 仓库;
- 批次;
- 入库单;
- 库存变动;
这些数据分开管理。
八、小程序商品系统常见的四个坑
1. 一个商品只建一个库存字段
如果商品有颜色、尺寸、套餐、规格,库存应落在 SKU 层,而不是 SPU 层。
错误设计:
商品:柠檬茶 库存:100正确设计:
柠檬茶 500ml 单瓶:60 柠檬茶 500ml 12 瓶装:402. 把展示名称当唯一标识
商品名称可以改,SKU 编码不应频繁改。
不要用:
柠檬茶大瓶装作为唯一关联字段。
3. 用条码关联全部订单数据
条码是业务属性,不是万能主键。
订单明细更适合保存:
sku_id sku_code barcode_snapshot product_name_snapshot spec_snapshot sale_price_snapshot这样即使商品后续改名、改规格,历史订单也不会乱。
4. 没有为第三方平台留编码字段
以后接入抖音电商、淘宝、京东、拼多多、外卖平台、ERP、WMS 时,常常需要不同平台的外部编码。
建议预留:
external_code platform_sku_code supplier_sku_code warehouse_sku_code九、项目交付时建议附上一份“商品数据字典”
小程序、商城或库存系统交付时,不要只交源码和后台账号。
建议同时交付一份商品数据字典,至少包含:
| 字段 | 含义 | 示例 |
|---|---|---|
| product_id | 商品主键 | 10001 |
| spu_code | 主商品编码 | TEA-LEMON |
| sku_code | 规格编码 | TEA-LEMON-500-SINGLE |
| barcode | 商品条码 | 6941234567890 |
| batch_no | 批次号 | 20260626-A |
| warehouse_id | 仓库编号 | 1 |
| external_code | 外部平台编码 | TB-10001-A |
这份文档能减少后续运营、仓库、客服、开发人员之间的信息断层。
结语
商城系统里,SKU、条码、二维码、批次号不是同一个概念。
项目初期把它们分清楚,后期接入扫码枪、仓储、门店、供应链、电商平台时,系统扩展会更顺畅。
对于开发团队来说,最重要的不是一开始把模型做得无限复杂,而是给未来的商品规格、条码流通、库存批次和平台对接留出合理空间。
关于作者:本文由恒信致远知识产权团队架构师整理。我们在标准商品数字化建模、供应链系统研发等领域拥有丰富的实战经验,欢迎各位技术同仁在评论区交流探讨。