ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

055、SELECT单表查询

055、SELECT单表查询 055、SELECT单表查询那天半夜被电话叫醒说生产某个报表转圈圈。登录系统一查不是程序逻辑死循环是SQL在数据库里裸奔。看代码一个订单查询条件字段是vbeln但屏幕参数传进来的是numc类型而表字段是charABAP直接隐式转换索引废掉全表扫描。改成lvbeln p_vbeln类型对齐瞬间从几十秒变成毫秒级。从那以后我养成习惯写SELECT先检查字段类型匹配。单表查询听着简单真正不出坑的没几个。先搭最简单架子SELECT carrid, connid, fldate FROM sflight INTO wa_flight WHERE carrid LH.这段代码不是只取一行是隐式循环每条匹配记录都会把值塞进wa_flight然后往下走。如果你只想拿一条要么补UP TO 1 ROWS要么用SELECT SINGLE。SELECT SINGLE更适合主键或唯一条件比如查物料号、客户号。注意它如果不加WHERE就直接取表里任意一行别这么干。INTO有讲究。你写字段列表INTO工作区里的结构顺序必须一致。比如SELECT a, b, c INTO wa那wa的结构必须是a, b, c这个顺序。如果多了少了数据错位不报错你查半天才发现wa-b里放的是c的值。这坑我踩过当年查一个金浓度查出来的数据忽大忽小折腾一晚上最后发现INTO少了一个字段。不想管顺序用INTO CORRESPONDING FIELDS OF wa按名字匹配但多了个字段映射性能稍差。对于小表无所谓大表别用。还有SELECT *的问题。新手最喜欢SELECT * INTO TABLE gt_itab方便嘛。但*会把表的所有字段都捞过来哪怕你只用两个字段。数据传输量、内存占用、网络开销全被放大。有一次优化报表改掉三个SELECT *直接缩掉一半执行时间。别懒。单表查询最常用的批量写法是SELECT carrid, connid, fldate INTO TABLE gt_flight FROM sflight WHERE carrid LH.这条语句会一次性把所有匹配行塞进内表中间不经过工作区效率比SELECT ... ENDSELECT高得多。记住这个原则能用INTO TABLE完成的事别用循环去APPEND。SELECT ... ENDSELECT适合在循环里处理每行逻辑没法避免时才用。比如你要逐行算金额、填状态那很正常。但如果你只是把数据装进内表后面用那就INTO TABLE。APPENDING和INTO TABLE的区别我再说一嘴。INTO TABLE会先清空接收内表再插入数据APPENDING TABLE不清空在表尾追加。这地方容易迷糊。比如你分多次查不同条件下相同字段想汇总到一个内表用APPENDING TABLE。但你要先确保内表类型匹配且每次查询的字段集合一致。有一次我在循环里查一个个物料描述每次都用INTO TABLE结果内表只有最后一次的数据找了半天原因。改成APPENDING就好了。说到WHERE条件除了还有IN、BETWEEN、LIKE。LIKE匹配通配符%代表任意串_代表一个字符。要注意数据库对LIKE的索引使用前导通配符%开头的条件基本走不了索引。比如查客户姓名以“张”开头写成name LIKE 张%索引还能用写成name LIKE %张完了全表扫。还有如果字段值里有%或_想当普通字符ABAP里可以用ESCAPE关键字指定转义符别生记。另一个坑是SY-SUBRC的判断。SELECT执行完后SY-SUBRC 0表示至少找到一条4表示没找到。很多人忘记检查拿着空内表往下算然后除零报错。建议每条SELECT后面紧跟IF sy-subrc 0. 有数据正常处理 ELSE. 没数据给个友好提示或者退出 ENDIF.别嫌麻烦出错时救你命。小技巧查单条数据时用UP TO 1 ROWS配合INTO TABLE或INTO wa比SELECT SINGLE更灵活。比如你想取最新一条可以按日期降序排列再加UP TO 1 ROWS。而SELECT SINGLE不支持这种排序取最新。排序用ORDER BY单表查询里也常用。比如取销售订单前10条最新SELECT vbeln, erdat INTO TABLE gt_list FROM vbak ORDER BY erdat DESCENDING UP TO 10 ROWS.注意UP TO 10 ROWS必须放在ORDER BY后面别搞反。还有字段类型转换开头那个案例。在WHERE条件里尽量让变量类型和表字段类型一致。如果不一致ABAP会做转换导致谓词无法使用索引。实在避免不了可以用CONV显式转换或者用l_field p_field.做个赋值再查。另外如果字段是NUMC类型你传进去一个带前导零的CHAR也容易出问题。建议平时阅读表结构用SE11看字段类型心里有数。调试技巧事务码ST05打开SQL跟踪执行你的程序然后看生成的SQL语句。如果发现ABAP自动加了一些转换函数或者条件里出现CAST多半是类型不匹配。ST05里还能看到读取的表、次数、扫描行数。我有次发现一个查询实际执行了1000多次结果优化成一次批量查询性能提升几十倍。多花五分钟跟踪SQL值。老生常谈一下写单表查询时先明确你要哪些字段哪些是筛选条件哪些需要排序。别一股脑SELECT *别把条件写宽。比如状态字段它本身索引价值低如果还用LIKE更糟。能精确匹配就精确匹配能缩小范围就缩小范围。字段多了INTO CORRESPONDING也会有额外开销尽量手写字段列表。最后给个经验处理完数据后如果内表很大用完了记得CLEAR或者FREE。FREE会释放内存CLEAR只清空内容。尤其长会话里大内表占用内存不释放影响后续调用。别小看这个我之前见过一个程序跑几次就把内存吃光就是没释放。单表查询是整个ABAP SQL的基石。你把它写干净性能稳一半。后面多表关联、子查询、批量操作全是这些基础规则叠加上去。记住每次SELECT前想想索引想想数据类型想想目的地。不用急掉几次坑就记住了。少点废话多跑ST05。
返回列表