进销存系统表设计的核心在于:先从业务流程出发抽象实体,再根据主数据、业务数据、辅助数据三大类规划表结构,并通过主外键、索引和字段规范保证性能与扩展性。在实际落地时,应优先拆分出商品、客户、供应商、库存等主数据表,再为采购、销售、退货、盘点等业务建立“单据头+单据明细”结构,并结合多仓库、多批次、多币种等场景预留字段或扩展表。在此基础上,通过标准化字段命名、状态字段与日志表、视图与报表中间层,构建兼顾查询性能与数据一致性的进销存数据库模型。对于中小团队,可选择支持自定义表结构和字段的进销存工具(如低代码进销存模板),在图形化界面中快速调整业务字段,避免一开始就“定死”数据库结构而难以迭代。
🧩 一、进销存系统表设计的整体思路
进销存系统(Purchase–Inventory–Sales)看似是“记账+库存统计”,本质上是在数据库中严谨地记录“货、钱、往来关系”的全流程。要高效规划系统表结构,关键有三点:
1. 从业务 → 概念模型 → 逻辑模型 → 物理模型
2. 按数据类型分层:主数据、业务数据、辅助数据
3. 用可进化的设计,而不是一次性“完美设计”
1.1 从业务流程出发,而不是从表名出发
很多人上来就写 product 、 order 表,几百个字段堆在一起,做到中期就发现无法适应退货、调拨、多仓、多批次等需求,需要频繁改表结构。正确顺序应是:
1. 列出业务流程:采购 → 入库 → 库存 → 销售 → 出库 → 退货 → 盘点 → 调拨……
2. 找出流程里的“名词”(实体):
- 商品(SKU)、商品分类、品牌
- 仓库、库区、货位
- 客户、供应商
- 员工 / 业务员
- 单据:采购单、销售单、入库单、出库单、退货单、盘点单、调拨单……
1. 分出实体之间的关系:一对多、多对多、从属关系等
2. 再落到数据库表设计:主键、外键、字段、索引等
1.2 三类核心数据:主数据、业务数据、辅助数据
将进销存系统中的表分为三大类,有助于控制复杂度:
| 数据类型 | 说明 | 典型表举例 |
|---|---|---|
| 主数据 | 相对稳定的基础档案 | 商品、客户、供应商、仓库、员工、价格模板 |
| 业务数据 | 每天大量新增的单据、流水 | 采购单、销售单、入库单、出库单、库存流水 |
| 辅助数据 | 帮助约束、编码、统计的配置数据 | 字典表、单位换算、税率、币种、对照表等 |
设计时先把主数据和核心业务数据做好,再用辅助数据增强灵活性。
1.3 采用“单据头 + 单据明细”模式
进销存系统中的采购单、销售单、入库单、退货单等,最典型的设计方法是:
- 单据头表:记录整张单据的信息(客户、供应商、业务日期、总金额、状态)
- 单据明细表:记录每一行商品的数量、单价、折扣、税额等
优点:
- 易扩展:新增字段时通常只影响单据头或单据明细之一
- 易统计:按单据、按商品、按客户都可以灵活汇总
- 符合业务习惯:纸质单据/Excel 通常也是“表头+明细行”
🏗 二、进销存系统核心表结构总体规划
在开始逐个拆表之前,先给出一个典型进销存系统的表结构总体蓝图,方便全局把握。
2.1 典型进销存系统表清单
以下列表以“模块-表”方式展示核心表(不含全部字段):
| 模块 | 表名示例 | 类型 |
|---|---|---|
| 商品管理 | product , product_category , brand , unit , product_price | 主数据 / 辅助数据 |
| 仓库管理 | warehouse , location , stock , stock_batch , stock_log | 主/业务/日志 |
| 采购管理 | purchase_order , purchase_order_item , purchase_inbound , purchase_return | 业务数据 |
| 销售管理 | sales_order , sales_order_item , sales_outbound , sales_return | 业务数据 |
| 往来单位 | customer , supplier , contact_person | 主数据 |
| 资金结算 | payment_receipt , payment_record , settlement_account | 业务/主数据 |
| 盘点调拨 | stock_check , stock_check_item , stock_transfer , stock_transfer_item | 业务数据 |
| 权限与组织 | user , role , department | 主数据 |
| 系统配置 | sys_dict , sys_config , currency , tax_rate | 辅助数据 |
| 报表中间层 | report_inventory_daily , report_sales_summary | 统计中间表 |
在实际系统中,可根据业务复杂度增减某些表,但大体的进销存数据库结构基本符合这一框架。
2.2 “主数据先行”原则
在进销存系统中,商品、仓库、客户、供应商几乎是所有业务表的外键来源。设计顺序建议:
1. 先设计主数据表(产品档案、仓库、客户等)
2. 再设计单据表(采购、销售等)
3. 最后设计库存、报表和统计中间表
这样可以最大限度避免“回头补外键、字段”的情况。
📦 三、商品与主数据表设计(产品、客户、供应商等)
商品和往来单位是进销存系统表结构中最重要的主数据。设计不当会导致库存统计困难、价格体系混乱、搜索与报表低效。
3.1 商品表(Product)设计要点
商品表是进销存系统的核心表之一。常见字段设计如下:
商品表设计要考虑的问题
1. 单位换算 :一箱=12瓶,如何设计?
- 不建议在 product 里堆多个“单位+换算”字段
- 推荐使用 product_unit_convert 子表,记录多个单位及换算率
1. 多条码 :同一商品可能有内外箱条码、旧条码
- 使用 product_barcode 子表,一条码对应一个 product_id
1. 批次和有效期 :是否每个商品都启用批次?
- 可以通过 enable_batch 、 enable_expiry 控制
- 库存表和出入库明细在需要时才关联 batch_no 、 expiry_date
1. 价格体系 :不同客户级别、不同价格表的价格管理如何做?
- 核心商品表只存“参考价”或“默认价”
- 实际销售价通过 product_price + 价格策略来控制
3.2 商品分类、品牌、单位等辅助表
为了让进销存系统在统计维度上更丰富,需要为商品建立分类表、品牌表、单位表等。
这些进销存基础表在业务上非常稳定,变动频率低,适合提前设计好。
3.3 客户表与供应商表设计
往来单位在进销存系统中一般以客户(Customer)和供应商(Supplier)为主,也可以合并成统一的“往来单位”表,再通过类型字段区分。
方案一:客户与供应商分表
方案二:统一往来单位表
进销存表结构选型建议:
- 若业务上客户和供应商字段差异大,推荐分表,避免大量无用字段
- 若有大量既是客户又是供应商的往来单位,可以采用统一 partner 方案,用 partner_type 做区分
3.4 员工、部门、业务员等组织主数据
为了在报表中统计“按业务员销售”“按部门毛利”等,进销存系统需要组织类主数据表:
🏬 四、仓库与库存表结构设计
库存相关的表设计,是进销存系统中最容易“踩坑”的部分:既要保证准确,又要兼顾性能与可扩展性。
4.1 仓库与库位表
进销存系统中的仓库可以是虚拟仓(在途仓、损耗仓等)也可以是实体仓(总部仓、门店仓)。
如果需要精确管理库区、货架、货位,可增加库位表:
4.2 库存现存量表(Stock)
库存现存量表用于快速查询当前库存数量。典型字段:
设计要点:
1. 多仓库:以 warehouse_id 作为维度
2. 多批次:按 batch_no + expiry_date 区分库存记录
3. 库存锁定:为了支持订单预占,可以用 locked_quantity 字段记录
4. 性能:对 product_id + warehouse_id (+ batch_no) 建复合索引,保证库存查询速度
4.3 库存流水表(Stock Log)与实时库存维护
为了追踪库存变化来源,需要库存流水表记录每一次库存变动:
使用原则:
- stock 表记录“当前快照”
- stock_log 表记录“所有变动历史记录”
- 实时更新库存:当业务单审核通过时,写入 stock_log ,同时更新 stock 表中的数量
- 若未来需要“某日库存回溯”,可按 stock_log 重新计算或通过每日库存快照表实现
4.4 批次与有效期管理
对于食品、药品等行业,进销存系统需要精确管理批次和有效期。
两种主流方案:
1. 在库存表中直接用 batch_no + expiry_date 作为维度
- 适用于批次字段不多、批次属性简单的场景
1. 单独建立批次表 stock_batch ,库存表只关联 batch_id
- 适用于批次有更多属性(生产日期、质检结果等)
示例(批次表):
库存表里用 batch_id 替代 batch_no ,利于统一管理和查询。
🧾 五、采购业务表结构设计(采购单、入库单、退货单)
采购模块是进销存系统中“库存增加”的主要入口,表设计直接影响库存准确性与采购分析能力。
5.1 采购订单表(Purchase Order)
采购订单包含订单头与订单明细:
5.2 采购入库单(Purchase Inbound)
在较为复杂的进销存系统中,采购订单与采购入库通常分离,以支持“多次到货、部分到货、超交”等场景。
审核 purchase_inbound 时,触发:
- 写入库存流水 stock_log (biz_type = purchase_in)
- 更新 stock 表对应仓库、商品、批次的库存数量
5.3 采购退货单设计
采购退货是库存减少的一种特殊出库类型:
审核退货单时,库存减少,对应 stock_log 记录 biz_type = purchase_return_out 或类似标识。
💰 六、销售业务表结构设计(销售单、出库单、退货单)
销售模块是进销存系统中“库存减少、应收增加”的核心模块。
6.1 销售订单表(Sales Order)
6.2 销售出库单(Sales Outbound)
与采购类似,销售订单和销售出库在进销存系统中通常分开发:
审核出库单时,触发:
- 生成库存流水 stock_log (biz_type = sales_out)
- 更新 stock 表数量
- 可以生成应收记录(与财务模块联动)
6.3 销售退货表结构
销售退货是库存增加的一种入库类型,设计上与采购退货相对称:
审核时库存增加,生成相反方向的应收调整记录。
🔄 七、盘点、调拨与其他库存业务表设计
进销存系统不仅有采购入库、销售出库,还存在盘点差异、库存调拨、报废等多种库存变动场景。
7.1 库存盘点表结构
库存盘点的过程通常是:
1. 生成盘点任务(指定仓库、商品范围)
2. 录入盘点数量
3. 审核后计算盘盈盘亏,形成库存调整记录
审核盘点单时:
- 对差异数量生成 stock_log (biz_type = check_adjust)
- 调整 stock 表对应记录的数量
7.2 库存调拨(仓库间转移)
库存调拨是仓库之间的转移,不改变整体库存总量,只改变仓库维度分布。
执行时有两种模式:
- 简化模式:审核即完成调出与调入(适合线上虚拟调拨)
- 严格模式:先生成“调出单”(出库),到达目标仓库后生成“调入单”(入库),更贴近现实物流过程
7.3 库存报废、损耗、赠品等特殊业务
可统一抽象为“库存调整单”:
所有特殊出入库都通过此类库存调整单体现,并在库存流水中有明确记录。
💳 八、资金、应收应付与结算相关表设计
很多进销存系统会与财务模块(应收、应付、现金银行)打通,因此需要考虑资金表结构与单据的关联。
8.1 结算账户与收付款方式
8.2 应收、应付与收款、付款单
这里给出较通用的进销存–财务接口设计:
收款单与付款单:
通过应收应付表与进销存业务表建立关联,形成完整的“货-账-款”闭环。
⚙️ 九、系统配置、字典与编码规则表设计
让进销存系统具备高扩展性与可配置性,离不开字典、配置和编码规则等辅助表。
9.1 字典表(数据字典)
字典表通常统一管理各种枚举值:客户类型、发票类型、付款方式等。
在进销存业务表中,很多字段可以通过外键 or 代码形式对 sys_dict 进行引用,从而实现灵活配置。
9.2 系统配置表(全局参数)
典型的进销存相关配置有:
- 是否允许负库存
- 是否启用批次管理、有效期管理
- 是否强制关联订单才能出入库
- 默认税率、默认币种等
9.3 编码规则表(单号规则)
进销存系统中的单据号(销售单号、采购单号等)一般不直接用数据库自增ID,而是根据规则生成:
在生成进销存单据号时,先查询对应 biz_type 的编码规则,再按照规则组合生成。
🧱 十、字段命名规范与主外键/索引设计原则
表结构设计不仅是“有哪些表”,还包括规范的字段命名和索引策略,这直接关系到维护成本与性能。
10.1 字段命名规范建议
1. 统一使用下划线风格: product_id , created_at
2. 主键统一命名为 id ,类型可以是 INT/BIGINT 自增,或 UUID
3. 关联字段统一使用 \{table_name_singular\}_id :如 product_id , customer_id
4. 金额字段统一使用 DECIMAL(18, 2) ,命名中包含 amount 或 price :如 total_amount
5. 数量字段统一使用 DECIMAL(18, 6) 或 NUMERIC ,便于支持小数数量
6. 时间字段统一以 _at 结尾: created_at , updated_at , approved_at
10.2 主键与外键设计策略
- 主键:每个表必须有主键 id ,对于单据头表,还可以建立 biz_no 唯一索引
- 外键:
- 在数据库层是否启用 FK 约束,可依据项目规模与性能要求选择
- 中小型进销存项目,可开启部分外键约束,提升数据一致性
- 高并发、大数据量场景,可在应用层控制关联关系,数据库层只保留字段和索引
10.3 索引设计要点
常见索引设计原则:
1. 所有外键字段都建立普通索引: product_id , warehouse_id , customer_id 等
2. 常用查询条件建复合索引,如:
- stock(product_id, warehouse_id, batch_no)
- purchase_order(supplier_id, order_date)
- sales_order(customer_id, order_date)
1. 对于单据头表中的 biz_no (如 so_no 、 po_no )建立唯一索引,保证单号唯一
2. 避免对高频更新字段建立过多索引,以免写入性能下降
📊 十一、报表与分析视图的表结构规划
进销存系统最终要为管理层提供决策报表,例如库存报表、毛利报表、销售分析等。在设计业务表时就需要考虑报表中间层。
11.1 报表中间表 vs 即时统计
两种策略:
1. 即时统计 :直接在业务表上通过复杂 SQL 聚合查询
- 优点:无需额外表
- 缺点:进销存数据量大时性能很差,影响业务操作
1. 报表中间表 :定时或实时将业务数据汇总到中间表
- 优点:查询性能好,可针对统计需求设计索引
- 缺点:需要额外开发同步逻辑
推荐在数据量增长后使用报表中间表,如:
这些表可以通过 ETL、定时任务或触发器等方式,从进销存业务表同步数据。
11.2 视图(View)与物化视图
对于中等规模的进销存系统,可以使用数据库视图:
- view_inventory_current :关联 stock + product + warehouse ,获取当前库存
- view_sales_detail :关联 sales_order + sales_order_item + customer + product ,获取明细销售报表
如果数据库支持物化视图(如 PostgreSQL、部分云数据库),可以进一步提升复杂统计的查询性能。
🧪 十二、多仓、多门店、多币种等复杂场景扩展设计
在实际项目中,进销存系统往往要支持多仓库、多门店、多币种,甚至跨地区分公司,这些需求在表结构层面的体现非常关键。
12.1 多门店与多组织
如果企业有多个门店或子公司,可以采用“组织维度”设计:
然后在关键表中增加 org_id 字段:
- 仓库表 warehouse.org_id
- 业务单据表 purchase_order.org_id , sales_order.org_id
- 报表中按组织维度统计
12.2 多币种与汇率
进销存系统如果涉及海外采购或外币结算,需要支持多币种:
在进销存业务表中:
- 单据头表记录 currency_id 和 exchange_rate
- 金额字段可以存“原币金额”和“本位币金额”两个字段
12.3 多价格体系与折扣策略
对于分销、渠道等复杂销售场景,通常需要设计商品价格表:
在销售订单明细中,根据客户、商品、日期等条件选择合适的价格记录。
🧰 十三、如何在实践中快速搭建和迭代表结构?
理论上设计一套完整的进销存表结构容易,但在实际项目中,为了适应不断变化的业务,如何迭代和调整才是难点。
13.1 原型期:用低代码/可视化工具快速试错
在进销存系统的原型阶段,不建议一上来就写死数据库表结构,可以使用支持自定义表单、字段和流程的工具进行建模,再逐步固化数据模型。
例如,在需要试验不同商品字段(多图片、自定义属性)、不同业务单据流程(是否拆分订单与出入库)时,通过可视化配置模型,调整成本更低。 在这类场景中,可以使用带进销存模板的应用平台,例如 <轻流平台进销存> ( https://s.qingflow.com/8bn69 ; )这类支持字段自定义、表单关联、流程配置的工具,先搭出业务流程和基础表,然后根据实际使用反馈再优化最终数据库模型。
13.2 成熟期:固化基础表结构,预留扩展字段
当进销存业务流程稳定后,可以:
1. 固定主数据表和核心业务表的主键、核心字段
2. 为将来可能变化的需求预留 ext_json 、 custom_field1/2/3 等扩展字段
3. 或者设计“自定义字段配置表”,将额外字段以键值对(Key-Value)形式存储
示例扩展表:
这样可以避免频繁改表结构,又能满足进销存项目中的定制化字段需求。
13.3 升级与迁移:版本化数据库结构
在长期维护的进销存系统中,数据库变更需要严格版本管理:
- 建议采用 db_migration 表记录每次脚本变更
- 每次新增字段、索引或表,使用统一的版本脚本执行
- 配套发布流程,确保多环境(测试、预生产、生产)同步
🧭 十四、进销存系统表设计中的典型坑与规避策略
14.1 把“所有业务”堆在一个表里
常见错误:一个 order 表既记录采购又记录销售,还有退货字段、盘点字段,导致字段大量空置、逻辑复杂。
规避策略:
- 分业务类型设计不同单据表: purchase_order , sales_order , stock_check 等
- 可以用统一抽象层(如统一的“单据接口”)在代码层封装,而不是数据库层强行混合
14.2 忽略状态字段与审核流
进销存业务有明确的状态流转(草稿→提交→审核→生效),如果表中没有状态字段,就很难控制业务规则。
建议:
- 每个单据表都应有 status 字段
- 至少区分“草稿 / 已提交 / 已审核 / 已作废”
- 审核动作与库存、应收应付生成紧密绑定
14.3 忽略性能与索引,导致报表极慢
进销存数据量一旦上来,直接在业务表上聚合统计会非常慢。
建议:
- 针对高频查询场景设计复合索引
- 使用报表中间表或物化视图承担复杂统计任务
- 对历史数据做分区或归档(如按月、按年分表)
14.4 一开始就追求绝对“通用”,导致设计过度复杂
太通用的数据库模型往往难以落地,业务同事看不懂,开发成本高。
建议:
- 按业务阶段迭代:先满足 70% 核心需求,再逐步扩展
- 可通过低代码工具 + 模板先验证业务,再将成熟模型抽象出来
- 像 <轻流平台进销存> ( https://s.qingflow.com/8bn69 ; )这类可按需扩展字段和流程的模板,可以作为“业务验证沙箱”,等模型稳定后再落到正式数据库中
🚀 十五、总结与未来进销存表结构设计趋势
进销存系统表设计的关键,可以归纳为以下几条原则:
1. 以业务驱动模型 :先梳理采购、库存、销售全链路,再抽象实体和关系,不要从“想象中的表名”出发。
2. 主数据、业务数据、辅助数据分层 :商品、客户、仓库等主数据表是所有进销存业务的基础;所有单据使用“单据头 + 明细”模式;字典、配置、编码规则等提高系统灵活性。
3. 库存设计要区分“现存量”和“流水” : stock 做快照, stock_log 做历史记录,必要时再加每日库存快照或报表中间表。
4. 多场景扩展预留空间 :多仓、多门店、多币种、多价格体系,通过组织维度、币种表、价格表、批次表等实现扩展,而不是在原表上堆杂乱字段。
5. 用规范命名、合理索引和状态字段保证可维护性 :统一的字段命名与主外键策略,配合状态流转字段,使进销存业务更清晰、可追溯。
6. 通过可配置平台加速迭代 :在早期和变更频繁的阶段,借助支持自定义表结构与流程的进销存工具,可以极大地降低试错成本;例如 <轻流平台进销存> ( https://s.qingflow.com/8bn69 ; )提供的进销存系统模板,就可以在可视化界面中快速调整字段、关联和审批流程,适合作为模型验证与小团队实践的起点。
未来,进销存系统表结构设计会呈现以下趋势:
- 与财务、CRM、生产等模块进一步一体化 :数据库模型会逐步演化为围绕商品、组织和单据的统一数据中台,跨模块共享主数据。
- 更多使用低代码/元数据驱动模型 :字段和表结构不再完全写死于代码,而是由元数据驱动,进而支持在线扩展字段、动态报表、个性化视图。
- 云原生与分布式数据库支持 :对于大型企业,进销存数据会分区、分库、分表存储,通过统一的逻辑视图提供服务,这对表结构规划提出更高要求。
- 实时分析与智能补货 :在已有库存与销售数据模型之上,将接入实时分析和算法,自动给出补货建议、价格策略和库存优化方案。
在动手设计进销存系统表结构时,可以先用文中提到的核心表结构作为蓝本,结合自身业务特点进行增删,再利用可以自定义字段和流程的工具进行快速验证和调整。
最后,分享一个我们公司在用的进销存系统模板,需要的可以自取,可直接使用,也可以自定义编辑修改: https://s.qingflow.com/8bn69
如果企业希望把文章中的进销存方法真正落到日常执行,轻流可通过可视化表单承接采购、入库、出库、调拨和盘点,再结合流程审批、库存数据关联、权限管理、自动提醒与数据看板,把业务对象、流程节点和经营数据串起来,并按实际变化持续调整;可了解轻流,从一个真实场景开始试点。
