如何在MySQL中存储同商品不同尺寸对应的库存数量
电商商品多规格库存的MySQL设计方案
你之前考虑的将尺寸和库存拼接为字符串存入单字段的方案属于违反数据库第一范式的反范式设计,存在查询效率低、并发更新易出错、无法做数据校验、扩展困难等硬伤,不建议使用。电商场景下这类多规格库存存储有经过长期验证的标准范式化设计方案,即SPU+SKU分层存储结构,具体实现如下:
方案核心逻辑
- SPU(Standard Product Unit):存储同一类商品的公共属性,比如T恤的名称、品牌、主图、分类等,和具体尺寸、颜色这类销售属性无关,一款商品对应1条SPU记录
- SKU(Stock Keeping Unit):存储最小库存单元的独有属性,每一组独立的销售属性组合对应1条SKU记录,库存、价格、专属编码这类和具体规格绑定的属性直接存在SKU记录上,你提到的不同尺寸对应不同库存的需求,直接给每个尺寸建独立SKU即可。
具体表结构实现
1. 商品SPU表
存储商品公共基础信息,建表语句参考:
CREATE TABLE `product_spu` ( `spu_id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '商品SPU主键', `product_name` varchar(255) NOT NULL COMMENT '商品名称', `category_id` bigint NOT NULL COMMENT '所属分类ID', `brand_id` bigint DEFAULT NULL COMMENT '品牌ID', `main_img` varchar(500) DEFAULT NULL COMMENT '商品主图地址', `status` tinyint NOT NULL DEFAULT '1' COMMENT '上架状态:1-上架 0-下架', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`spu_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品SPU表';
2. 商品SKU表
存储具体规格对应的库存、价格等信息,是解决多规格库存问题的核心表,建表语句参考:
CREATE TABLE `product_sku` ( `sku_id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'SKU主键', `spu_id` bigint unsigned NOT NULL COMMENT '关联的SPU ID', `size` varchar(20) NOT NULL COMMENT '尺寸值,如XL/XXL/XXXL', `stock` int unsigned NOT NULL DEFAULT '0' COMMENT '当前规格库存数量', `price` decimal(10,2) NOT NULL COMMENT '当前规格售价', `sku_code` varchar(64) DEFAULT NULL COMMENT 'SKU仓储编码', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`sku_id`), UNIQUE KEY `uk_spu_size` (`spu_id`,`size`), -- 避免同商品同尺寸重复创建SKU KEY `idx_spu_id` (`spu_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品SKU表';
以你提到的T恤为例,数据存储方式为:
- 在
product_spu中插入1条记录:spu_id=1, product_name="纯棉圆领T恤" - 在
product_sku中插入3条对应规格的记录:sku_id=1, spu_id=1, size="XL", stock=20sku_id=2, spu_id=1, size="XXL", stock=25sku_id=3, spu_id=1, size="XXXL", stock=30
常用操作示例
该结构下所有库存相关操作都可以直接通过SQL完成,不需要额外解析字符串:
- 查询某商品所有尺寸的库存:
SELECT size, stock FROM product_sku WHERE spu_id = 1;
- 扣减指定尺寸库存(并发场景下配合数据库行锁可以避免超卖):
UPDATE product_sku SET stock = stock - 1 WHERE spu_id = 1 AND size = 'XL' AND stock >= 1;
- 筛选所有XL码库存不足10件的在售商品:
SELECT p.product_name, s.stock FROM product_spu p JOIN product_sku s ON p.spu_id = s.spu_id WHERE s.size = 'XL' AND s.stock < 10 AND p.status = 1;
扩展说明
如果后续商品需要支持多维度规格(比如同时有尺寸、颜色两个规格),只需要在现有结构上扩展规格名、规格值关联表即可,核心的SKU存储库存的逻辑不需要改动,扩展性远强于字符串拼接方案。
不要为了减少表记录数采用字段存拼接字符串的设计,这类设计在业务量增长、需求迭代后会产生极高的维护成本,SPU+SKU的分层结构是电商领域通用的成熟方案,可以直接落地使用。
内容的提问来源于stack exchange,提问作者Nandini Sriavastava
相关产品推荐
相关产品推荐

