资讯动态

ERP主数据与业务数据关系梳理:从建模到SQL校验的治理实践

发布时间:2026/10/14 12:36:52 来源:尧图企业网站定制
简介一份面向ERP实施顾问、数据管理专员及企业信息化骨干的专题演示文稿围绕主数据与业务数据的关系展开。内容先梳理数据管理实施方法从Aris流程解读、业务访谈、方案设计到系统测试与方案落地再以总体业务数据流串联项目管理、研发、工艺、采购、库存、生产、销售、财务等环节。17页PPT结合生产订单、销售订单、CRM商机、维修工单、物资管理等案例拆解物料主数据、BOM、工艺路线、价格、客户、供应商、会计科目等在发料、报工、调拨、开票、应收应付等动作中的传递。资源为单个pptx文件大小164KB已有43人学习。内容还汇总了MMQM、PP、SD、FICO模块典型问题及对策如删除采购信息记录、采用单车BOM、定制备品备件专用订单类型、统一会计科目等对提升ERP主数据治理水平有直接参考价值。1. 豪华版ERP主数据与业务数据关系17页PPT背后的数据治理命题老板把一个豪华版ERP主数据与业务数据关系17页.pptx丢给我时我第一反应是模板做得真漂亮第二反应是这17页到底要讲清什么。做过ERP实施和运维的人都明白主数据和业务数据的关系从来不是画一张ER图就能交差的。主数据是物料、客户、供应商、会计科目这些名词业务数据是订单、发货单、库存流水、财务凭证这些动词关系理不顺MRP跑出来的需求就是错的库存账实不符永远是玄学财务和供应链对账能吵一整晚。这篇内容不评价PPT本身而是把这个主题拆成能照做的数据治理方案关系怎么建模、字段怎么落、SQL怎么查、坑在哪、以及如何让这份关系文档不只是交付物而是能持续校验的规则。适合ERP实施顾问、数据专员和数据治理新手照着复现。2. 从物料编码到库存流水主数据与业务数据的本质分工2.1 主数据是名词业务数据是动词两条链路的建模差异先给一个判断标准如果一条数据在多个业务流程里被重复引用、变化频率低、删除时必须考虑历史单据引用它大概率是主数据。物料、客户、供应商、会计科目、成本中心、利润中心、仓库、资产都属于主数据。你在SAP里做ABAP资产主数据屏幕增强改的是资产主数据的屏幕字段而不是资产业务凭证你在ERP库存场景里写高并发解决方案并发压力全在库存业务流水表上物料主数据本身不会因为一秒十笔过账而产生竞争。这就是主数据和业务数据最直观的差别主数据是维度是业务数据的地基业务数据是事实是地基上盖起来的房子。从建模看主数据和业务数据走的是两条链路。主数据表的做法是唯一编码做主键加状态字段和有效期间隔valid_from / valid_to用逻辑删除代替物理删除保证历史单据还能通过时间维度追溯当时的引用关系。业务数据表的做法是用单据号行项目号做联合主键业务日期跟随发生时间只增不改数量金额只允许追加或冲销不允许直接UPDATE历史记录。如果不懂这个区别最容易翻车的就是把主数据当成普通表做物理删除——删掉一个物料编码结果三年前的生产订单全部变成黑匣子下游对账直接崩。还有一个常被问到的概念元数据和主数据不是一回事。元数据是描述数据的数据回答这个字段叫什么、什么类型、哪个系统来的主数据是被引用的基础实体数据回答这个客户是谁、这个物料是什么。你梳理ERP主数据与业务数据关系时一定会先做元数据登记但元数据清单只是第一步真正的核心是把主数据实体和业务数据实体之间的引用关系、引用层级、同步机制画清楚。2.2 关系映射的三种典型结构一对多、多对多、递归引用把ERP里常见的关系归纳一下无外乎三种结构。第一种是一对多这是最常见的关系。一个客户下有多张销售订单一个物料下有多条库存收发货记录一个采购订单头下有多行采购行项目。落到数据库里就是在多的那一方业务数据表保存一的那一方主数据表的主键作为外键。查询方向也由此确定从订单表带出客户名称用JOIN订单表引向客户表反过来从客户看他的全部订单用WHERE客户编码查订单表。第二种是多对多需要中间表承接。典型场景是物料与供应商的关系一个物料可以有多家合格供应商一个供应商能供多个物料。ERP里通常把这种关系放在采购信息记录或货源清单里它具备部分主数据特征——相对稳定、被采购业务引用所以一般归入主数据扩展。另一个多对多是BOM物料清单中成品件与原材料的关系这在SAP/用友里属于工程主数据一条BOM行引用子件物料但子件物料本身也是主数据。第三种是递归引用在同一个主数据实体内部自关联。最典型的是BOM的父子层级一个组装件可以当子件被更上级BOM引用同时它自己也能引用下一级零件。还有会计科目表一级科目1001应收账款下有二级科目100101客户A100102客户B它们都在同一张科目主数据表里通过上级科目编码字段挂起来。递归引用最麻烦的坑是死循环——A引用BB引用CC又引用A跑MRP时直接陷入无限循环。所以设计递归主数据表时必须预留层级号字段并限制最大展开层数常见做法是控制在20层以内同时做环路检测。2.3 用ER模型落一个最小案例客户、订单、发货单的关系与字段空谈关系不如直接建模。下面用一个最精简的销售到发货场景展示主数据和业务数据在表结构上的差别。这是我在给企业做数据治理方案时常用的最小骨架所有ERP的进销存链路都能套进去。-- 客户主数据编码唯一状态有效期间隔是主数据标配 CREATE TABLE mdm_customer ( customer_code VARCHAR(20) PRIMARY KEY, -- 业务主键全局唯一 customer_name VARCHAR(100) NOT NULL, customer_group VARCHAR(20), -- 客户组分销/直销/电商 status CHAR(1) DEFAULT A, -- A有效I失效 valid_from DATE NOT NULL, valid_to DATE DEFAULT 9999-12-31, change_time TIMESTAMP -- 最后变更时间用于增量同步 ); -- 销售订单业务数据主键是单据号行号引用客户主数据 CREATE TABLE o2c_sales_order ( order_id VARCHAR(30) NOT NULL, -- 单据号如SO20240701001 line_no INT NOT NULL, customer_code VARCHAR(20) NOT NULL, material_code VARCHAR(20) NOT NULL, order_qty DECIMAL(15,3) NOT NULL, order_date DATE NOT NULL, status VARCHAR(10) DEFAULT OPEN, -- OPEN/COMPLETED/CANCELLED PRIMARY KEY (order_id, line_no), CONSTRAINT fk_order_customer FOREIGN KEY (customer_code) REFERENCES mdm_customer (customer_code) ); -- 发货单引用订单行数量和状态与订单形成勾稽关系 CREATE TABLE o2c_delivery ( delivery_id VARCHAR(30) NOT NULL, line_no INT NOT NULL, order_id VARCHAR(30) NOT NULL, order_line_no INT, delivered_qty DECIMAL(15,3) NOT NULL, delivery_date DATE NOT NULL, PRIMARY KEY (delivery_id, line_no), CONSTRAINT fk_delivery_order FOREIGN KEY (order_id, order_line_no) REFERENCES o2c_sales_order (order_id, line_no) );逻辑说明客户主数据表用customer_code做业务主键而不是自增整数主键是因为ERP集成场景里外部系统、Excel导入、报表平台都需要看到并引用这个编码。status配合valid_from/valid_to实现软删除有效期控制这样即使客户被标记失效历史订单仍然能通过订单日期判断当时该客户是否有效。销售订单表用(order_id, line_no)联合主键这是业务数据的通用做法——一张订单头对应多行物料行项目才是真正引用物料主数据的层级。发货单引用销售订单的联合主键形成客户→订单→发货的单据链。参数说明状态字段用CHAR(1)存A/I比存中文有效/失效更省空间且便于写校验条件和建索引。valid_to默认9999-12-31是行业惯例代表无限期有效如果主数据有正式失效日期再改成真实日期。这里的唯一约束只做演示实际用Oracle或SAP时外键是否启用需要看ERP模块配置——很多老ERP为了性能不建物理外键关系一致性靠应用层维护这就引出后面章节的校验问题。3. 把17页PPT变成可复现的关系梳理方法三张表模板与字段设计3.1 主数据清单表实体、编码规则、状态、有效期的字段怎么定既然要梳理ERP主数据与业务数据的关系第一步是把主数据实体枚举全面。很多项目从ERP里导出了几十张表却没有一张主数据清单总表导致关系图画到一半发现漏了利润中心。我一般会先建一张主数据清单表字段这样设计字段含义示例/规则实体类型主数据分类客户/供应商/物料/会计科目/成本中心/利润中心/资产/仓库实体代码表名或对象名KNA1SAP客户主数据、MDM_CUSTOMER编码规则编码生成规范物料编码定长20位前三段分别为大类2位中类4位流水8位状态字段启用/冻结/失效A启用I失效B冻结有效期字段生效起止valid_from / valid_to来源系统主数据的权威来源SAP MDG、用友U8、自建MDM下游引用数被哪些业务表引用销售订单、采购订单、生产订单负责人数据Owner供应链部物料、财务部科目这张清单表的价值在于让你在梳理关系前先确认哪些实体够资格叫主数据。判断标准就三条——是否跨流程共享、是否被多张单据引用、是否相对稳定。像客户联系人这类数据如果只被CRM使用不被ERP单据引用就不应该出现在这份17页PPT的主数据清单里否则会把关系图撑得很乱。编码规则字段最容易被人忽略但它决定了业务数据怎么引用主数据。常见问题有物料编码有的带前导零有的不带客户编码在销售ERP里是6位在财务共享系统里是8位。整理主数据清单时我会把编码规则写成定长、无含义、含校验位或分段有含义并标注源系统实际格式后面做引用匹配时用得上。3.2 业务数据清单表单据类型、流水号、引用主数据的键怎么设计业务数据清单是第二张表它不写具体业务字段而是记录每一类业务单据在哪个层级引用哪些主数据。这张表设计得好后面画关系图就是照单抄的事。字段含义示例单据类型业务对象分类销售订单/采购订单/生产领料单/库存盘点单/财务凭证单据表名物理表或视图VBAK销售订单头、VBAP销售订单行主键结构单据号行号还是单据号序号订单头主键VBELN订单行主键VBELNPOSNR引用层级头引用/行引用/头行列引用订单头引用客户订单行引用物料主数据引用字段具体外键字段名KUNNR客户编号、MATNR物料编号业务时间字段单据日期/过账日期ERDAT创建日期、AUFDT过账日期台账保留周期在线保留时长5年归档历史表保留10年这里要特别强调引用层级。一张销售订单头引用客户、售达方、送达方、销售组织行引用物料、工厂、库存地点、计量单位。梳理时必须按层级写清楚否则关系图会在订单-客户这一层画完就停了漏掉订单行-物料这个最关键的关系。而MRP主数据介绍里反复强调的BOM展开、独立需求转化为相关需求依赖的正是生产订单行-组件物料的引用关系。业务数据清单里还要记录是否允许跨系统引用。比如你做了本地ERP和自建MDM的集成客户主数据在MDM里生成业务单据在ERP里录入ERP的客户表就是主数据的一个副本。这种情况下业务数据清单要增加一列主数据来源表否则后期排查数据不一致时你根本不知道订单引用的KUNNR到底该和哪张表的编码比对。3.3 关系矩阵表来源系统、引用关系、同步方式与校验规则第三张表是整个17页PPT的灵魂——关系矩阵。如果说前面两张是点这张就是把点连成线的边。源主数据实体目标业务数据实体关系类型引用字段映射同步方式校验规则客户(KNA1/MDM_CUSTOMER)销售订单头(VBAK)1:NKUNNR VBAP-KUNNR实时接口不允许订单引用失效客户物料(MARA/MDM_MATERIAL)销售订单行(VBAP)1:NMATNR VBAP-MATNR实时接口订单行物料必须在物料主数据中启用销售状态供应商(LFA1/MDM_VENDOR)采购订单头(EKKO)1:NLIFNR EKKO-LIFNR实时接口采购订单不允许引用冻结供应商会计科目(SKA1)财务凭证明细(BSEG)1:NHKONT BSEG-HKONT批处理实时科目必须处于记账期内物料(MARA)BOM组件(MAST/STPO)N:NMATNR(父件) ↔ MATNR(子件)批处理BOM展开层级≤20无回路关系矩阵里同步方式和校验规则是落地关键。同步方式决定了主数据变更多久能反映到下游业务单据客户创建后马上要下单用实时接口科目变更涉及财务月结可以走批处理但必须保证日清日结。校验规则是后面做数据质量检查的蓝图宁可先在矩阵里多写几条也不要等数据对不上时再想。这张矩阵还有个额外价值当你的ERP关系梳理干净后想接本地ERPRAGLLM做产品检索直接把矩阵喂给模型它才知道客户编码应该去MDM_CUSTOMER里查、而不是去订单表里猜。很多RAG项目翻车不是因为模型不行而是底层数据关系本身就没梳理过。4. 关系梳理实操从Oracle/SAP/用友导出数据做关系分析4.1 导出主数据与业务数据的标准查询脚本SQL关系矩阵画完之后必须用真实数据验证。我见过太多17页PPT里画的关系图和底层数据库表字段完全对不上——PPT讲的是订单引用客户实际订单表里根本没有客户编码字段客户名称直接REDUNDANT地冗余在订单表里。所以这个阶段的动作是按矩阵逐条导出主数据表和业务数据表检查引用字段是否真实存在。下面用Oracle EBS的常见表结构做示例。不同ERP的表名不同但查询逻辑通用主数据表用编码做主键业务数据表通过外键字段LEFT JOIN主数据表。-- 导出客户主数据Oracle EBS 客户主表 SELECT customer_id, customer_number, customer_name, nvl(status, A) AS status, creation_date, last_update_date FROM ar.hz_customers WHERE nvl(status, A) A; -- 导出销售订单头关联客户主数据检查外键是否都能匹配 SELECT ord.order_number, ord.book_date, ord.sold_to_customer_id, cus.customer_number, cus.customer_name FROM oe.oe_order_headers_all ord LEFT JOIN ar.hz_customers cus ON ord.sold_to_customer_id cus.customer_id WHERE ord.book_date DATE 2024-01-01;逻辑说明第一段查询客户主数据用NVL把空状态当成A过滤保证只导出有效客户。第二段是关系验证查询重点看sold_to_customer_id能不能在客户主表里匹配上。LEFT JOIN保证所有订单都出现在结果里如果customer_number是NULL说明存在孤儿引用。参数说明Oracle里DATE 2024-01-01是标准日期字面量不要写成TO_DATE(2024-01-01,YYYY-MM-DD)前者可读性更好。customer_id是内部IDcustomer_number是业务编码做关系分析时尽量输出业务编码方便非技术人员看懂。如果你面对的是SAP系统主数据表KNA1存客户主数据、VBAK存销售订单头、VBAP存销售订单行。查询逻辑一样VBAK的KUNNR引用KNA1的KUNNRVBAP的MATNR引用MARA的MATNR。用友U8的客户档案在Customer表销售订单头在SaleOrder也是同一个套路。关键不是背表名而是先跑通主表LEFT JOIN子表这条验证思路。4.2 用Python检查引用完整性与孤儿数据SQL导出只是第一步数据量一上来眼睛看不完必须用脚本批量检查。我这里用Pythonpandas做最经典的孤儿数据扫描确认业务数据里引用的主数据编码在主数据表里是否真正存在。import pandas as pd # 读取导出的主数据与业务数据 # 注意编码字段全部按字符串读取防止前导零丢失 customer_df pd.read_csv(mdm_customer.csv, dtype{customer_code: str}) order_df pd.read_csv(o2c_sales_order.csv, dtype{customer_code: str}) # 左连接并标记孤儿记录业务数据引用了主数据中不存在的编码 merged order_df.merge( customer_df[[customer_code]], oncustomer_code, howleft, indicatorTrue ) orphan merged[merged[_merge] left_only] print(f孤儿订单行数: {len(orphan)}) if not orphan.empty: orphan.to_csv(orphan_orders.csv, indexFalse)逻辑说明dtype{customer_code: str}把编码列强制转成字符串避免Excel导出时物料编码变成科学计数法或数字格式丢前导零。indicatorTrue会让merge结果多一列_mergeleft_only表示左侧的订单表有没有在客户主数据表中匹配上的行这些就是孤儿数据。输出文件和打印计数可以让你在17页PPT里直接写订单引用客户匹配率99.86%发现15条孤儿记录这类有说服力的数字。参数说明如果主数据表有2万条、业务数据有60万条这个脚本运行时间在几秒内。如果数据量到千万级建议加一个条件过滤比如只检查本年度业务单据避免每次全量扫描。还有一个可调参数是howleft——如果你想知道客户主数据里有哪些客户从来没下过单改成howright即可。4.3 生成关系图与文档从PowerDesigner到draw.io的落地数据验证通过后要把关系可视化。常用做法有三种按团队条件选。第一种直接用数据库建模工具反向生成。Oracle SQL Developer的数据模型器、PowerDesigner都能连接ERP数据库选择若干表后自动生成外键关系图。好处是准——图里的实线虚线都是真实外键坏处是ERP表太多直接把几百张表扔进来会画成一团乱麻。所以我通常只选择关系矩阵里列出的核心表控制在15张以内。第二种用draw.io手工画分层图。我习惯画三层最底层是主数据实体客户、物料、供应商、科目中间层是业务单据头订单、采购单、生产订单、凭证头最上层是单据行/流水订单行、库存过账行、凭证明细。层与层之间用带箭头的连线表示引用关系线上标注KUNNRVBAK-KUNNR。这样画出来的图业务人员看得懂开发人员也能照图定位字段。第三种直接生成HTML/PDF关系文档。把关系矩阵导出成口袋书每个主数据实体一节后面跟着被哪些业务数据引用、引用字段是什么、校验规则是什么。这种文档比PPT更实用因为对口人员可以在系统报错时快速查这个物料被哪些单据引用为什么不能删。落到你的17页PPT交付时我的建议是前5页放主数据清单和业务数据清单中间7页放关系图一张总览六张链路销售到收款、采购到付款、生产到成本、库存到存货、资产到折旧、总账到报表最后5页放校验规则和问题清单。这样每页都有干货不是套模板凑数。5. 数据关系梳理的5个坑编码不一致、孤儿数据、状态穿越与同步延迟这一章直接给血泪经验。以下5个问题几乎每个ERP数据治理项目里都至少中两条。坑1编码前导零丢失现象业务系统导出的客户编码是001234Excel打开后自动变成1234再导入分析平台后匹配不上主数据报无效客户编码。原因Excel默认把纯数字列当数值处理前导零被吃掉。这不是ERP的错是数据导出导入环节的格式问题但最终会表现为主数据和业务数据对不上。解决导出的CSV/Excel在生成时就把编码列设为文本格式Python读取时用dtype{customer_code: str}强制转字符串如果已经丢了用zfill(6)补零还原。最稳妥的做法是固定编码长度物料编码20位、客户编码6位从源头杜绝歧义。坑2物理删除了主数据现象某物料因停产被管理员从ERP里物理删除半年后一张历史采购订单在报表里显示物料名称为空月度对账时这笔采购无法匹配到物料成本。原因主数据的物理删除是灾难性的。业务单据永远引用历史主数据一旦物理消失所有历史单据都成了孤儿。很多开发人员图省事直接DELETE而不是置状态字段为I加有效期截止。解决所有主数据表一律禁止物理删除只允许逻辑删除status改I并设置valid_to为删除当天。如果历史原因已经删了需要从备份表恢复并标记为失效状态恢复不了的话在关系矩阵中记录该编码为历史失效编码报表查询时用LEFT JOIN并在缺失时显示编码本身。坑3状态穿越——单据引用了未来才生效的主数据现象一张销售订单日期是2024-07-01但订单引用的客户主数据valid_from是2024-08-01。账务月结时财务发现这笔订单的客户信用评估还没上线导致风险敞口漏判。原因主数据的有效期设置错误或者业务系统允许录入未来生效的主数据。更隐蔽的原因是把业务单据日期手工改到过去或未来绕过有效期校验。解决在业务单据保存触发器或应用层校验里增加条件业务日期 BETWEEN 主数据.valid_from AND 主数据.valid_to。像Oracle可以建BEFORE INSERT触发器发现状态穿越就抛出异常。参数上主数据的valid_to默认9999-12-31但valid_from一定要在单据录入时实时校验。坑4主数据同步延迟导致新单据引用旧属性现象MDM系统改了客户付款条件但ERP本地客户表继续保存旧数据。当天新单据按旧付款条件执行一个月后对账发现多扣了两个点的现金折扣。原因主数据在MDM侧更新了但ERP的本地副本同步任务延迟6小时或者接口失败后没有重推机制。远程审核ERP单据时审核界面展示的客户名称、付款条件都是从本地副本读的同步没跑审核就是看黑匣子。解决给主数据表增加last_update_date字段增量同步只取last_update_date 上次同步时间的记录。同步完成后做一次比对脚本对比MDM和ERP两边主数据表的MD5或逐字段diff不一致的自动告警。同步频率要写入关系矩阵客户、物料这类每天至少同步4次科目主数据可以日终批处理。坑5同义不同码——一个实体在多个系统有多个编码现象一个客户在CRM里编码是CRMC001234在ERP里编码是10000034。订单导出的客户编码无法和CRM的客户报表对上销售总监要的客户全生命周期视图做不出来。原因没有建立跨系统的客户主数据统一视图也没有编码映射表。很多集团ERP和CRM各自维护客户靠实施时人工对应后面新增客户就漏了。解决在关系矩阵之外再建一张编码映射表ENTITY_TYPE, ERP_CODE, CRM_CODE, MAP_STATUS。业务数据表引用哪个系统的编码就通过映射表转换。注意映射关系本身也是治理对象必须记录建立时间、有效期间、负责人。这个问题延伸到医疗数据领域也一样医疗本体和主数据区别在于本体是概念模型、主数据是可被业务系统引用的实例数据但同义不同码的病历诊断编码、手术编码映射在所有行业都是同一个坑。排查时不要只盯着数据本身。现象只是表象先查数据在哪一层断的是源系统就没这个编码还是同步丢了还是转换规则写错。按这个顺序查比瞎猜快得多。6. 进阶把关系结果做成数据血缘检查防止豪华版PPT变成一次性交付关系图和矩阵做完如果不变成自动检查规则三个月后再看就是废纸一张。我最常做的落地动作是把每一对关系写成一个校验视图挂进数据库定时任务。下面是一个综合校验视图的例子一次检查三类问题孤儿引用、状态穿越、有效期失效。基于第2章的建表演示。CREATE OR REPLACE VIEW v_check_order_master AS SELECT o.order_id, o.order_date, o.customer_code, c.customer_name, CASE WHEN c.customer_code IS NULL THEN 孤儿引用 WHEN o.order_date c.valid_from THEN 引用未来主数据 WHEN o.order_date c.valid_to THEN 引用失效主数据 ELSE 正常 END AS check_result FROM o2c_sales_order o LEFT JOIN mdm_customer c ON o.customer_code c.customer_code WHERE c.customer_code IS NULL OR o.order_date c.valid_from OR o.order_date c.valid_to;逻辑说明LEFT JOIN保证订单全部保留WHERE条件筛出三类异常。check_result用CASE给出可读的异常类型方便后续在告警平台里按类型分组统计。这个视图可以每天跑一次把结果写入一张datas_quality_check_log表保留30天做趋势分析。这样做的价值是你的17页PPT交付后不是躺在硬盘里而是转化成了一组可执行的校验规则。后面再遇到某个客户编码在订单里查不到直接跑这个视图五分钟定位是主数据删除、同步延迟还是单据录入错误。我做第一个ERP主数据治理项目时就是画完图、写完矩阵就交付了结果下个月财务对账翻车连夜查了三个小时发现是同步接口挂了。从那以后我要求每张关系图必须有对应的SQL校验没有校验的关系图不允许放进交付文档。这个习惯救了我很多次希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑