做过进销存的人都知道,这个系统看着简单,数据库设计却极容易埋雷。商品改价之后历史单据金额变了、盘点调整把流水冲断、月底成本算不平——这些事故的根子大多在表结构设计阶段就埋下了。这篇文章把一套标准进销存的核心表结构拆开讲:商品、单据、库存、批次、往来五组表,各自解决什么问题、有哪些设计红线,适合正在自研或评估产品数据模型的团队。
一、商品档案表:一切的起点,也最容易烂
商品表是进销存的字典,所有单据都引用它。这张表的设计质量决定了整个系统的数据质量。
1. 编码是主键,名称不是
商品编码用唯一主键,名称允许重复。两个厂家的「螺栓M8」名字一样、编码必须不同。见过用名称当关联键的系统,商品改个名,三年历史单据全部失联。
2. 计量单位与多单位换算
采购按箱、销售按个、库存按件,这是批发行业的日常。商品表存基本单位,另建一张换算表存各单位与基本单位的系数,单据录入时自动折算。单位混乱是库存对不上账的头号原因,值得在表设计阶段就锁死。
3. 分类与属性分层
商品分类单独建表,树形结构,商品挂分类ID。品牌、规格、颜色这类属性不要全做成商品表字段,用扩展属性表纵向存,加新属性不用改表结构。
二、单据体系:主子表结构是铁律
采购入库、销售出库、调拨、盘点、退货,所有单据一律主表加子表:主表存单号、日期、往来单位、经办人、金额汇总;子表按行存商品、数量、单价、金额。
| 表 | 存什么 | 关键点 |
|---|---|---|
| 单据主表 | 单号、类型、日期、往来方 | 单号全局唯一、类型枚举固定 |
| 单据子表 | 商品行、数量、单价、折扣 | 挂主表ID、逐行留快照 |
| 单据状态表 | 审核、冲销、作废记录 | 红冲不改原单 |
1. 快照字段:历史单据不许变
子表里的商品名称、单价、单位,必须在保存单据时快照下来,不能只存商品编码外键。商品档案后续怎么改,历史单据展示的还是开单那一刻的样子。财务对账、审计追溯都依赖这条原则。
2. 红字冲销而不是删除
错单不许物理删除,走红字冲销:生成一张数量金额取负的冲销单,两张单都留在库里。删单是审计大忌,也让你永远说不清「这个月为什么少了三万块的货」。
三、库存账:结存表加流水表双轨并行
库存设计只有一个正确答案:流水表记每一笔变动,结存表存当前余量,两张表互相校验。只留结存数的系统,库存变成了黑盒——数对不对,谁也无法证明。
1. 库存流水表:只增不改
每张单据审核后写入流水:哪个仓库、哪个商品、变了多少、方向、来源单号。流水表是只追加的账本,改库存必须通过新单据,不允许直接update结存字段。
2. 结存表与流水定期对轧
结存数等于期初加流水累计,定期跑对轧校验,两边不一致立刻报警。这是发现程序漏洞和人为篡改的最强手段,对不上账的月结等于裸奔。
3. 占用与可用分开学
销售订单审核后生成占用,出库核销占用。结存表里现存数减占用数才是可用数,页面展示、下单校验都用可用数。不分清这两层,就会把同一批货承诺给两个客户。
不想从零建这套模型的话,可以直接用现成的进销存数据模型方案,流水加结存的双轨结构、红冲机制都是预置好的,省掉大量试错。
四、批次与序列号:追溯的最后一公里
食品、医药、器械行业必须按批次管理。批次表的核心字段:批号、生产日期、保质期、供应商、入库单号。出库时按先进先出带出批次,临期预警扫这张表。
- 批次结存独立于商品结存:同一商品多批次各自有余量
- 序列号管理再加一层:一物一码,出库绑定序列号,适合高值设备
- 质量追溯从批次反查供应商:出问题能一批拉出来召回
五、往来账款表:进销存不止管货
采购入库产生应付、销售出库产生应收,收付款单核销往来。设计上有两个要点。
1. 按单核销,不按余额抹
回款必须关联到具体的销售单,一笔款核销多张单、一张单被多次部分核销都支持。只记客户总余额不做单级核销的系统,对账时「这钱到底是哪笔的」永远说不清。
2. 账龄从单据日期起算
应收账龄按每张未核销单的日期独立计算,而不是按客户最早欠款。催收的时候能精确到单,业务员没有含糊空间。
六、低代码建模:表结构设计的新选项
传统自研这套模型,光表结构设计和联调就要耗掉小半年。现在更务实的做法是用低代码平台建模:主子表结构、流水联动、快照规则这些进销存的标准件,平台已经封装成表单模板和自动动作,业务管理员配置字段和公式即可生成一套结构规范的应用,底层依然是标准关系型数据库,数据可整体导出、可对接报表工具。比如套用一套标准进销存模板,主子表和流水逻辑开箱即用,行业特殊需求再加扩展字段。
1. 什么时候还值得自研
并发量极大、需要深度对接自研WMS或财务中台、或者有严格的本地化部署要求时,自研依然合理。除此之外,自研的维护成本通常远超预期——进销存的坑不在第一版,在第三年业务规则开始变化的时候。
2. 迁移时数据怎么搬
商品、往来单位档案先清洗后导入;期初库存按仓库批次整理成期初入库单;历史单据建议只迁一年内的,更早的封存归档供查询。期初数据录完先做一次全面盘点校验,对上了再切换。
进销存数据库设计的全部秘密就三条:单据快照不许变、库存改动必留流水、错误只能红冲不能删。这三条守住了,账永远对得平。
常见问题解答
Q1:库存表只存一个当前数量不行吗?为什么要流水表?
只存当前数量等于只有结果没有过程,库存对不上时无从查证。流水表记录每一笔变动的来源单据,结存数等于流水累计,任何时刻都能重演和校验。没有流水,月末盘点差异就是一笔糊涂账。
Q2:商品信息改了价格,以前的销售单金额会变吗?
规范设计下不会。单据子表保存时对商品名称、单价做了快照,历史单据展示的是开单当时的信息,商品档案后续修改不影响。这是快照原则,也是财务审计的基本要求。
Q3:什么是红字冲销?和删除单据有什么区别?
红字冲销是生成一张负数单据抵消原单,原单和冲销单都保留。删除则让单据凭空消失,账目出现无法解释的缺口。审计要求所有业务痕迹可追溯,所以进销存系统一律用红冲、禁用物理删除。
Q4:批次管理和序列号管理有什么区别?
批次管「一群」:同一批生产的货共用一个批号,进出按批核算,适合食品医药。序列号管「一个」:每件货有唯一编码,出库绑定到具体那一件,适合设备、高值商品。两者可以叠加使用。
Q5:低代码平台搭的进销存,底层数据库规范吗?
主流低代码平台底层就是标准关系型数据库,主子表、流水表、外键关系都是规范建模的,支持全量数据导出和外部报表工具直连。区别在于建模方式从写代码变成了配置,数据资产不锁定在平台里。