Shell调用sqlplus查询表空间时for循环输出无法追加仅显首条如何解决
问题原因与修复方案
核心错误点
- 循环取值逻辑错误:遍历得到的
val本身就是数组存储的表空间名,不是数组下标,原代码写${array[val]}相当于把表空间名当下标取值,bash默认数字下标,非数字下标会默认转成0,所以每次循环都只会查询第一个表空间,自然只有一条结果。 - spool默认覆盖写入:每次循环执行
spool test.txt都会清空之前的文件内容,就算后续查询出结果也会覆盖之前的内容,最后只会保留最后一次循环的输出。 - 数组读取存在冗余风险:sqlplus返回的结果可能携带空行、多余换行,直接拆分进数组可能产生无效空元素。
修正后的完整代码
按原逻辑调整后可正常输出所有符合条件的表空间数据:
# 第一步:查询使用率超过50%的表空间,过滤空行后存入数组 output1=`sqlplus -s username/password as sysbackup <<END1 set linesize 200 set head off set feedback off select tablespace_name from dba_tablespace_usage_metrics where used_percent > 50; exit; END1` # 按行拆分结果,过滤空行后存入数组,避免分隔符异常问题 readarray -t array < <(echo "$output1" | grep -v '^$') # 清空结果文件避免历史内容干扰 > test.txt # 遍历数组查询每个表空间容量,结果直接追加到文件 for val in "${array[@]}" do sqlplus -s username/password as sysbackup <<END2 >> test.txt set linesize 200 set head off set feedback off SELECT TABLESPACE_NAME, ROUND (SUM (BYTES) / 1048576) FROM DBA_DATA_FILES WHERE TABLESPACE_NAME = '$val' GROUP BY TABLESPACE_NAME; exit; END2 done
更高效的优化方案(无需循环)
可以直接关联两个Oracle字典表,单次查询就能得到所有符合条件的结果,不需要shell循环多次连接数据库,性能更高:
sqlplus -s username/password as sysbackup <<END > test.txt set linesize 200 set head off set feedback off SELECT d.tablespace_name, ROUND (SUM (d.bytes) / 1048576) FROM DBA_DATA_FILES d JOIN dba_tablespace_usage_metrics u ON d.tablespace_name = u.tablespace_name WHERE u.used_percent > 50 GROUP BY d.tablespace_name; exit; END
内容的提问来源于stack exchange,提问作者Divya
相关产品推荐
相关产品推荐

