首页 / 资讯中心 / 文章详情

金蝶基础档案SQL查询实战:从表结构到数据字典

金蝶基础档案SQL查询实战:从表结构到数据字典 ★ FEATURED ARTICLE
做金蝶项目时间长了你会发现一个特别真实的现象最基础的基础档案查询反而是最能让人卡壳的。物料、客户、供应商、部门、职员这些在界面上都是点几下就能看到的数据可真要让你写一条SQL把这些档案干净利落地捞出来不少干了几年的实施顾问都得愣一会儿。原因在于金蝶的基础档案在数据库里从来不是“一张表”那么简单而是“主表 辅助表 多语言表 状态标记”的一套组合。本文就围绕金蝶基础档案数据字典这个场景把SQL写法掰开讲清楚包括常见版本的表结构、能直接复制使用的脚本、查询过程中最常见的坑。这套内容适合三类人一是做金蝶二次开发的程序员二是做数据迁移、数据清洗的项目实施人员三是负责ERP系统运维、经常要导出基础档案给业务部门的IT。不管你用的是K3 WISE、K3 Cloud还是云星空核心思路都是通用的差别只在表名和个别字段。我会把那些踩过坑的地方重点标出来尽量让你少走弯路。1. 先从“数据字典”说起为什么基础档案这么难查1.1 基础档案到底包含哪些金蝶里的“基础档案”是一个很宽泛的词日常说得最多的是这几类物料商品、客户、供应商、部门、职员、仓库、会计科目、计量单位、结算方式、币别、银行账号等。这些档案是业务单据的“地基”采购订单要选供应商销售出库要选客户和物料领料单要选部门所有业务流程都建立在这些主数据之上。所以基础档案的数据质量直接决定业务单据能不能做对。从数据库的角度看这些档案分布在不同表里但有一个共同的毛病数据字段散落在多张表中而且很多表名长得并不直观。比如你输入“客户”这两个字在数据库里是找不到一张叫“客户表”的东西的实际是t_BD_Customer再往下还有往来单位、联系人、地址等一群辅助表。这就是为什么很多开发第一次接金蝶项目时光找表就找了一整天。我做项目时的习惯是先建一张“数据字典脑图”把常用档案对应到主表、辅助表、关键字段、状态字段然后再写SQL。没有这张脑图每次查询都是在猜猜数据库结构永远猜不准。1.2 界面能查到为什么还要写SQL可能有朋友会说基础档案在界面上都能查为什么非要写SQL这个问题我经常被问到。界面查询确实方便但遇到下面这些场景界面就顶不住了第一界面导出慢。基础档案数量一多比如物料有几万条界面分页翻起来吃力导出的Excel又要经过服务器处理经常卡住半天。用SQL直连数据库直接在查询分析器里跑完结果秒出。第二界面只能看到部分字段。金蝶的列表界面通常只展示系统预设的字段很多后台字段比如创建时间、修改人、数据状态、自定义字段得一层层点开才行更别提把“系统内码”这种隐藏字段批量导出来。做数据对接、接口开发时往往要的就是这些界面不显示的字段。第三数据清洗和批量核对必须要SQL。项目上线前要做数据迁移要检查档案编码是否规范、分类是否齐全、有没有重复数据。这种批量判断题用SQL做最高效比如一次性找到所有“编码相同但名称不同”的物料界面上根本做不到。第四二次开发需要理解数据库原始逻辑。你写报表、做插件、对接外部系统时业务数据最终还是要落到表字段上不懂底层表结构寸步难行。所以我的结论是界面查询是给业务用户用的SQL查询才是给技术人员和进阶实施用的两者互相补充谁也不能替代谁。1.3 一条贯穿全篇的查表规律金蝶基础档案虽然版本众多表名五花八门但如果你把几十张表放在一起对比会发现一个高度相似的规律我总结成一句话“主表定位、辅助表补全、状态表过滤。”什么意思呢任何一类基础档案都会有一个“主表”负责存最核心的标识信息比如内码、编码、名称以及禁用、删除状态。然后有一到多个“辅助表”负责存具体业务属性比如客户的税号、开户行物料的默认仓库、计价方式。到了云星空这种较新的平台还会多一张“多语言表”专门用来存不同语言环境下的名称和描述。这个规律一旦记住你查任何一类档案就有了路径感先找到主表确认编码和名称再根据业务需求选择要不要关联辅助表最后一定不要忘了过滤状态字段。否则要么把禁用数据查出来要么把已删除的数据查出来出来的结果和界面一对比就对不上。后面所有实战SQL都是按这个规律来设计的。2. 摸清金蝶基础档案的表结构从根上避免瞎查2.1 K3 WISE 与 K3 Cloud 的两个世界金蝶的产品线比较多目前项目里最常见的就是K3 WISE和K3 Cloud云星空。这两个虽然都是金蝶ERP但数据库表结构的设计思路差异非常大不能拿一套脚本通吃。K3 WISE的表名前缀一般是t_表名字段偏短很多表自带中文字段比如FName直接就是名称。常用基础档案表包括t_ICItem物料、t_BD_Customer客户、t_BD_Supplier供应商、t_Item部门/科目等多类别共用、t_Emp职员、t_Stock仓库、t_Account科目、t_MeasureUnit计量单位。这类环境里查基础档案相对直接但要注意共用表的概念。例如t_Item里可能同时存了部门、科目、职员类别等多种数据区分它们的字段通常是FItemClassID不同类别值对应不同档案类型。具体对应关系可以在t_ItemClass表里查不要凭感觉硬猜。K3 Cloud云星空是BOS平台构建的表名一般是T_BD_开头大量使用多语言表。比如物料主表是T_BD_MATERIAL多语言表是T_BD_MATERIAL_L基本辅助表是T_BD_MATERIALBASE库存辅助表是T_BD_MATERIALSTOCK。客户是T_BD_CUSTOMER供应商是T_BD_SUPPLIER每个主表几乎都配一张_L结尾的多语言表。这种设计的好处是支持多国语言和灵活扩展代价就是查询时要多关联一层写SQL会很啰嗦。我建议你在动手之前先确认好项目用的版本和数据库然后找到对应版本的表结构说明别指望一套SQL包打天下。下面的脚本我会分场景给出大家按版本对号入座。2.2 核心字段与状态标记不懂这些等于白查写基础档案查询SQL最核心的字段其实就是这么几个内码、编码、名称、规格型号、状态。它们在不同版本里叫法不同但含义几乎一样。内码是数据库内部的主键K3 WISE里物料叫FItemID客户叫FItemID或FCustID云星空里通常叫FMATERIALID、FCUSTOMERID。内码在界面上看不到但它是关联其他业务表的核心桥梁。你查单据时要用内码去关联而不是用编码。编码和名称是所有档案都必须有的。K3 WISE里常见的是FNumber和FName云星空里主表多语言表上是FNUMBER和FNAME。这里有个坑云星空很多档案的名称放在多语言表里你不关联_L表FNAME可能查出来是NULL或者直接取到一条空记录。规格型号是物料特有的K3里的FModel、FSpecification都属于物料主表自带字段云星空的FSPECIFICATION同样在多语言表中。做物料选型、生成本地物料清单的时候规格型号经常是查询条件一定要确认它在哪张表。状态标记是生命线。K3 WISE最常见的两个状态字段是FForbid禁用和FDeleted逻辑删除。禁用表示这条档案在业务上不能再用了删除表示这条档案已经在数据层面被标记删除。做查询时FForbid 0表示未禁用FDeleted 0表示未删除两个条件通常都要带。云星空的状态字段命名在不同版本有细微差异有些版本用状态字符有些版本用数值标记我建议你在正式写SQL前先通过系统视图或数据字典确认字段名。提醒一句禁用和删除完全是两码事。一条记录可以被禁用但没被删除也可以被删除但没被禁用。如果你只过滤了一个状态结果就会混入另一类“垃圾数据”。我见过不少同事从界面导出数据和SQL对不上账最后查出来就是状态字段漏了。2.3 常用基础档案的表映射关系我整理了一份非常实用的表映射清单是基于最常见的K3 WISE环境写的云星空环境思路一样但表名后缀需要换成对应平台的。这份清单我自己的项目里一直在用查档案时相当于一张“字典索引”档案类型主表辅助表/关联表常用过滤条件物料t_ICItemt_ICItemBase、t_ICItemTextFForbid0客户t_BD_Customert_BD_Ecot、t_BD_Contact、t_BD_AddressFForbid0 AND FDeleted0供应商t_BD_Suppliert_BD_Ecot、t_BD_Contact、t_BD_AddressFForbid0 AND FDeleted0部门/科目t_Itemt_ItemClass确认FItemClassID分类按类别ID过滤职员t_Emp部门表、职员辅助表FForbid0仓库t_Stock仓库属性表FForbid0计量单位t_MeasureUnitt_MeasureGroup无会计科目t_Account科目辅助表FDeleted0这个表不是让你死记硬背的而是告诉你一个规律先确认主表再找辅助表永远不要只盯着一张表看。很多新人一上来就SELECT * FROM t_ICItem然后发现缺少物料属性、单位名称就以为自己找错表了其实只是没有关联辅助表而已。3. 实战SQL基础档案数据字典的落地写法3.1 K3 WISE 物料档案查询脚本先给一份最常用的K3 WISE物料档案查询SQL。这段脚本的目标是查出未禁用的物料把物料编码、名称、规格型号、基本单位、物料属性都带出来。单位名称要从计量单位表里取物料属性要从辅助表里取三张表一起关联SELECT i.FItemID AS 物料内码, i.FNumber AS 物料编码, i.FName AS 物料名称, i.FModel AS 型号, i.FSpecification AS 规格, u.FName AS 基本单位, b.FErpCls AS 物料属性 FROM t_ICItem i LEFT JOIN t_ICItemBase b ON i.FItemID b.FItemID LEFT JOIN t_MeasureUnit u ON b.FUnitID u.FMeasureUnitID WHERE i.FForbid 0 ORDER BY i.FNumber;这段SQL里有几个细节要说明。第一主表t_ICItem我没有用SELECT *而是明确列出需要的字段这是写数据字典SQL的基本素养字段列得清楚别人才知道这个查询到底取了什么。第二用LEFT JOIN而不是INNER JOIN是因为有些物料可能没有关联到计量单位或辅助资料如果用了内连接这些物料会直接消失结果数量和界面就对不上了。第三b.FErpCls是物料属性字段它表示这个物料是外购、自制、委外还是其他类型具体含义需要查阅当前环境的枚举值不同版本取值可能不一样。如果你还需要物料的默认仓库、计价方式、是否启用批次管理那就要继续从t_ICItemBase里取对应字段或关联库存相关表。但我的建议是用多少取多少不要一上来就关联七八张表关联的表越多出重复数据的概率就越大。3.2 客户与供应商档案查询脚本客户和供应商在金蝶里是很典型的主表加辅助表结构。主表t_BD_Customer存客户编码、名称、简称、状态辅助表t_BD_Ecot存往来单位的税务信息、法人、开户行等联系人、联系电话又在另外的表里。以下是一个标准的客户档案查询SELECT c.FItemID AS 客户内码, c.FNumber AS 客户编码, c.FName AS 客户名称, c.FShortName AS 客户简称, e.FTaxNumber AS 税号, e.FAttPerson AS 法人, c.FForbid AS 禁用状态 FROM t_BD_Customer c LEFT JOIN t_BD_Ecot e ON c.FItemID e.FItemID WHERE c.FDeleted 0 AND c.FForbid 0 ORDER BY c.FNumber;这里特别强调一下FDeleted 0。客户档案经常会有逻辑删除操作界面上看不到数据库里还在。如果你不带这个条件后续做销售统计、应收账款分析时这些已删除客户的数据会混进来对账对到怀疑人生。供应商查询跟客户几乎一样只需要把t_BD_Customer换成t_BD_Supplier辅助表的关联字段不变。还有一个经验客户联系人信息不要在一开始就关联。因为一个客户可能有多个联系人你一旦关联联系人表一张客户主记录会变成多行导致整个查询结果行数膨胀。碰到这种情况不要急着去重先想清楚业务上到底是“一客户一联系人”还是“一客户多联系人”再决定怎么关联。3.3 K3 Cloud云星空物料档案查询的差异到了云星空表结构变化最明显的就是多语言表。以物料为例主表T_BD_MATERIAL存编码、内码、状态但名称、规格型号这些文本信息放到了T_BD_MATERIAL_L里基本属性放到了T_BD_MATERIALBASE里。查询时要这样关联SELECT m.FMATERIALID AS 物料内码, m.FNUMBER AS 物料编码, ml.FNAME AS 物料名称, ml.FSPECIFICATION AS 规格, mb.FBASEUNITID AS 基本单位内码 FROM T_BD_MATERIAL m LEFT JOIN T_BD_MATERIAL_L ml ON m.FMATERIALID ml.FMATERIALID LEFT JOIN T_BD_MATERIALBASE mb ON m.FMATERIALID mb.FMATERIALID WHERE ml.FLOCALEID 2052 AND m.FForbidStatus 0;多语言表通过语言标识来区分不同语言环境简体中文的语言标识通常是2052。这个条件很多人第一次写会漏掉结果一条物料查出两条记录一条中文一条英文然后怎么过滤都过滤不掉。另外云星空的禁用字段命名在不同版本里略有不同我示例里用的是FForbidStatus如果你发现当前环境没有这个字段去系统视图里搜一下状态相关的列名很快就能确认。云星空的表结构更规范字段命名也更有规律但也正因为规范多表关联是常态。记不住没关系养成“先用系统视图确认列名再写查询”的习惯能省很多事。3.4 让SQL自带“字典属性”格式、注释与去重写金蝶基础档案SQL我特别看重代码的“字典属性”。什么叫字典属性就是你拿到这条SQL不用再翻任何文档通过注释和字段别名就能知道每个字段是什么、从哪里来、为什么这么筛。所以我建议所有SQL都按统一格式来写。第一每行一个字段字段名前带表别名别写一长串SELECT *。第二中文别名写得越直白越好比如FNumber AS 物料编码导出Excel时表头直接就对了。第三在SQL顶部加注释块写清楚这条SQL的用途、适用版本、更新日期、维护人。这个习惯前期觉得麻烦后期收益巨大尤其是项目交接的时候对方拿到你的SQL文件不用追着你问东问西。去重也是高频率需求。最基础的是DISTINCT但它的作用范围很有限只能去掉完全相同的行。真正让人头疼的是“关联表一对多导致的重复”比如客户档案关联多条联系人记录一张客户就变成多行。这种重复用DISTINCT处理不了因为你查出的行本身数据不同。更可靠的办法是用窗口函数按主键排序并标记序号只取其中一条SELECT * FROM ( SELECT c.FItemID, c.FNumber, c.FName, ROW_NUMBER() OVER (PARTITION BY c.FItemID ORDER BY ct.FEntryID) AS rn FROM t_BD_Customer c LEFT JOIN t_BD_Contact ct ON c.FItemID ct.FItemID ) t WHERE t.rn 1;PARTITION BY按客户内码分组ORDER BY决定保留哪一条最后在外面过滤rn 1这样每个客户只保留一条记录。这个技巧在处理一对多关联、去重取数时非常实用值得收藏。4. 查询中最容易踩的坑与排查技巧4.1 表名记不住先查数据库系统视图金蝶的表和字段实在太多没人能全部记住。我自己也是边查边记最常用的办法是直接问数据库系统视图。以SQL Server为例想找包含“Material”字样的表执行SELECT name FROM sys.tables WHERE name LIKE %Material%;想查某张表里所有列名和类型执行SELECT c.name AS 列名, t.name AS 类型 FROM sys.columns c JOIN sys.types t ON c.user_type_id t.user_type_id WHERE c.object_id OBJECT_ID(t_ICItem);通过系统视图确认表结构比自己瞎翻文档快得多也能避免记错字段名导致SQL直接报错。更重要的是这样查出来的结构是你当前环境真实存在的不会出现文档和库对不上的情况。4.2 查询结果出现重复数据重复数据是写金蝶SQL时遇到最多的异常情况。第一反应不要马上用DISTINCT而是先复现重复场景搞清楚重复是怎么来的。我自己的排查步骤是先只查主表的字段看行数再逐步加上关联表看行数什么时候开始增多。一旦发现加了某张表后行数翻倍那问题一定出在这张表的关联关系上往往是“一对多”造成的。比如客户主表有500条记录关联联系人表之后变成了1200条说明很多客户有多个联系人。此时你要问自己业务上到底需不需要联系人如果只需要客户档案本身那就不要关联联系人表。如果确实需要联系人信息就想清楚是“每个客户取一个默认联系人”还是“每个联系人单独一行”。前者用窗口函数取一条后者就让它多行输出不要强行用DISTINCT把不同联系人信息吃掉。4.3 查不到数据时的排查清单“明明界面上有这个物料为什么SQL查不出来”这个问题我几乎每个项目都会被问到。下面按出现频率从高到低整理一份排查清单第一数据库选错了。金蝶项目有时候一个系统对应多个数据库你连的是测试库界面上是正式库两边数据当然不一样。第二过滤条件太严格。比如FForbid 0对当前表不适用或云星空多语言表的语言标识值不是2052导致关联后过滤掉了所有行。第三名称字段取错了表。云星空里FNAME在多语言表你只查主表得到的是NULL看起来就像没数据。第四编码字段有空格或大小写区分。导入的编码往往带全角空格查询时条件FNumber A001匹配不到改成LTRIM(RTRIM(FNumber)) A001试一试。第五数据本身被逻辑删除了界面上根本看不到但你要查的恰好是这条已删除的数据。排查这种问题时我有一个笨但特别有效的方法把过滤条件逐步拆掉先只查主表看数据在不在再加状态条件看数据会不会消失再加关联表看字段是否从NULL变成有值。拆到最后问题自然就水落石出了。4.4 环境与组件异常的快速判断写SQL时常常会跑偏到环境问题上比如金蝶K3客户端组件配置测试提示“组件 kdsvrmgr 无法正常工作”这其实是客户端中间层组件注册或补丁环境的问题跟你写的SQL没有任何直接关系。很多同事遇到这类报错后把SQL反复改来改去结果一点用都没有。我的建议是区分两个层面查数据库数据用数据库工具比如SQL Server Management Studio、Navicat或金蝶自带的查询分析器直接连库执行可以不依赖客户端组件。如果你的目标是“查基础档案”那就不必被中间件提示干扰。至于金蝶云 closetoolK3反过账工具这类单据操作工具属于业务单据处理范畴跟基础档案数据字典的SQL查询不是一回事别混淆。真遇到组件报错优先检查当前客户端补丁版本、组件注册状态和网络权限而不是改SQL。5. 把数据字典沉淀下来长期维护的实操心得5.1 建立你自己的SQL字典目录基础档案查询脚本写多了以后你会发现很多查询是可以复用的。我习惯在本地建一个目录叫“金蝶基础档案字典”下面的SQL文件按编号命名01_物料档案.sql、02_客户档案.sql、03_供应商档案.sql、04_部门职员.sql……每个文件顶部都写清楚适用版本、核心表、最后验证日期。这个目录就是我的“个人版数据字典”项目成员谁要查数据直接从这里拷贝脚本比重新写高效得多。这样做还有个好处当金蝶打补丁导致字段变化时你会第一时间从自己维护的脚本里发现差异。比如某天跑02_客户档案.sql突然报“列名无效”那说明表结构变了马上重新查一下系统视图更新脚本。这种维护节奏比临时查库要安全得多。5.2 从“会查”到“会校验”SQL写出来能跑通只是第一步查询结果是否能和界面数据对上才是真正检验你表理解对不对的关键。我每次写完一个档案查询都会做三个校验动作第一个是总数校验拿SQL查出来的行数和界面上筛选后的记录数做对比第二个是抽样校验随机抽3到5条记录把SQL返回的编码、名称、状态和界面上的明细页比对第三个是编码唯一性校验用GROUP BY FNumber HAVING COUNT(*) 1看看有没有重复编码。如果三个校验都能通过那这条SQL基本可以放心用。如果对不上不要急着怀疑金蝶系统有问题先按第4章的排查清单走一遍绝大多数问题都出在状态字段过滤或关联关系上。我个人在实际操作中的体会是金蝶基础档案的SQL查询难点从来不是SQL语法本身而是对表结构的理解和对状态的敬畏。写多了你会发现真正值钱的经验就是知道“查这个字段要去哪张表”以及“千万要过滤哪个状态字段”。把这些经验沉淀成自己的数据字典比复制十份晦涩的官方文档都管用。最后再分享一个我自己的小习惯每次写完基础档案查询我都会顺手查一下目标表的系统视图把新增或变更的字段备注到字典里。这样在下一次做数据清洗、报表开发或系统对接的时候能省下很多来回确认的时间。金蝶的版本迭代很快别让手里的脚本停在两年前数据和字典都需要常更常新。
阅读完成 · 觉得有帮助?
咨询建站