电商小程序SKU数据模型设计:SPU、规格组合、库存与价格的工程实践

做电商小程序,商品模型是整个系统的地基。规格(颜色/尺码/套餐)、库存、价格、图片这几样东西一旦建模出错,后面的购物车、下单、营销活动全会跟着返工。本文从最基础的SPU/SKU概念讲起,给出一套可直接落地的表结构与核心代码,并复盘我们在真实项目里踩过的四个坑。

一、为什么不能把"商品"做成一张表

新手最常见的错误:商品表直接存 price、stock,规格用一个 JSON 字段塞进去。商品只有单一规格时没问题,一旦出现"红色M码""红色L码"这种组合,库存和价格必须按组合独立管理------红色M码卖完不代表红色L码也卖完,套餐版和单机版价格完全不同。

行业通用的抽象是两层:

  • SPU(Standard Product Unit):标准化产品单元,即"一款商品",如"某品牌纯棉T恤",承载商品名称、分类、详情、主图等公共属性。
  • SKU(Stock Keeping Unit):库存最小单元,即"一款商品的一个具体规格组合",如"红色/M码",承载该组合独立的价格、库存、编码。

规格维度(规格名+规格值)与SKU是多对多关系:一个SKU对应多个规格值(红色、M码),一个规格值也被多个SKU共享。

二、表结构设计

sql 复制代码
-- SPU:商品主表
CREATE TABLE product_spu (
  id           BIGINT PRIMARY KEY AUTO_INCREMENT,
  title        VARCHAR(200) NOT NULL COMMENT '商品标题',
  category_id  BIGINT NOT NULL,
  main_image   VARCHAR(500),
  detail_html  MEDIUMTEXT COMMENT '商品详情',
  status       TINYINT DEFAULT 1 COMMENT '1上架 0下架',
  created_at   DATETIME DEFAULT CURRENT_TIMESTAMP
) COMMENT='商品SPU表';

-- 规格名:颜色、尺码、套餐
CREATE TABLE product_spec (
  id     BIGINT PRIMARY KEY AUTO_INCREMENT,
  spu_id BIGINT NOT NULL,
  name   VARCHAR(50) NOT NULL COMMENT '规格名,如:颜色'
) COMMENT='规格名表';

-- 规格值:红色、蓝色;M、L
CREATE TABLE product_spec_value (
  id      BIGINT PRIMARY KEY AUTO_INCREMENT,
  spec_id BIGINT NOT NULL,
  value   VARCHAR(50) NOT NULL COMMENT '规格值,如:红色'
) COMMENT='规格值表';

-- SKU:具体规格组合
CREATE TABLE product_sku (
  id          BIGINT PRIMARY KEY AUTO_INCREMENT,
  spu_id      BIGINT NOT NULL,
  sku_code    VARCHAR(64) NOT NULL COMMENT '商家编码/条码',
  price       DECIMAL(10,2) NOT NULL COMMENT '销售价',
  origin_price DECIMAL(10,2) COMMENT '划线价',
  stock       INT NOT NULL DEFAULT 0,
  image       VARCHAR(500) COMMENT '规格图,如颜色图',
  INDEX idx_spu (spu_id)
) COMMENT='商品SKU表';

-- SKU与规格值关联(核心:多对多)
CREATE TABLE product_sku_spec_value (
  id             BIGINT PRIMARY KEY AUTO_INCREMENT,
  sku_id         BIGINT NOT NULL,
  spec_value_id  BIGINT NOT NULL,
  UNIQUE KEY uk_sku_value (sku_id, spec_value_id),
  INDEX idx_value (spec_value_id)
) COMMENT='SKU规格值关联表';

下单时库存扣减必须在SKU维度进行,并配合乐观锁防超卖:

sql 复制代码
UPDATE product_sku
SET stock = stock - #{num}
WHERE id = #{skuId} AND stock >= #{num};

影响行数为0即库存不足,直接回滚订单。

三、规格选择交互:前端怎么知道哪个组合有货

用户选规格时的经典交互:先选"红色",再选"M码",前端要能立刻定位到对应SKU并展示价格/库存。后端给前端的数据结构建议如下:

json 复制代码
{
  "spuId": 1001,
  "specs": [
    { "specId": 1, "name": "颜色", "values": [
      { "valueId": 11, "value": "红色" },
      { "valueId": 12, "value": "蓝色" }
    ]},
    { "specId": 2, "name": "尺码", "values": [
      { "valueId": 21, "value": "M" },
      { "valueId": 22, "value": "L" }
    ]}
  ],
  "skus": [
    { "skuId": 9001, "valueIds": [11, 21], "price": "99.00", "stock": 32, "image": "..." },
    { "skuId": 9002, "valueIds": [11, 22], "price": "99.00", "stock": 0 },
    { "skuId": 9003, "valueIds": [12, 21], "price": "109.00", "stock": 15 }
  ]
}

前端把 valueIds 排序后拼成 key(如 "11,21")建 Map,用户每选一项就查一次 Map,O(n) 规格维度内即可定位SKU,无库存组合置灰。

四、踩坑复盘

坑1:规格值用字符串匹配而不是ID关联

早期图省事,SKU表直接存 spec_desc="红色,M"。结果商家把"红色"改名成"酒红色"后,历史订单、购物车里的规格全部对不上;字符串匹配也无法支撑规格图联动。规格必须用ID关联,展示名只存规格值表一处,改名全局生效。

坑2:笛卡尔积生成无效SKU组合

两个规格各5个值,理论组合25个,但不是每个组合都真实存在(某颜色可能不产XXL码)。如果后端按笛卡尔积自动生成SKU,会出现大量库存为0的"幽灵SKU",前端置灰逻辑和库存报表全乱。SKU必须由商家在后台显式创建,系统只校验"同一SPU下规格值组合唯一"。

坑3:库存扣减和订单创建不在同一事务

先 update stock 再插订单,看似没问题;但订单插入失败时如果事务没包住,库存就丢了。更隐蔽的是营销活动叠加(拼团+优惠券)导致的并发扣减:必须把"锁库存→算价→建订单明细"放在同一个数据库事务里,超卖回滚由 stock >= num 的乐观锁兜底,不要用 SELECT ... FOR UPDATE 长事务扛高并发,行锁持有时间一长连接池就打满。

坑4:价格快照不入库

下单时只存了 sku_id,没存成交单价。半年后商家调价,历史订单详情里的价格全变成新价,退款金额也算错。订单明细表必须冗余 sku_title、spec_desc、deal_price、sku_image 快照字段------商品会改名、调价、删除,订单是法律凭证,数据必须定格在成交那一刻。

五、小结

商品SKU模型的核心就三句话:SPU管公共信息,SKU管价格库存,规格用ID多对多关联;库存扣减用乐观锁并与订单同事务;订单数据永远存快照。这套结构能覆盖服装、生鲜、套餐组合等绝大多数零售场景,后续做多规格营销、库存预警、销量统计也都有干净的数据基础。

相关推荐
wafrdggh8 小时前
2026电商快递批量查询怎么用?固乔助手模板设置评测
大数据·数据库·小程序
天诰11 小时前
SA-K-11 检索会消失吗与四个未解问题
java·服务器·人工智能·python·机器学习·ai编程
陈希12313 小时前
Linux 防火墙配置实战:firewalld、iptables 与云安全组
linux·运维·服务器
女神下凡13 小时前
芯参谋(95):嵌入式文件系统_开发指南
linux·服务器·arm开发·驱动开发·设计规范
@兽血沸腾14 小时前
Windows系统安装Jenkins部署应用至远程Windows服务器操作指南
运维·服务器·jenkins
讯捷蓝达19 小时前
戴尔R720xd服务器卡死在 “Configuring Memory...Done“,换了内存还是卡?问题根本不在内存
运维·服务器
数字新视界1 天前
动环监控信创适配在智能机房管理中的应用价值与未来展望
大数据·服务器·数据库·动环监控系统·动力与环境监控系统
爱和冰阔落1 天前
【Linux网络】TCP 服务器如何并发处理多个客户端?从 fork、僵尸进程到双重 fork
linux·运维·服务器·网络
lisanmengmeng1 天前
alertmanger 标签 rules 打上分组标签
linux·运维·服务器
wafrdggh1 天前
2026 商城小程序平台哪个价格合理?把跨境附加成本这个坑算透
大数据·小程序