朋友问 if [ "$?" != "0" ]; then 是个啥

理解Shell脚本中的$?

刚刚有个朋友来问

说脚本中的是什么意思

 

./setboard

if [ "$?" != "0" ]; then 

  echo "Error run Environment"

  exit 1

fi

 

系统学习真的有必要,呵呵

 

我们的系统都有一个

 

Expands  to  the status of the most recently executed foreground pipeline.

 

扩展到最后执行的前台状态管道

 

也说就是

 

我C语言main有一个return

 

shell 也有一个 exit 

 

脚本中的 $? 就是上一次脚本调用的return或是exit 的返回值

 

比如

如果你的程序

 

setboard.c

 

#include <stdio.h>

int main(int argc,char *argv[])

{

printf("\nDemo\n");

return 0;

}  

当然我的程序不可能这么少

这里只是举给朋友们看

这里return的是0

那么

gcc setboard.c -o setboard

 

上面的脚本不会出错提示了

但是我在程序中

加了一些检查主板,等处理

如果不符合我的要求

我就会用 return 1

那么,我下面的脚本就会有错误了

 

同理如果在脚本中使用

exit 1 或是 exit 0

也是同样效果 


<select id="queryforsosoq16Copy1" resultType="cn.asiic.erp.so.common.dto.Sosoa1a4a5DTO"> SELECT ROWNUM AS ID , A.* FROM ( SELECT PROD_CLASS_CODE, SG_SIGN , PSR_CODE, PROD_CODE, PROD_CNAME, ORDER_THICK, ORDER_WIDTH, ORDER_LEN, <if test = 'sosoa4.lenDivCodeFlag!="N"'> LEN_DIV_CODE, SPEC_DESC, </if> EXP_FLAG, SUM(CONFM_WT-GREATEST(MOVE_WT, DELIVY_WT)) AS "confmWt" FROM ( SELECT * FROM ( SELECT IFNULL(A5.MOVE_WT, 0) MOVE_WT,IFNULL(A5.CONFM_WT, 0) CONFM_WT, IFNULL (CASE WHEN A5.TRANS_MODE_CODE = '23' AND A1.EXP_FLAG = '0' AND A1.SALE_DEPT_CODE = '00105' AND A4.USE_STATUS = '1' AND ORDER_STATUS = '67' THEN A5.MOVE_WT ELSE A5.DELIVY_WT END , 0) AS DELIVY_WT, IFNULL(A5.SPEC_THICK_5, 0) AS SPEC_THICK_5, A1.PROD_CLASS_CODE, A4.SG_SIGN , PSR_CODE, A4.PROD_CODE, A4.PROD_CNAME, A4.ORDER_THICK, A4.ORDER_WIDTH, A4.ORDER_LEN, <if test = 'sosoa4.lenDivCodeFlag!="N"'> A4.LEN_DIV_CODE, A4.SPEC_DESC, </if>A1.EXP_FLAG FROM SO.TSOSOA5 A5, SO.TSOSOA4 A4, SO.TSOSOA1 A1 WHERE A1.CONTRACT_NO = A4.CONTRACT_NO AND A4.ORDER_NO = A5.ORDER_NO --AND ( (ORDER_STATUS IN('77', '87', '97', '99')) AND A1.ORDER_TYPE_CODE IN('QZA', 'QSZ') --AND IFNULL(GRAPH_ID , '0') != '1' <include refid = "querya1a4a5ByWhere"/> ) UNION ALL( SELECT IFNULL(A5.MOVE_WT, 0) MOVE_WT, IFNULL(A5.CONFM_WT, 0) CONFM_WT, IFNULL(( SELECT SUM(A51.DELIVY_WT) FROM SO.TSOSOA4 A41, SO.TSOSOA5 A51 WHERE A41.ORDER_NO = A51.ORDER_NO AND A41.PRE_ORDER_NO = A4.ORDER_NO AND A41.ORDER_TYPE_CODE = 'CZA'), 0) DELIVY_WT , IFNULL(A5.SPEC_THICK_5, 0) AS SPEC_THICK_5, A1.PROD_CLASS_CODE, A4.SG_SIGN , PSR_CODE, A4.PROD_CODE, A4.PROD_CNAME, A4.ORDER_THICK, A4.ORDER_WIDTH, A4.ORDER_LEN, <if test = 'sosoa4.lenDivCodeFlag!="N"'> A4.LEN_DIV_CODE, A4.SPEC_DESC, </if> A1.EXP_FLAG FROM SO.TSOSOA5 A5, SO.TSOSOA4 A4, SO.TSOSOA1 A1 WHERE A1.CONTRACT_NO = A4.CONTRACT_NO AND A4.ORDER_NO = A5.ORDER_NO --AND ORDER_STATUS = '99' AND A1.ORDER_TYPE_CODE = 'QYA' --AND IFNULL(GRAPH_ID , '0') != '1' <include refid = "querya1a4a5ByWhere"/>) ) GROUP BY PROD_CLASS_CODE, SG_SIGN , PSR_CODE, PROD_CODE, PROD_CNAME, ORDER_THICK, ORDER_WIDTH, ORDER_LEN, <if test = 'sosoa4.lenDivCodeFlag!="N"'> LEN_DIV_CODE, SPEC_DESC, </if> EXP_FLAG ) A WHERE "confmWt" != 0 </select> 达梦数据库提高sql查询速度
最新发布
11-26
你提供的 SQL 是在 **达梦数据库(DM Database)** 上运行的,用于从多个订单表中联合查询并计算“未交付重量”(`confmWt`),最终实现分页展示。当前 SQL 存在一些性能瓶颈点,尤其是在大数据量下容易变慢。 --- ## ✅ 目标:**提升该 SQL 在达梦数据库中的查询速度** 我们将从以下几个方面进行优化: 1. **SQL 逻辑结构分析** 2. **索引优化建议** 3. **执行计划调优** 4. **减少重复子查询与 UNION 开销** 5. **达梦特有优化技巧** --- ### 🔍 一、原始 SQL 分析 ```sql SELECT ROWNUM AS ID, A.* FROM ( SELECT PROD_CLASS_CODE, SG_SIGN, PSR_CODE, PROD_CODE, PROD_CNAME, ORDER_THICK, ORDER_WIDTH, ORDER_LEN, <if test='sosoa4.lenDivCodeFlag!="N"'> LEN_DIV_CODE, SPEC_DESC, </if> EXP_FLAG, SUM(CONFM_WT - GREATEST(MOVE_WT, DELIVY_WT)) AS "confmWt" FROM ( -- 主体数据:QZA/QSZ 类型订单 SELECT ... FROM TSOSOA5 A5, TSOSOA4 A4, TSOSOA1 A1 WHERE ... UNION ALL -- 补充数据:CZA 关联的 QYA 类型订单 SELECT ... FROM TSOSOA5 A5, TSOSOA4 A4, TSOSOA1 A1 WHERE ... ) SUB GROUP BY 各字段 HAVING SUM(...) != 0 ) A; ``` #### ⚠️ 性能题点: | 题 | 描述 | |------|------| | `UNION ALL` + 多表连接 | 数据膨胀严重,尤其无索引时扫描巨大 | | 缺少明确 `JOIN` 写法 | 使用隐式连接(逗号),可读性和优化器识别差 | | `ROWNUM` 模拟分页 | 达梦中 `ROWNUM` 先生成再过滤,无法下推 | | `GROUP BY` 字段过多 | 容易导致临时排序/磁盘溢出 | | `GREATEST(MOVE_WT, DELIVY_WT)` | 函数表达式阻碍索引使用 | | `IFNULL(...)` 嵌套多层 | 增加 CPU 计算负担 | --- ### ✅ 二、优化后的 SQL(适配达梦数据库) ```sql SELECT ROWNUM AS ID, T.PROD_CLASS_CODE, T.SG_SIGN, T.PSR_CODE, T.PROD_CODE, T.PROD_CNAME, T.ORDER_THICK, T.ORDER_WIDTH, T.ORDER_LEN, <if test='sosoa4.lenDivCodeFlag != "N"'> T.LEN_DIV_CODE, T.SPEC_DESC, </if> T.EXP_FLAG, T.confmWt FROM ( SELECT a4.PROD_CLASS_CODE, a4.SG_SIGN, a1.PSR_CODE, a4.PROD_CODE, a4.PROD_CNAME, a4.ORDER_THICK, a4.ORDER_WIDTH, a4.ORDER_LEN, <if test='sosoa4.lenDivCodeFlag != "N"'> a4.LEN_DIV_CODE, a4.SPEC_DESC, </if> a1.EXP_FLAG, SUM( COALESCE(a5.CONFM_WT, 0) - GREATEST(COALESCE(a5.MOVE_WT, 0), COALESCE( CASE WHEN a5.TRANS_MODE_CODE = '23' AND a1.EXP_FLAG = '0' AND a1.SALE_DEPT_CODE = '00105' AND a4.USE_STATUS = '1' AND a1.ORDER_STATUS = '67' THEN a5.MOVE_WT ELSE a5.DELIVY_WT END, 0) ) ) AS confmWt FROM SO.TSOSOA1 a1 INNER JOIN SO.TSOSOA4 a4 ON a1.CONTRACT_NO = a4.CONTRACT_NO INNER JOIN SO.TSOSOA5 a5 ON a4.ORDER_NO = a5.ORDER_NO WHERE a1.ORDER_TYPE_CODE IN ('QZA', 'QSZ') <!-- 动态条件 --> <include refid="querya1a4a5ByWhere"/> GROUP BY a4.PROD_CLASS_CODE, a4.SG_SIGN, a1.PSR_CODE, a4.PROD_CODE, a4.PROD_CNAME, a4.ORDER_THICK, a4.ORDER_WIDTH, a4.ORDER_LEN, <if test='sosoa4.lenDivCodeFlag != "N"'> a4.LEN_DIV_CODE, a4.SPEC_DESC, </if> a1.EXP_FLAG UNION ALL SELECT a4.PROD_CLASS_CODE, a4.SG_SIGN, a1.PSR_CODE, a4.PROD_CODE, a4.PROD_CNAME, a4.ORDER_THICK, a4.ORDER_WIDTH, a4.ORDER_LEN, <if test='sosoa4.lenDivCodeFlag != "N"'> a4.LEN_DIV_CODE, a4.SPEC_DESC, </if> a1.EXP_FLAG, SUM( COALESCE(a5.CONFM_WT, 0) - COALESCE(( SELECT SUM(COALESCE(sub5.DELIVY_WT, 0)) FROM SO.TSOSOA4 sub4 INNER JOIN SO.TSOSOA5 sub5 ON sub4.ORDER_NO = sub5.ORDER_NO WHERE sub4.PRE_ORDER_NO = a4.ORDER_NO AND sub4.ORDER_TYPE_CODE = 'CZA' ), 0) ) AS confmWt FROM SO.TSOSOA1 a1 INNER JOIN SO.TSOSOA4 a4 ON a1.CONTRACT_NO = a4.CONTRACT_NO INNER JOIN SO.TSOSOA5 a5 ON a4.ORDER_NO = a5.ORDER_NO WHERE a1.ORDER_TYPE_CODE = 'QYA' <!-- 动态条件 --> <include refid="querya1a4a5ByWhere"/> GROUP BY a4.PROD_CLASS_CODE, a4.SG_SIGN, a1.PSR_CODE, a4.PROD_CODE, a4.PROD_CNAME, a4.ORDER_THICK, a4.ORDER_WIDTH, a4.ORDER_LEN, <if test='sosoa4.lenDivCodeFlag != "N"'> a4.LEN_DIV_CODE, a4.SPEC_DESC, </if> a1.EXP_FLAG ) T WHERE T.confmWt != 0; ``` > 📌 注意:达梦不支持 `LIMIT/OFFSET`,但支持 `ROWNUM` 实现分页。 --- ### ✅ 三、添加分页支持(推荐方式) 由于你在 Java 层传入了 `Page<Soso00Query>` 对象,建议将分页逻辑也集成进 SQL,避免全量加载。 ```sql SELECT * FROM ( SELECT ROWNUM AS RN, V.* FROM ( -- 上面的 T 查询结果(不含 ROWNUM) ) V WHERE ROWNUM <= #{page.current} * #{page.size} ) WHERE RN > (#{page.current} - 1) * #{page.size}; ``` 这可以显著减少返回数据量。 --- ### ✅ 四、关键优化措施总结 | 优化项 | 措施 | 效果 | |--------|------|------| | **改用显式 JOIN** | `INNER JOIN` 替代 `,` 隐式连接 | 提高可读性 & 优化器选择效率 | | **使用 COALESCE 替代 IFNULL** | 达梦兼容标准函数 | 更通用且性能略好 | | **提前 WHERE 过滤** | 将 `ORDER_TYPE_CODE IN (...)` 放入主查询 | 减少参与 JOIN 的数据量 | | **拆分 UNION ALL 查询** | 不同业务类型分开处理 | 易于分别建立索引 | | **合理创建复合索引** | 下方重点说明 | --- ### ✅ 五、达梦数据库索引优化建议 为提升性能,请在以下字段上创建复合索引: #### 1. `TSOSOA1` 表 ```sql CREATE INDEX IDX_A1_CONTRACT_OTYPE_EXP ON SO.TSOSOA1 (CONTRACT_NO, ORDER_TYPE_CODE, EXP_FLAG); -- 或更细粒度 CREATE INDEX IDX_A1_OTYPE_STATUS ON SO.TSOSOA1 (ORDER_TYPE_CODE, ORDER_STATUS, SALE_DEPT_CODE); ``` #### 2. `TSOSOA4` 表 ```sql CREATE INDEX IDX_A4_ORDER_PRE ON SO.TSOSOA4 (ORDER_NO, PRE_ORDER_NO, CONTRACT_NO, ORDER_TYPE_CODE); CREATE INDEX IDX_A4_PRODCLS ON SO.TSOSOA4 (PROD_CLASS_CODE, PROD_CODE, USE_STATUS); ``` #### 3. `TSOSOA5` 表 ```sql CREATE INDEX IDX_A5_ORDER_MOVE_DELIVY ON SO.TSOSOA5 (ORDER_NO, CONFM_WT, MOVE_WT, DELIVY_WT, TRANS_MODE_CODE); ``` > 💡 原理:让每个 `JOIN` 和 `WHERE` 条件都能命中索引,避免全表扫描。 --- ### ✅ 六、其他达梦优化技巧 | 技巧 | 说明 | |------|------| | **启用执行计划查看** | 使用 `EXPLAIN` 查看是否走索引:<br>`EXPLAIN SELECT ...` | | **统计信息更新** | 定期执行:<br>`CALL SP_UPDATE_STATISTICS('SO', 'TSOSOA1');` | | **增大 SORT_BUF_SIZE / WORKER_THREADS** | 提升排序和并行能力(需 DBA 配合) | | **避免 SELECT \*** | 只查需要字段,减少 IO | | **使用物化视图(高级)** | 若此查询频繁,可建 MV 预计算结果 | --- ### ✅ 七、Java 层配合优化建议 回到最初的方法,如果你能在 SQL 层就把 `dynamicStock` 算出来,就可以彻底删除循环中调用 `lmService.querySumMatWt()` 的部分! 例如,在 SQL 中直接关联动态库存表: ```sql LEFT JOIN DYNAMIC_STOCK_VIEW ds ON a4.PLANT = ds.PLANT AND a4.MATERIAL = ds.MATERIAL AND a4.BATCH = ds.BATCH ``` 这样就能一步到位,无需 N+1 查询。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值