数据库设计基础:库存表结构设计、商品表与货架表关系、字段类型选择

好,咱们进入第二章。上一章我们聊了仓库的整体架构,这一章要落地了——数据库设计。说白了,就是怎么用表把货架上的东西管明白。

我见过太多项目,业务逻辑还没跑通,数据库先炸了。为什么?表结构设计不合理。你想想看,一个字段类型选错了,后期改起来有多痛苦?嗯,我经历过,改一次表结构,牵一发而动全身。

2.1 商品表:一切的基础

商品表,也叫SKU表。这是整个库存系统的基石。没有它,后面所有表都是空中楼阁。

我个人习惯,商品表的核心字段就这几个:

字段名 类型 说明
sku_id BIGINT 主键,自增,唯一标识
sku_code VARCHAR(64) 商品编码,业务上唯一
sku_name VARCHAR(128) 商品名称
category_id INT 分类ID,关联分类表
unit VARCHAR(16) 单位,如:件、箱、个
status TINYINT 状态:1启用,0停用

这里有个坑。很多人喜欢用VARCHAR(255)当默认长度。我建议别这么干。为什么?因为MySQL在内存中排序时,VARCHAR会按定义长度分配内存。你定义255,哪怕只存了3个字符,也占255字节。浪费。

核心原则:字段长度够用就行,别贪多。sku_code 64位足够了,sku_name 128位也够了。真遇到超长商品名?那是业务问题,不是数据库问题。

2.2 货架表:位置即身份

货架表,也叫库位表。它记录的是「东西放在哪」。我做过一个项目,仓库有5层货架,每层20个格子。一开始设计时,有人提议用「A-01-01」这种字符串当主键。我坚决反对。

为什么?因为字符串做主键,查询性能差,而且不好做范围查询。你想想看,要查「A区所有货架」,用字符串得用LIKE,索引基本废了。

我建议这样设计:

字段名 类型 说明
shelf_id BIGINT 主键,自增
warehouse_id INT 仓库ID
zone_code VARCHAR(16) 区域编码,如A区、B区
shelf_code VARCHAR(32) 货架编码,如A-01-01
shelf_type TINYINT 货架类型:1标准,2冷藏,3危险品
max_capacity DECIMAL(10,2) 最大容量(单位:立方米或件数)
current_used DECIMAL(10,2) 已使用容量

小技巧:shelf_code虽然是字符串,但它是业务编码,用来给人看的。真正做关联查询时,用shelf_id这个数字主键。这叫「业务主键」和「逻辑主键」分离。我踩过这个坑,后来一直这么用。

2.3 库存表:核心中的核心

库存表,这是整个系统的命脉。设计得好,后面所有业务逻辑都顺。设计得不好,嗯,你懂的。

库存表的核心字段:

字段名 类型 说明
inventory_id BIGINT 主键,自增
sku_id BIGINT 关联商品表
shelf_id BIGINT 关联货架表
quantity DECIMAL(12,2) 库存数量
locked_quantity DECIMAL(12,2) 锁定数量(订单占用)
available_quantity DECIMAL(12,2) 可用数量 = quantity - locked_quantity
batch_no VARCHAR(64) 批次号
production_date DATE 生产日期
expiry_date DATE 过期日期

这里我要重点说一下数量字段的类型选择。很多人用INT,觉得整数就够了。但我在实际项目中遇到过,有些商品是按「千克」算的,有些是按「米」算的,甚至有些是按「平方米」算的。用INT?小数点后面全丢了。

所以我建议用DECIMAL,而不是FLOAT或DOUBLE。为什么?因为FLOAT和DOUBLE是浮点数,有精度问题。你存个0.1,读出来可能是0.100000001。做库存计算时,这种误差会累积,最后对不上账。

警告:千万不要用FLOAT或DOUBLE存金额或数量。DECIMAL才是正解。精度问题在金融和库存系统里是致命的。我曾经因为这个问题,半夜被叫起来修数据,那滋味...嗯,你懂的。

2.4 商品表与货架表的关系

商品和货架是什么关系?多对多。一个商品可以放在多个货架上,一个货架也可以放多种商品。所以我们需要一个中间表——库存表。

库存表就是那个「桥梁」。它把商品ID和货架ID连在一起,再加上数量、批次等信息,就构成了完整的库存记录。

我画个简单的逻辑图:

商品表 (sku) ——< 库存表 (inventory) >—— 货架表 (shelf)

这种设计的好处是什么?灵活。你想查「某个商品在哪些货架上」,直接查库存表,按sku_id过滤就行。你想查「某个货架上有什么商品」,也是查库存表,按shelf_id过滤。

而且,这种设计天然支持「一货多位」和「一位多货」的场景。你想想看,仓库里经常会有「同一个商品分散在多个货架」的情况,或者「同一个货架混放多种商品」的情况。这种设计都能完美支持。

2.5 字段类型选择的避坑指南

好,最后我总结一下字段类型选择的几个原则。这些都是我用真金白银换来的经验。

  1. 能用TINYINT就别用INT。状态字段、类型字段,值就那么几个,TINYINT就够了。省空间就是省性能。
  2. 日期用DATE或DATETIME,别用字符串。字符串存日期,没法做日期计算,也没法利用日期索引。我见过有人用VARCHAR存日期,查某个月的数据时,用LIKE '2024-03%',那性能...惨不忍睹。
  3. 数量用DECIMAL,别用FLOAT。这个前面说过了,精度问题。
  4. 主键用BIGINT,别用INT。虽然INT够用,但万一数据量上亿了呢?BIGINT多花4个字节,买个安心。
  5. 编码字段加唯一索引。比如sku_code、shelf_code,业务上要求唯一,那就加UNIQUE索引。防止脏数据。

总结一下:数据库设计没有银弹,但遵循这些基本原则,至少能让你少踩80%的坑。下一章,我们会聊库存的初始化流程,包括怎么把数据从Excel导入数据库。到时候我会分享一个我常用的「批量导入模板」,保证效率翻倍。

嗯,今天就到这里。记住,表结构设计是地基,地基不稳,楼盖得再高也是危楼。