金蝶ERP基础档案数据字典查询与SQL应用实战指南
1. 先弄清楚一件事金蝶的“基础档案”到底指什么先花点时间把“基础档案”这四个字掰开揉碎说明白。不管是做金蝶实施、二次开发还是单纯被领导安排去导一份客户档案Excel你早晚会碰到这个词。基础档案在ERP系统里就是那些被所有单据反复引用的公共基础数据物料、客户、供应商、部门、员工、仓库、会计科目、币别、计量单位、结算方式、收款条件、银行账号诸如此类。它们的特点是“一次维护、处处使用”今天给客户改了名字明天所有关联单据的报表就会跟着变。正因为基础档案是高度复用的业务人员把基础档案建错、建重复、建了又清代价会成倍放大。比如销售订单、出库单、应收单都挂同一个客户编码客户资料一旦建重复月底对账时财务就要在两条记录里猜来猜去。再比如仓库档案只有8个库存报表却出了16行极有可能是把已删除或禁用的仓库也带进了查询。这种问题的根子往往就是查询SQL没有按照基础档案的数据字典来写。“数据字典”这个词听起来很技术说白了就是一张“说明数据库里每一张表、每一个字段、每一种关联关系的说明表”。金蝶的安装界面不会把这个字典直接端到你面前但它就藏在数据库的系统视图和系统表里。你要做的事就是通过SQL语句把它读出来再用它去理解金蝶的业务表。数据库里哪些表存客户客户分组表叫什么联系人和主表怎么关联“禁用”状态存在哪个字段——这些答案全部可以从数据字典里反查出来。常见基础档案典型业务场景为什么要用SQL直接查物料采购、销售、BOM、库存界面导出字段有限无法多表关联客户订单、发货、应收对账重复客户需要按唯一键排查供应商采购入库、应付对账对账时要带出结算方式和银行信息部门/员工费用归属、业绩统计树形结构需要递归查询会计科目凭证、总账、辅助核算大量查询需要过滤明细科目不同版本的金蝶表结构差异非常明显。旧版K/3和KIS用的是传统账套表结构大量表名以t_开头比如t_ICItem物料、t_Item往来单位、t_Account科目、t_Department部门。金蝶云星空这类新平台基础档案表普遍以t_BD_开头像t_BD_MATERIAL、t_BD_Customer、t_BD_Supplier字段命名也从FItemID这类老风格变成了FID、FNumber、FName为主。所以有人拿着一篇老教程里的表名往新系统上套查出来一堆空结果或者报错我一点都不意外。正确姿势只有一条先用数据字典确认真实表结构再写业务SQL。2. 数据字典SQL的三种打开方式2.1 用系统视图查表、查字段SQL Server里查数据字典最常用的是几张系统视图sys.objects、sys.columns、sys.types、sys.schemas再加上老一点但依然好用的SYSOBJECTS、SYSCOLUMNS、SYSTYPES。我在金蝶账套数据库里最常跑的入门查询是这样的SELECT SCHEMA_NAME(o.schema_id) AS SchemaName, o.name AS TableName, c.column_id AS ColumnID, c.name AS ColumnName, tp.name AS DataType, c.max_length AS MaxLength, c.is_nullable AS IsNullable FROM sys.objects o INNER JOIN sys.columns c ON o.object_id c.object_id INNER JOIN sys.types tp ON c.user_type_id tp.user_type_id WHERE o.type U AND o.name LIKE %Customer% ORDER BY o.name, c.column_id;执行完之后你会看到所有名字里带Customer的业务表以及每张表的字段、类型、长度、是否允许为空。这个结果就是数据字典的最小形态。我第一次在金蝶库里跑这种查询时最大的感叹是界面上的“客户编码”“客户名称”在数据库里根本不是想当然的CustCode、CustName而是FNumber、FName这一套而且不同模块的表之间全靠内码FID关联跟界面上看到的编码完全是两套体系。2.2 用系统存储过程快速“解剖”单张表当你已经定位到目标表想快速看这张表的字段明细、索引、约束用系统存储过程sp_help是最快的一句话就完事EXEC sp_help t_BD_Customer;这个命令会一次性返回这张表的列信息、标识列、索引、约束、外键引用等信息量比手工拼系统视图大得多。实际工作中我基本都是先跑sp_help看主表全貌再跑自定义元数据查询看自己关心的字段。两者配合一张表的结构十几秒就能看明白。有个坑要提醒互联网上关于金蝶数据字典的文章很大一部分写于K/3时代字段列表和现在的新版本已经对不上。比如老文档里客户表的字段是FCustID、FNumber、FShortName新版云星空可能就变成了FID、FNumber、FName。所以请把“先查系统表再信参考资料”当默认动作而不是反过来。2.3 建立自己的数据字典查询模板把上面两种方式合并成一个可复用的模板存成SQL脚本或者做成一个自定义视图以后每次接新项目都先执行一遍。我的个人习惯是这样写的-- 金蝶基础档案数据字典查询模板 DECLARE Keyword NVARCHAR(50) BD_; -- 按需改成 Customer、Material、Account 等 SELECT s.name AS SchemaName, o.name AS TableName, c.column_id AS ColumnID, c.name AS ColumnName, tp.name AS DataType, c.max_length AS MaxLength, c.is_nullable AS IsNullable FROM sys.objects o INNER JOIN sys.columns c ON o.object_id c.object_id INNER JOIN sys.types tp ON c.user_type_id tp.user_type_id INNER JOIN sys.schemas s ON o.schema_id s.schema_id WHERE o.type U AND (o.name LIKE % Keyword % OR c.name LIKE % Keyword %) ORDER BY o.name, c.column_id;这段脚本的优点在于你既可以用BD_筛出金蝶云星空的基础档案主表也可以用Item筛出老版本的物料相关表甚至可以拿一个字段名去反查“到底哪些表里有这个名字的字段”。在搞不清楚“名称到底存在哪个字段”的时候这个模板比在几十张表里人工翻找高效太多了。注意不同金蝶版本的数据库名称和表前缀差异很大。执行系统视图查询之前先确认你连的确实是金蝶账套对应的业务数据库而不是master、msdb这类系统数据库更不是别的业务库。只读查询通常问题不大但连错库浪费的时间成本往往比想象中高得多。3. 金蝶基础档案核心表结构盘点3.1 物料产品/商品档案物料档案是制造业和贸易企业最核心的基础档案没有物料表BOM、生产订单、采购、库存全都玩不转。旧版金蝶K/3里物料主表一般是t_ICItem核心字段大致如下字段名含义备注FItemID物料内码关联单据的常用键所有单据都通过它引用物料FNumber物料编码界面展示和录入用一般有唯一性约束FName物料名称基础名称FModel规格型号很多报表和BOM都会用到FUnitID计量单位关联计量单位表查询时要JOINFDefaultLoc默认仓库关联仓库表FDeleted删除标记0未删1已删查询务必过滤FForbid禁用状态禁用物料在业务单据中不可选新版金蝶云星空里物料主表通常叫t_BD_MATERIAL字段命名风格变成FID、FNumber、FName、FSpecification等。不管哪个版本最关键的查询条件一定是删除状态和禁用状态。我见过太多人写SELECT * FROM t_ICItem然后数据翻倍就是没带FDeleted0。倒不是说这句SQL有多错而是它把“已删除的测试物料”和“正常在用物料”搅在一起后续统计成本、库存、BOM用量时所有数字都会跟着歪掉。写物料档案查询时另一个容易踩的地方是计量单位。物料表里的FUnitID存储的通常是单位内码界面上显示的是“个”“件”“箱”这些名称必须把计量单位表JOIN进来才能带出单位名称。金蝶的单位表在老版本中常见t_MeasureUnit新版叫t_BD_UNIT之类。JOIN之后记得给计量单位也加个过滤状态否则可能出现一个物料挂多个历史单位造成的重复行。3.2 客户与供应商档案客户和供应商在ERP里同属往来单位但在表结构上往往是两张独立的表旁边还挂着分组表、联系人表、银行信息表。K/3老版本里客户和供应商都放在t_Item体系下通过FItemClassID区分类别新版云星空则拆成t_BD_Customer和t_BD_Supplier两张独立主表。客户表里比较常见的字段字段名含义备注FCustID 或 FID客户内码单据表通过这个字段关联客户FNumber客户编码唯一性编码查询和匹配的关键FName客户名称常用显示字段FGroupID客户分组关联客户分组表FAddress地址自由文本FTaxNumber税号开票和税务核对用FDeleted / FForbidStatus删除与禁用状态过滤必须带上否则历史数据会混入供应商表的结构几乎和客户表对仗只是字段前缀从Cust变成Supp。写对账、应收、应付类SQL时这两张档案表应该放在FROM子句最前面再通过业务单据表里的内码字段把它们JOIN进来。比如查“近三个月每个客户的发货金额”并不是直接去客户表里捞数据而是先查发货单明细再JOIN客户表带出客户编码和名称。如果只盯着客户表本身你会发现它根本没有业务数量字段。初次接触金蝶数据库的人还容易把“客户分组”当成客户表里的一个文本字段。实际上分组通常存在单独的t_BD_CustomerGroup或t_ItemGroup表里客户表只存一个FGroupID。要带出分组名称必须JOIN一次。这个JOIN看似简单却直接决定了你的客户清单是“裸数据”还是“能直接交给业务看的报表”。3.3 部门、员工与仓库档案部门表在K/3里常见t_Department字段有FDeptID、FNumber、FName、FParentID、FDeleted等员工表常见t_Emp仓库表常见t_Stock。云星空里则对应t_BD_Department、t_BD_Employee、t_BD_STOCK。很多人忽略的一点是部门表通常带树形结构FParentID指向父部门。如果你想统计“某个部门及其所有子部门的费用发生额”光靠一条简单的WHERE FDeptID xxx是拿不全数据的因为子子孙孙部门还有各自的下级。这时候需要递归CTE公用表表达式来处理WITH DeptTree AS ( SELECT FDeptID, FNumber, FName, FParentID FROM t_Department WHERE FDeptID RootID -- 根部门内码 UNION ALL SELECT d.FDeptID, d.FNumber, d.FName, d.FParentID FROM t_Department d INNER JOIN DeptTree t ON d.FParentID t.FDeptID ) SELECT * FROM DeptTree;这段SQL里的RootID是你要展开的部门根节点。跑完之后你会拿到一整个部门分支的清单再拿这个清单去关联业务单据就能准确汇总整个部门树的费用或业绩。这个技巧在处理组织架构频繁调整的公司时特别管用因为历史单据挂在旧部门上而旧部门又可能被挪到新树下面只有递归展开才能避免漏算。仓库档案和部门档案有几个相似点都有内码、编码、名称、删除状态有的版本还支持多级仓库结构。写库存相关SQL时仓库表是必须JJOIN的核心表因为库存数量本身不在仓库表里而在库存余额表或即时库存表里两张表通过仓库内码关联。数据字典在这里的作用就是帮你快速找到“哪个字段是仓库内码”。3.4 会计科目与辅助核算会计科目主表在K/3里是t_Account云星空里一般是t_BD_ACCOUNT。核心字段包括科目内码FAccountID或FID、科目编码FNumber、科目名称FName、级次FLevel、上级科目FParentID、借贷方向FDC、是否明细科目FDetail等。写总账类SQL时务必记住一条底线多做一次“明细科目”过滤。会计科目表里同时躺着汇总科目和明细科目如果你直接按科目编码范围去查很容易把“应收账款”这个汇总科目和它下面的“应收账款—A公司”“应收账款—B公司”都带进来导致凭证查询或余额表数据重复。界面程序通常会在查询条件上自动带出FDetail1而裸SQL可没有这么智能。辅助核算金蝶里也叫核算项目是财务模块非常有特色的设计。简单理解就是把“科目辅助项”组合起来记账比如“应收账款—A客户”“管理费用—市场部—差旅费”。在数据库里这种多维组合往往不是存在一个平面表里而是科目表、核算项目类别表、核算项目明细表、凭证分录表等多张表通过内码彼此关联。想用SQL还原界面上的科目辅助账你得先理清这几张表的关联关系再一层一层JOIN上去。数据字典在这个场景里基本就是导航图没有它你连从哪张表开始都不知道。这里插一句实操心得我见过有人试图直接修改t_Account里的科目编码来满足新的编码规则结果总账模块所有历史凭证的科目显示全部错乱。科目表是最不应该乱动的表之一任何编码变更都应该走系统的科目变更功能而不是在数据库里硬改。数据字典告诉你字段在哪张表它告诉不了你哪些字段绝对不能碰这是两回事。4. 实战演练从“找表”到“出数据”这一节我们走一遍完整实操。假设你从没查过金蝶基础档案需求也很朴素“把系统里所有客户档案包括客户编码、客户名称、客户分组、联系人电话、是否禁用导成Excel。”我按四步带你在SQL Server Management Studio里完成。4.1 第一步用关键词锁定候选表先用第2节的模板把关键词换成Customer看看库里到底有哪些表DECLARE Keyword NVARCHAR(50) Customer; SELECT s.name AS SchemaName, o.name AS TableName, c.column_id AS ColumnID, c.name AS ColumnName, tp.name AS DataType, c.max_length AS MaxLength, c.is_nullable AS IsNullable FROM sys.objects o INNER JOIN sys.columns c ON o.object_id c.object_id INNER JOIN sys.types tp ON c.user_type_id tp.user_type_id INNER JOIN sys.schemas s ON o.schema_id s.schema_id WHERE o.type U AND (o.name LIKE % Keyword % OR c.name LIKE % Keyword %) ORDER BY o.name, c.column_id;跑完你会发现名字里带Customer的表不止一张可能有t_BD_Customer、t_BD_CustomerBank、t_BD_CustomerContact、t_BD_CustomerGroup等。这很正常金蝶把“客户”这个业务对象拆成了主表、银行表、联系人表、分组表等多个物理表。先不要慌挑出主表和分组表就行。4.2 第二步确认主表关键字段对主表执行sp_helpEXEC sp_help t_BD_Customer;你会看到主表的字段清单从中找到我们需要的字段客户编码通常叫FNumber客户名称叫FName分组字段叫FGroupID状态字段可能是FForbidStatus。不要想当然猜字段名我就在“编码”这个字段上吃过亏有的版本叫FNumber有的版本叫FCode还有老版本叫FNUMBER大小写不敏感但语义也不完全一样。以sp_help实际返回为准。4.3 第三步写查询并关联分组表既然要带出“分组”就需要JOIN客户分组表SELECT c.FNumber AS 客户编码, c.FName AS 客户名称, g.FName AS 客户分组, ct.FNumber AS 联系人电话, CASE WHEN c.FForbidStatus 1 THEN 禁用 ELSE 正常 END AS 状态 FROM t_BD_Customer c LEFT JOIN t_BD_CustomerGroup g ON c.FGroupID g.FID LEFT JOIN t_BD_CustomerContact ct ON c.FID ct.FCustomerID WHERE c.FDeleted 0;注意我用了LEFT JOIN因为不是每个客户都一定填了联系人或分组用INNER JOIN会把“没维护联系人电话”的客户直接过滤掉导致导出数据少掉一大截。这个细节看起来不起眼实际导出后对不上数的时候十有八九都是JOIN类型选错。如果有多个联系人客户表会带出多条重复客户行这时候需要按业务需要决定是否只取一条主联系人比如用ROW_NUMBER()按客户分组排序取电话优先的那行。4.4 第四步导出前检查数量写完后不要直接导出先做一次数量校验-- 客户全量 SELECT COUNT(*) AS TotalCount FROM t_BD_Customer WHERE FDeleted 0; -- 带联系人的客户量 SELECT COUNT(DISTINCT c.FID) AS ContactedCount FROM t_BD_Customer c INNER JOIN t_BD_CustomerContact ct ON c.FID ct.FCustomerID WHERE c.FDeleted 0;两个数字如果完全一样说明所有客户都有关联联系人如果后面的数比前面小说明有客户没录联系人。如果你希望全量客户都要保留就必须用LEFT JOIN哪怕某客户没有联系人也要以客户表为主体带出一行空电话。这种“先数量、后明细”的习惯能让你少挨很多次“数据怎么少了几条”的批评。导出到Excel之后再抽查几行与金蝶界面比对编码和名称确认无误再发给业务。5. 基础档案SQL的高频问题与避坑5.1 删除标记和禁用状态是头号大坑金蝶几乎所有基础档案表里都有删除标记字段常见的有FDeleted、FForbidStatus、FStatus等。界面上删掉一个档案数据库通常不是真删而是把标记位置为1。如果不加过滤你的查询会把那些“已删除但界面看不到”的记录也带出来。我的建议是每条业务SQL都强制带上FDeleted0或者FStatus1这类状态条件宁可多写一个条件也不要让脏数据流进报表。禁用状态和删除标记是两回事。删除标记表示这条记录在界面上已经没有了禁用状态表示这条记录还在只是不允许在新的业务单据中选择。比如一家客户已经停止合作业务员会把它禁用而不是删除。跑历史单据查询时禁用客户照样要带出来因为历史订单还挂在它名下跑当前客户清单时则通常要过滤掉禁用记录。分清这两者的业务含义比记忆字段名更重要。5.2 编码字段的类型与长度坑基础档案的编码字段FNumber在大多数表里是NVARCHAR类型长度从20到100不等。问题常出在“编码含前导0”和“编码全是数字”的时候。比如客户编码是“00123”Excel表里一保存可能变成“123”但SQL里必须匹配“00123”。写WHERE FNumber 00123没毛病写成WHERE FNumber 123则可能因为隐式类型转换导致索引失效查询速度慢得离谱。另一个相关问题是LIKE模糊匹配的效率。基础档案表动辄几万几十万行如果业务上确实需要模糊搜索客户名称建议写成FName LIKE N%关键词%并在关键过滤字段上建立索引。虽然模糊匹配用不上普通索引的最左前缀但至少编码字段上的精确匹配查询要能用上索引。别为了省事把客户编码和客户名称拼在一起做模糊查询那样性能只会更差。5.3 千万别随意UPDATE基础档案表基础档案是业务单据引用的根数据直接UPDATE可能导致关联单据显示异常、数据追溯断裂。这句话我说过很多次但每次项目里总有人觉得“我就改一个名称字段而已能出什么事”。实际上编码、内码这类被无数表引用的字段被改掉之后历史单据上显示出来的可能就不是你期望的内容了。就算只是改名称也要先确认所有下游报表是否按名称做匹配。我的经验是修数据之前先备份、先测试、再小范围执行最好在测试库上完整验证一遍SQL再动生产库。5.4 权限最小化与安全自查生产数据库的账号建议只给查询权限SELECT不要给增删改权限INSERT/UPDATE/DELETE。需要修数据时走正式的变更流程在指定时间窗口由专人操作。这不是小题大做而是我见过太多因为测试SQL直接贴到生产库执行而闹出事故的案例。数据字典查询本身是只读操作相对安全但你写出来的业务SQL一定要先自己审一遍有没有忘记WHERE有没有可能全表更新有没有把测试条件带到生产环境5.5 字符集和中文乱码问题金蝶账套数据库一般使用SQL Server默认排序规则多为Chinese_PRC_CI_AS。如果查询条件里写中文字面量查不到数据先检查数据库排序规则和表的字段排序规则是否一致再看客户端连接是否设置了正确的字符集。很多时候“明明数据库里能看到中文为什么WHERE条件一写中文就查不出来”的怪问题根源都是排序规则冲突或N前缀缺失。建议在SQL文本里给中文字符串加上N前缀比如WHERE FName N测试客户这个习惯能规避掉大量隐性兼容问题尤其是在不同排序规则的数据库之间做数据比较或迁移的时候。5.6 常见问题快查表症状可能原因排查方向查询返回重复行没过滤删除标记或JOIN了联系人、银行等一对多子表检查FDeleted使用COUNT(DISTINCT) 校验导出后客户/物料少了几条用了INNER JOIN导致无子表记录的主数据被过滤改用LEFT JOIN主表留在FROM左侧中文条件查不到数据排序规则不一致或缺N前缀检查排序规则给中文字面量加N编码明明有值却查不到字段类型是NVARCHAR按数字匹配发生隐式转换编码统一按字符串处理科目余额表数据翻倍没过滤明细科目把汇总科目也带进来了加FDetail1或按科目级次过滤部门汇总金额漏算只查当前部门没带下级部门用递归CTE展开部门树6. 把数据字典思维变成日常习惯最后分享一点个人经验。我在接金蝶相关的数据需求时第一件事永远不是问“要哪张报表”而是先跑一遍数据字典查询把需求里涉及的基础档案表、字段、状态标记全部列出来。这个动作看似多花几分钟实际能省下后面大量返工时间。需求方说“我要导出所有客户”我不能直接信这个“所有”因为界面上看不到的记录、已禁用的记录、测试用的记录都在数据库里躺着只有查数据字典并和业务确认过滤规则才能真正保证导出数据的质量。遇到表结构看不懂的字段也别硬猜。SQL Server的系统视图里除了字段名和类型还有字段说明扩展属性可以这样查看SELECT o.name AS TableName, c.name AS ColumnName, CAST(ep.value AS NVARCHAR(500)) AS Description FROM sys.objects o INNER JOIN sys.columns c ON o.object_id c.object_id LEFT JOIN sys.extended_properties ep ON ep.major_id o.object_id AND ep.minor_id c.column_id WHERE o.type U AND o.name t_BD_Customer AND ep.value IS NOT NULL;金蝶在很多字段上会维护中文说明用这段SQL能直接看到类似“客户编码”“客户名称”“禁用状态”这样的注释比自己翻文档快得多。如果扩展属性为空那就老老实实用业务单据上的字段标题去反查或者找一份老实施顾问留下的字段对照表当参考。总之数据字典不是一本躺在书架上的书而是一个需要反复查询、验证、积累的工具。你每次用它解决一个实际问题你对金蝶数据库的理解就会深一层。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →