spool导数处理数据格式&空格问题

最近使用spool导数,出现导出的数据科学计数法、小数位数丢失、字段间补了很多空格,网上搜索了一圈采取的措施:

1.解决数据格式问题

使用to_char函数,例如to_char(num,‘9999.99’)

2.解决字段间空格问题

导出的查询sql字段间使用||加分隔符的方式连接起来,如

select COLUMN_NAME||'~'||DATA_TYPE||'~'||DATA_LENGTH||'~'||DATA_PRECISION||'~'||DATA_SCALE from user_tab_columns

实际使用的过程中,发现导出number型字段的时候,字段间还是自动补了空格,这个时候,可以在to_char函数外嵌套replace函数,去空格,例如:

select COLUMN_NAME||'~'||DATA_TYPE||'~'||replace(to_char(DATA_LENGTH,'99999'),' ','')||'~'||DATA_PRECISION||'~'||DATA_SCALE from user_tab_columns

如果表字段比较少,需要处理的表也少的话,我们可以直接把导出的sql写好;表字段超多,需要处理的表也多的话,再手写就比较麻烦了,下面介绍一个我自己写的一个只要获取到表名,就能按照格式使用约定的分隔符导出的例子。

1.首先我们通过user_tab_columns表,查询表的字段名、字段类型、字段长度等信息,这边要注意,表名要大写

value1=`sqlplus -S "${orauser}/${orapasswd}@${sid}" << !
  set heading off 
  set feedback off
  set pagesize 0
  set verify off
  set echo off
  set linesize 2000
  set sqlblanklines on
  select COLUMN_NAME||'~'||DATA_TYPE||'~'||DATA_LENGTH||'~'||DATA_PRECISION||'~'||DATA_SCALE||'^' from user_tab_columns where table_name = ${table_name} order by column_id;
  exit;
  !`

2.我们循环解析查询到的字段名称、字段类型,并按照不同的类型进行不同处理,我这边的做法是:
如果是字符串类型,就直接用拼接符连接,如果是int型也直接拼接,如果是number带小数型,用to_char限制格式,然后再用replace去空格,再拼接;
要注意一下,最后一个字段需要单独处理

#将返回字符串进行数组切分,分隔符'^'
  OLD_IFS="$IFS"
  IFS="^"
  arr1=($value1)
  IFS="$OLD_IFS"
  
  #通过spool进行导数操作
  echo "开始导出数据">>${log_file}
  echo set echo off newpage 0 space 0 pagesize 0 line 5000 feed off head off trimspool on trimout on >>tem001.sql
  #导出路径及文件名
  echo SPOOL /app/detail/${exp_file_name}>>tem001.sql
  #导出sql拼接
  sql="select "
  echo $sql>>tem001.sql  
  for((y=0;y<${#arr1[@]};y++));do
   OLD_IFS="$IFS"
   IFS="~"
   arr2=(${arr1[${y}]})
   IFS="$OLD_IFS"
   
   #用于判断是否是最后一个字段,是的话,不用再拼接【||chr(29)||】
   int=`expr ${#arr1[@]} - 1`   
   if [ ${y} != ${int} ];then
    if [ ${arr2[1]} = 'NUMBER' ];then
     if [ ${arr2[3]} > 0 ];then
      f='0.'
      for((j=0;j<${arr2[3]}-1;j++));do
       f="9"$f
      done
      for((j=0;j<${arr2[4]}+0;j++));do
       f=$f"9"
      done
      sql1='replace(to_char('${arr2[0]}",'"${f}"'),' ','')||chr(29)||"
     else
      sql1=${arr2[0]}"||chr(29)||"
     fi
    else
     sql1=${arr2[0]}"||chr(29)||"
    fi
   else
    if [ ${arr2[1]} = 'NUMBER' ];then
     if [ ${arr2[3]} > 0 ];then
      f='0.'
      for((j=0;j<${arr2[3]}-1;j++));do
       f="9"$f
      done
      for((j=0;j<${arr2[4]}+0;j++));do
       f=$f"9"
      done
      sql1='replace(to_char('${arr2[0]}",'"${f}"'),' ','')"
     else
      sql1=${arr2[0]}
     fi
    else
     sql1=${arr2[0]}
    fi
   fi
   echo $sql1>>tem001.sql
  done
  #from 表名 条件语句
  sql2="' from "${table_name}" '"${where}"';'"
  
  eval echo $sql2>>tem001.sql
  echo SPOOL OFF>>tem001.sql
  echo quit>>tem001.sql
  #执行导出
  sqlplus ${orauser}/${orapasswd}@${sid} @tem001.sql>>${log_file}

注:在实际操作中发现,发现因为拼接的原因,sql太长,导致报SP2-0027:输入太长(>2499个字符)的错误,拼接过程可以将sql:

select a||'~'||b||'~'||c||'~'||d from table_name

写成:

select 
a||'~'||
b||'~'||
c||'~'||
d
from table_name

可以避免SP2-0027错误。

写脚本过程中的小记录,如果有不对的地方或者可以优化的欢迎留言指正,谢谢~

  • 1
    点赞
  • 1
    收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mikebinbin007

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值