尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

041、数据字典概述

041、数据字典概述 那天半夜线上报了个错SAP系统里一个自定义表死活激活不了报的是“Dictionary object not consistent”。我第一反应是有人动过域或者数据元素结果查了一圈发现是某位同事在数据字典里直接改了这个表某个字段的“Data Type”长度从CHAR10改成了CHAR20但是下游视图和搜索帮助还停留在旧的CHAR10上。激活时系统要把引用关系全量校验一遍任何不一致都会卡住。那时候我才真正体会到ABAP数据字典不是一张静态的“建表工具”它是一张网所有程序、内表、屏幕字段、数据库表、视图、搜索帮助、锁定对象全都挂在这张网上。你动一个节点整张网的张力都会变。很多零基础的朋友学ABAP一开始接触数据字典就以为是SE11建个表、维护个字段、保存激活完事。等真上了项目被各种激活失败、激活时“滚动”到别的对象、传输请求里莫名其妙多出一堆依赖对象才意识到自己根本不了解数据字典在系统里的地位。这篇就当是带你掀开数据字典的盖子看看里面到底是什么。先把数据字典这词拆开。SAP的ABAP数据字典ABAP Dictionary在事务码SE11里操作它在整个ABAP技术栈里处于底层支撑的位置。数据库表只是它的一个产物它真正的职责是管理元数据——也就是关于数据的数据。你在SE11里定义的东西叫对象包括域、数据元素、表、结构、视图、类型组、搜索帮助、锁定对象。这些对象之间存在引用关系比如“表”引用“数据元素”“数据元素”引用“域”“表”还可以被“视图”引用被“搜索帮助”引用被“程序”里的“类型”引用。这种引用关系是静态的编译时就要解析。因此数据字典一改动所有引用它的对象都可能需要重新生成这也是为什么激活一个表经常带出来一长串其他对象。从真实调试的角度看数据字典最常见的坑就在“域”和“数据元素”这两层。域是字段的“物理户口本”定义数据类型、长度、小数位、大小写敏感、输出长度、值范围。数据元素是字段的“业务标签”定义字段的语义名称、文档、搜索帮助。一个数据元素可以对应一个域一个域可以被多个数据元素复用。比如你建一个物料号字段如果直接用CHAR18不建域也能过但将来所有用这个字段的地方只要有人把长度改成CHAR20你就要逐个去找哪里还写死了CHAR18。而如果通过域来定义改了域所有引用这个域的数据元素和表字段都会收到一致性的变更影响至少系统会明确告诉你影响范围。别图省事跳过域直接建数据元素挂到表上这是很多菜鸟容易踩的坑看似活得快后面还债的时候只想删表跑路。再说表。SE11里建表你要区分“透明表”“结构”“附加结构”。透明表就是数据库中真实存在的物理表表名默认跟ABAP字典中的表名一致字段顺序也一致。结构Structure不占用物理存储只存在于ABAP字典中用来定义程序间的数据载体比如内表的工作区、接口参数、函数模块的传递结构。附加结构Append Structure是别人给你预留的“加塞位”通常用于增强标准表不改变标准表原有字段只在末尾追加字段。注意这里是“末尾”不是“任意位置”如果你试图把增强字段塞到中间系统会报错。别问我怎么知道的我见过有人把附加结构加上强制排序激活时直接炸最后只能删掉重建。建表时有个“Delivery Class”下拉框这里容易选错。它决定了数据在传输请求中的处理方式。A是应用表用于应用数据比如你自己写的业务表。C是客户表一般指客户自定义的数据但也要区分是否允许按客户隔离。L是临时表存临时数据比如批处理会话输入系统重启不保证保留。W是系统表一般不要动。实际项目里自己开发的自定义主数据、配置表通常选A或C具体看是否做跨客户端传输。如果你选错了传输时可能数据没跟过去或者覆盖了目标系统是已有数据。这个坑很隐蔽因为字段定义没报错但上线后数据对不上那时候你根本没心思去查Delivery Class。内部的“Technical Settings”也值得提一嘴。这里设置表空间、数据类、大小类别、缓冲区开关等。数据类有 APPL0主数据、APPL1事务数据、APPL2组织数据、USER用户自定义等。这个分类影响数据存储的物理位置和备份策略不是随便填填。缓冲区开关意味着“是否允许把表数据放入SAP缓存”。主数据表、配置表、低频变更但高频读取的表可以开缓冲能明显提升性能。而事务数据表、日志表千万别开缓冲否则数据不一致你想骂人。零基础朋友建表时可能忽略这个页签但性能问题往往从这埋下。表字段定义里“Data Element”和“Domain”我们说了再看“Field Type”和“Length”。这里有个经典概念ABAP内建类型C字符、N数字文本、D日期、T时间、I整型、F浮点、X十六进制、STRING字符串、XSTRING二进制字符串。但你在表里定义字段一般不直接写类型长度而是通过域来间接确定。域里可以指定“Output Style”和“Value Table”。Value Table是用于外键校验的参考表表示这个字段的值必须存在于那个表的主键里。这个不是强制要求但如果你不设置程序里又手动去查表校验最终就是逻辑散落、性能下降。设置外键后数据完整性由数据库层和SAP层共同保证虽然会带来一点性能开销但值得。讲完表必须讲视图。SE11里视图有四种数据库视图、投影视图、维护视图、帮助视图。数据库视图说白了就是跨表连接查询的映射底层对应一个类似SQL View的东西可以用来在ABAP里直接SELECT。投影视图是把一张表的某些字段暴露出去通常用于数据屏蔽。维护视图是用来生成维护对话框的你可以让业务人员在SM30里维护视图对应的数据而不需要去SE16N直接改表。帮助视图是供搜索帮助使用的用于定义搜索帮助的取值逻辑。很多初学者看到“视图”就以为全是一样的JOIN导致用维护视图做连接查询发现SM30里不能维护数据白费功夫。所以看到视图先分清哪个类型。搜索帮助Search Help也是数据字典的重要成员。它有两种元素搜索帮助定义在数据元素上和集合搜索帮助多个搜索帮助组合。搜索帮助可以基于表字段、视图、或者自定义的方法来取值。它的作用是给输入框提供F4帮助。如果你建了一个表但没建搜索帮助用户在屏幕输入框里按F4就没什么反应或者只能手动输值体验极差。但要注意搜索帮助和表字段之间要通过“Search Help Export/Import”参数映射字段映射错了F4能弹出来但选中的值不回填一样尴尬。锁定对象Lock Object是数据字典里很多人忽略的。它的功能是控制数据并发访问。你在SE11里定义锁定对象自动会生成两个函数模块ENQUEUE_E_XXX和DEQUEUE_E_XXX。程序里调用这两个函数实现逻辑锁。比如你要对一个订单编号加锁防止多个用户同时修改同一单就用锁定对象。如果不做锁数据库层面可能被脏写覆盖。这个不会在表结构上体现但它是数据字典中“保证一致性”的关键工具。切记锁定对象要在“数据字典”里定义而不是在SE37里手写FM。手写容易漏掉错误处理系统标准锁逻辑有详尽的异常管理自己别造轮子。再提一个冷门但关键的点数据字典对象中的“激活Activation”和“调整Adjustment”流程。你在SE11里修改一个对象后激活时系统会进行一致性检查并生成运行时对象runtime object。对于透明表激活会去数据库层面执行DDL修改物理表结构。如果物理表已有大量数据这个操作可能非常慢。更重要的是如果表正在被其他程序使用激活期间可能会遇到锁或者性能瓶颈。SAP有一种技巧是把大表结构调整分散到多个步骤先加字段再填充数据再索引再写程序。别指望一次激活搞定所有那是写小玩具逻辑的思路。从调试实战看你还会遇到一类情况程序里“结构”不一致。ABAP的TSADT、DDTYPES这些类型组里定义了东西但在SE11中修改了一个结构后某个程序里引用该结构的内表却没跟着变。这时候系统会有“版本不一致”的提示有时候甚至不会提示只是运行时报“Subtyping cannot be executed”。这时候激活结构并不能解决因为结构属于数据字典但程序里的内表是本地类型它们之间存在运行时生成关系需要重新生成程序。你就记住了改了数据字典对象引用它的程序多半要重新激活否则运行时会用旧定义。有些情况还需要“程序生成”或者“WB011”之类工具太深的先不展开。零基础朋友最容易混淆的还有“表类型Table Type”和“数据库表Transparent Table”。表类型是一种“结构”用来定义内表的类型比如标准表、排序表、哈希表。你可以用SE11建立一个表类型然后在程序中声明内表时引用它。这是数据类型层面的复用不是物理存储。很多人一开始搞混以为建了表类型就建了表然后去SE11看不到数据正常因为表类型根本不存数据。再说说“域”里那个“Conversion Routine”字段。这是个高级功能但容易踩坑。比如给你自定义字段挂一个转换例程像ALPHA它会在输入/输出时自动做前导零压缩或填补。你定义了域数据元素表字段映射好系统会在读写数据库时自动调用转换例程。但如果你在程序里手动拼接SQL条件时忽略了转换例程查出来的数据就是带不带零的区别。我们调试过一个问题选择屏幕上两个人输入同一个单号一个带前导零一个不带结果查询结果不同。原因就是选择屏幕字段没挂转换例程而数据库表字段挂了。这东西属于隐性逻辑代码不走SE11你都看不到。所以定义域时转换例程不要乱挂挂了就要保证所有程序都经过它。个人经验学习数据字典最好的方式不是背概念而是去SE11里“追依赖关系”。拿一个标准表比如MARV点“Where-Used List”看看它被哪些数据元素、域、视图、搜索帮助、程序引用。顺着这个关系链点下去你就能理解数据字典里每类对象的定位。这比看十篇文档都有用。平时排查问题时也要多用“Where-Used List”反向找影响范围。改一个字段前按“影响分析”查看所有引用它的对象能避免半夜被电话叫醒。真实项目里我养成的习惯是任何数据字典对象都单独放一个传输请求不要和其他代码混在一起。因为数据字典对象的激活顺序和依赖关系非常敏感混在一个请求里容易导致传输时依赖链断裂。比如先传程序、后传表结构程序一激活就找不到了表字段直接报错。所以哪怕懒一点也要为每个SE11对象建独立请求或者至少把“域-数据元素-表-视图-搜索帮助-锁定对象”按dependency打包成一个最小单元。传输之前在SE03里做一下对象依赖检查确认无循环引用、无缺失对象。这些操作看起来繁琐但能避免上线时被坑得欲哭无泪。还有一点不要在开发系统里随意删除数据字典对象。删除一个域或数据元素会牵连到很多表字段。即使有人告诉你“这个字段没人用了”你也要先跑一遍Where-Used并且查询它在动态代码比如动态SQL拼表名中是否被引用——SE11不一定能完全捕捉到动态引用。这种动态引用是隐藏炸弹只能靠代码搜索例如ST程序扫描去找。等上线前杀不掉的业务数据、锁对象、视图全是坑。删除之前建议把对象复制到一个“垃圾命名空间”里比如前缀YDEL先放个把月确认无异常再物理删除。这是我这几年学到的保守策略适用于不敢承担事故风险的朋友。不要迷信“SE11建表就是填字段”数据字典里保存的是一套完整的语义层。域定义规则、数据元素定义语言、表定义存储、视图定义读取路径、搜索帮助定义交互、锁定对象定义并发边界。一套好的数据字典设计会让程序代码非常干净。举个例子你把一个“审批状态”的字段域定义好固定值01未审、02已审、03退回那么程序中就不需要到处写“IF STATUS ‘01’”而是直接用数据元素上的固定值常量或者在代码里定义常量引用AUTH_STATUS的值。虽然这涉及ABAP编程风格但数据字典的语义统一性会直接降低后续维护成本。再补充一个容易出错的地方数据字典里的“字段标签”Field Labels。你在数据元素里定义短、中、长标签用于屏幕上自动生成字段文本。但如果你标签文本太长超过了字段在屏幕上的输出长度系统会自动截断或者出现“***”显示。这种问题排查起来很费劲因为代码没错、表结构没错、就是界面显示异常。所以定义数据元素时尽量按照“短标签10字符、中标签15、长标签20”的SAP建议去做别超过除非你确实知道那个屏幕能用表头标签。标签内容是面向用户的语言注意大小写和缩写别用“ID”这种缩写写“编号”可能更友好除非项目强制外文。“域”里还有一个“Output Length”和“Conversion Routine”的关系。Output Length用来定义屏幕输出字段的宽度它和数据类型的物理长度可以不一样。比如你存一个CHAR18的物料号Output Length设成18没问题。但如果你存一个INT4物理长度是4字节输出长度默认是10位数字可以调成8都没关系。就怕你把Output Length设得小于实际数据能显示的长度数据本身没丢只是显示不全。这个不算严重bug但用户会把界面截图发到群里说“系统坏了”你还得解释数据没坏只是显示宽度问题。趁早定义合理些。说一下“技术设置”中的“Size Category”这影响表预计的行数范围从0到6分别对应不同的初始区大小。你预估表数据量是几百万行就应该选4或5。选小了存储扩展次数多性能下降选大了小表也占大量空间。其实SAP有自动扩展但初始值会影响行的聚簇因子。大部分项目里这个不会成为瓶颈但一定要理解它不是业务意义的“重要性”而是存储预估参数。别因为觉得“这个表很重要”就选6那是误解。对于初学者我还是建议先把SE11左侧对象列表里的每一类都新建一遍哪怕只是练习。建一个域建一个数据元素建一个表建一个结构建一个数据库视图建一个维护视图建一个搜索帮助建一个锁定对象。整个过程按顺序走一遍观察“Where-Used List”的引用如何一步步累积。然后试着改域的长度看系统提示会影响哪些对象。再激活一个表看传输请求里自动包含哪些依赖。你就懂为什么说数据字典是网了。这种练习比背任何概念都有用因为你自己动手摸过那根线再遇到报错时能顺着线头找到问题。调试问题的时候还有一个习惯很重要看激活日志。SE11激活对象后菜单里“功能-日志”或者“环境-激活日志”会显示激活过程的每一步。报错时日志里会明确写“数据元素DUSR1缺失”“域DOMA_XXX不一致”等等。很多零基础朋友一报错就截图提问截图里没有日志没法判断。你自己先看日志再决定求助这能让你少挨骂。另外遇到“对象被锁”这种提示执行SM12解锁前一定要确认没有其他人在做同一个对象的开发否则解锁可能导致对方传输破裂。这属于团队协作素养数据字典领域的锁经常因为跨请求引用而蔓延不是你自己的SE11锁住了整个域可能只是因为某个人正在创建数据元素。耐心等几分钟比乱解锁安全。再说说“增强”和“自定义命名空间”。标准表里加附加结构时附加结构名必须用YY或ZZ开头自定义表名也应该用Y或Z开头。这不是强制要求但SAP的约定是Y/Z开头表示客户对象。传输到生产系统时很多业务插件或者升级程序会忽略Y/Z对象避免冲突。如果你用A或S开头可能跟SAP标准对象重名激活时系统提示“Name already exists”或更严重——覆盖了标准对象实际不会让你覆盖但可能混淆。自己写测试时也要遵守别等到做增强时再改命名重命名牵涉所有引用相当痛苦。“数据字典”还有一个被初学者忽略的入口SE12。SE12是显示模式的SE11只能查看对象定义不能修改。对于开发环境用SE12打开对象查看影响分析很方便因为不会误改。尤其是当你只想快速看一个域的值范围别进SE11免得手滑按到某个字段保存了。养成用SE12看、SE11改的习惯能防止很多“我没改啊”的荒谬事故。有时候你会在代码里看到类似“TYPE mara-matnr”这种语法意思是定义变量类型为表MARA中字段MATNR的数据类型。这种引用方式就是直接在程序里与数据字典建立耦合。如果数据字典中该字段被修改程序重新激活时会自动采用新类型。但如果你在图省事写“TYPE char18”那天改了域的长度你这里就漏了。所以写代码时能用字典类型引用的就别裸写内建类型。这一点在数据字典使用规范中很重要属于代码与字典之间的“契约精神”。零基础阶段养成这个习惯后面做大型开发时能少改很多硬编码。说到硬编码数据字典的“固定值”也可以帮你避免魔法值。比如在域或数据元素上定义固定值的“值表”不是外键表只是值域名里的Fixed Values。你可以把“单据状态”的固定值都定义在域里然后在程序里通过“DOMAIN_NAME”的常量或者“CONSTANTS”引用。这样整个系统里状态值只有一个来源。有人会问这是不是多此一举等到你看到某程序里写“IF STATUS ‘X’”另一个程序里写“IF STATUS ‘A’”第三个程序里写“IF STATUS ‘Y’”而它们实际指的是同一个状态的不同取值时你就明白了。固定值统一管理能够有力制止这种负负得正的地狱。数据字典还有“类型组”Type Group这种老古董现在ABAP引入了“类型组”的替代——就是“Type Group”的增强版“类型组”准确说类型组在ABAP里用TYPE-POOL语句简化定义使用“ABAP TYPE GROUP”创建 TYPE-POOL里面的类型可以被全局引用。不过新版ABAP中更推荐使用“Data Dictionary structures”或“Interface data types”。但很多老项目还在用TYPE-POOL比如ALV的SLIS。你在数据字典里可以看到“类型组”这个对象它本质上不是真正的数据字典对象但是它存在于数据字典中。如果你要修改一个类型组里的定义要小心它被大量程序引用改错了全项目编译失败。我就遇到过有人给类型组加了一个类型导致所有使用该类型组的程序重新生成传输时一堆对象被拉进来。这种“依赖风暴”在数据字典世界里极其常见因为关联关系是静态且连锁的。传输请求中数据字典对象与普通程序对象有个显著不同对象版本和运行时对象是分开的。你修改SE11的表结构会产生新的定义版本但运行时对象比如数据库表定义、ABAP程序里内表结构只有在激活后才会重建。传输时不仅传定义还要传运行时对象。有时你传输一个数据元素会带出许多表结构因为该数据元素被这些表引用目标系统的表结构也需要更新。所以每次SE11操作后看传输请求中的对象列表能帮助你理解这个“网”到底连接了什么。如果不看你永远不知道一个小小的长度变更会牵扯几十张表还会导致目标系统停机窗口需要更长的时间来激活。调试中还有一类奇葩问题数据字典不一致Inconsistent Dictionary Objects。比如数据库表被人在SE14里调整了但字典对象没有更新。或者数据库表已经存在但字典对象没激活。这时你用SE11查看好像没问题用SE16N查表也能查但程序里SELECT时系统报“Database table not active”或“Table content is inconsistent”。这种情况下执行SE14“调整数据库”或SE11“激活”通常能修复。但更麻烦的是有人在开发机中直接删除了数据库表而ABAP字典中还存有表定义激活时系统又试图创建产生冲突。所以请记住对数据字典对象的任何更改都要在SE11/SE14中正式操作别绕过ABAP层直接动DB。到了项目上线后生产系统上的数据字典对象是最高优先级保护对象。生产机上修改一个域的长度、增加一个表字段往往要经过严格审批并且要评估对索引、视图、数据库存储过程、订单数据清洗的影响。有些操作比如在大型透明表上增加一个非空字段并设置默认值可能导致数据库锁表时间很长。聪明的做法先增加一个可空字段程序里做兼容处理跑批量程序填值再通过“字段属性变更”改回非空。这个流程听起来很绕但很多资深顾问都这么干因为安全第一。结尾给点个人经验吧。不要小看数据字典这个入口很多问题看似在程序里根子却在字典。排查性能调优的时候数据字典影响分析往往能帮你找到“同一字段在不同表里类型不一致”的隐忧这种不一致会导致隐式类型转换索引失效SQL慢如蜗牛。你在SE11里能定义类型完美的域却可能因为在某个程序里用了定义不一致的局部类型而破坏它的性能这类问题只有从字典层审视才能明白。做笔记的时候建议把数据字典对象之间的关系画成一张脑图不是为了考试而是为了在项目里快速导航。这张脑图最好能印在你脑子里域是地基数据元素是承重墙表是房间视图是窗户搜索帮助是门铃锁定对象是门锁类型组是房间里预制的家具。这样当你遇到新需求时你会按这个地图去决定要动哪个对象而不是一上来就写代码。最后一句ABAP数据字典是SAP技术体系的“宪法”程序不过是这宪法下的法律条文。你改了宪法所有法律都要重新注释。所以在SE11里点“激活”之前想想那台半夜响个不停的电话你不希望它响就要在那个瞬间多花三分钟检查影响范围。这不是教科书式建议这是被骂出来的习惯。
返回列表