数据库设计基础:库存表结构设计、商品表与货架表关系、字段类型选择
好,咱们进入第二章。上一章我们聊了仓库的整体架构,这一章要落地了——数据库设计。说白了,就是怎么用表把货架上的东西管明白。
我见过太多项目,业务逻辑还没跑通,数据库先炸了。为什么?表结构设计不合理。你想想看,一个字段类型选错了,后期改起来有多痛苦?嗯,我经历过,改一次表结构,牵一发而动全身。
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 字段类型选择的避坑指南
好,最后我总结一下字段类型选择的几个原则。这些都是我用真金白银换来的经验。
- 能用TINYINT就别用INT。状态字段、类型字段,值就那么几个,TINYINT就够了。省空间就是省性能。
- 日期用DATE或DATETIME,别用字符串。字符串存日期,没法做日期计算,也没法利用日期索引。我见过有人用VARCHAR存日期,查某个月的数据时,用LIKE '2024-03%',那性能...惨不忍睹。
- 数量用DECIMAL,别用FLOAT。这个前面说过了,精度问题。
- 主键用BIGINT,别用INT。虽然INT够用,但万一数据量上亿了呢?BIGINT多花4个字节,买个安心。
- 编码字段加唯一索引。比如sku_code、shelf_code,业务上要求唯一,那就加UNIQUE索引。防止脏数据。
总结一下:数据库设计没有银弹,但遵循这些基本原则,至少能让你少踩80%的坑。下一章,我们会聊库存的初始化流程,包括怎么把数据从Excel导入数据库。到时候我会分享一个我常用的「批量导入模板」,保证效率翻倍。
嗯,今天就到这里。记住,表结构设计是地基,地基不稳,楼盖得再高也是危楼。