zoukankan      html  css  js  c++  java
  • Shell同步数据到oracle数据库

      某数据库有几张表更新,本地数据库增量更新数据,用脚本定时执行实现。

      由于无blob/clob字段,使用sqlldr导入数据:查询目的数据库,以"|"分割导出所有数据,保存在./data/tablename.new

      比较 tablename.new和tablename.old,将 tablename.new有,而tablename.old没有的数据更新至目的数据库,并添加至tablename.old
      ./data/tablename.ctl存放sqlldr控制文件
      ./log 存放相关日志

      执行时发现bash中的while创建了子shell,不能保存变量的值,解决办法:

      1、使用其他shell,如:ksh

      2、形如 while read line ;do ... ;done < file

      代码如下:

      

      1 #!/usr/bin/ksh 
      2 
      3 DEBUG="false"
      4 if [ $DEBUG = "true" ];then
      5     orig_dir="."
      6 else
      7     cd
      8     . ./.profile
      9     orig_dir="${HOME}"
     10 fi
     11 v_date=`date +%Y%m%d%H%M%S`
     12 ###############################################################################
     13 # 日志文件,大于20M时压缩半数行
     14 cd $orig_dir
     15 log="$orig_dir/log/alpha.log"
     16 [ ! -d $orig_dir/log ] && mkdir $orig_dir/log
     17 [ ! -d $orig_dir/cfg ] && mkdir $orig_dir/cfg
     18 [ ! -d $orig_dir/data ] && mkdir $orig_dir/data
     19 if [ -e $log ];then
     20     log_size=`ls -l $log | awk '{printf("%d",$5)}'`
     21     if [ -n "$log_size" -a $log_size -gt 20971520 ];then
     22         half_line=`awk 'END{printf("%d",NR/2)}' $log`
     23         perl -ni -e "print if($.>$half_line)" $log
     24     fi
     25 fi
     26 ###############################################################################
     27 # 写日志
     28 wlog() {
     29     echo "`date +%Y-%m-%d' '%H:%M:%S`: $*">>$log
     30 }
     31 ###############################################################################
     32 # 函数:get_col_type 获取列、类型 
     33 # 传递参数:用户名 密码 数据库名 表所有者 表名
     34  get_col_type() {
     35     db_user=$1
     36     db_pass=$2
     37     db_name=$3
     38     tb_own=$4
     39     tb_name=$5
     40     tmp=./cfg/${tb_name}.tmp
     41     tb_name="${tb_own}.${tb_name}"
     42 sqlplus ${db_user}/${db_pass}@${db_name}<<EOF
     43     set heading off feedback off pagesize 0 verify off echo off
     44     spool $tmp
     45         desc ${tb_name};
     46     spool off
     47     quit
     48 EOF
     49 }
     50 ###############################################################################
     51 # 函数:make_ctl 生成控制文件
     52 # 传递参数:目的表名
     53  make_ctl() {
     54     d_name=$1
     55     ctl_file=./data/${d_name}.ctl
     56     echo "load data" > $ctl_file
     57     echo "infile './data/${d_name}.unl'" >> $ctl_file
     58     echo "append into table ${d_name}" >> $ctl_file
     59     echo "fields terminated by '|'" >> $ctl_file
     60     echo "(" >> $ctl_file
     61     cat ./cfg/${d_name}.ini|grep -v '^[ 	]*$'|grep -v '^#'|while read column col_type
     62     do
     63         case $col_type in
     64             NUMBER|VARCHAR|VARCHAR2) 
     65                 echo "$column," >> $ctl_file ;;
     66             DATE)
     67                 echo "$column "to_date(:$column,'yyyymmddhh24miss')"," >> $ctl_file ;;
     68             *)
     69                 wlog "未识别的类型:$col_type" ;;
     70         esac
     71     done
     72     echo ")" >> $ctl_file
     73     # 替换末尾的,)为)
     74     perl -pi -e 'undef $/;s/,
    ?
    )/
    )/' $ctl_file
     75 }
     76 
     77 ###############################################################################
     78 # 函数:select_sql 查询数据
     79 # 传递参数:用户名 密码 数据库名 数据文件名 表所有者 查询语句 表名
     80 # select CALL_ID||'|'||to_char(END_TIME,'yyyymmddhh24miss')||'|'||CALLER||'|'||SERVICE_NO||'|'||CALL_PURPOSE from tablename; 
     81  select_sql() {
     82     db_user=$1
     83     db_pass=$2
     84     db_name=$3
     85     data_file=$4
     86     tb_own=$5
     87     sql_line=$6
     88     tb_name=$7
     89     sql_line="$sql_line from ${tb_own}.${tb_name}"
     90     wlog "查询sql:$sql_line"
     91     # set closep '|'
     92 sqlplus -S /nolog<<EOF
     93     set heading off feedback off newpage none pagesize 0 echo off termout off trimout on trimspool on linesize 800
     94     conn ${db_user}/${db_pass}@${db_name}
     95     spool ${data_file} 
     96       $sql_line;
     97     spool off
     98     quit
     99 EOF
    100 }
    101 
    102 ###############################################################################
    103 # 函数:handle 处理数据
    104 # 传递参数:配置文件
    105  handle() {
    106     table_name=$1
    107     cat $table_name|grep -v '^#'|while read suser sname dname
    108     do
    109         # 如果dname为空,默认使用sname
    110         [ -z "$dname" ] && dname=$sname
    111         sname=`echo $sname | tr 'A-Z' 'a-z'`
    112         dname=`echo $dname | tr 'A-Z' 'a-z'`
    113     
    114         [ -e ./log/${dname}.log ] && : > ./log/${dname}.log
    115         [ -e ./log/${dname}.bad ] && : > ./log/${dname}.bad
    116         [ -e ./log/${dname}.unl ] && : > ./log/${dname}.unl
    117 
    118         if [ ! -e ./cfg/${dname}.ini ];then
    119             wlog "不存在./cfg/${dname}.ini,开始获取${dname}列配置..."
    120             get_col_type dest_db_user dest_db_pass DBNAME dest_db_user $dname
    121             cat ./cfg/${dname}.tmp|grep -v "^SQL>" |grep -v " Name " |grep -v " -------" | tr -d '15'|awk '{gsub(/[0-9]?([0-9]+)/,"",$0);print $1,$NF}' > ./cfg/${dname}.ini    
    122         fi        
    123         wlog "根据./cfg/${dname}.ini拼接查询sql..."
    124         wlog "${dname}列配置为:"
    125         line="select"
    126         cat ./cfg/${dname}.ini|grep -v '^[ 	]*$'|grep -v '^#'|while read column col_type
    127         do
    128             wlog "$column $col_type"
    129             case $col_type in
    130                 NUMBER|VARCHAR|VARCHAR2)
    131                     line="${line} $column;" ;;
    132                 DATE)
    133                     line="${line} to_char($column,'yyyymmddhh24miss');" ;;
    134                 *)
    135                     wlog "未识别的类型:$col_type" ;;
    136             esac
    137         done
    138         [ $DEBUG = "true" ] && wlog "line:$line"
    139         # 去掉最后一个分号,替换所有分号为|
    140         line=${line%;*}
    141         line=${line//,/"||'|'||"}
    142         [ $DEBUG = "true" ] && wlog "line:$line"
    143         
    144         # 不存在$sname.old时创建$sname.old
    145         [ ! -e ./data/${sname}.old ] && touch ./data/${sname}.old
    146         
    147         if [ ! -s ./data/${sname}.old ];then
    148             wlog "./data/${sname}.old为空,从目的表获取数据..."
    149             select_sql dest_db_user dest_db_pass DBNAME ./data/${sname}.old dest_db_user "$line" $dname
    150             wlog "目的表数据获取成功,从源表获取数据..."
    151         fi
    152             
    153         select_sql source_db_user source_db_pass SDBNAME ./data/${sname}.new $suser "$line" $sname
    154         # 对比文件,选出在new中但不在old中的行
    155     if [ -s ./data/${sname}.old ];then
    156         awk 'NR==FNR{if($0 !~ /^[ 	]*$/)arr[$0]+=1;next}{if($0 in arr || $0 ~ /^[ 	]*$/);else print;}' ./data/${sname}.old ./data/${sname}.new > ./data/${dname}.unl
    157     else
    158         cp ./data/${sname}.new ./data/${dname}.unl 
    159     fi        
    160         data_lines=`awk 'END{print NR}' ./data/${dname}.unl`        
    161         if [ ! -e ./data/${dname}.ctl ];then
    162             wlog "不存在./data/${dname}.ctl,开始生成./data/${dname}.ctl "
    163             make_ctl ${dname}
    164         fi
    165 
    166         if [ $data_lines -eq 0 ];then
    167             wlog "本次无数据需要更新"
    168         else
    169             wlog "本次需要更新${data_lines}条数据"
    170             wlog "执行sqlldr..."
    171             sqlldr dest_db_user/dest_db_pass@DBNAME control=./data/${dname}.ctl direct=true log=./log/${dname}.log bad=./log/${dname}.bad
    172             succ_cnt=`grep successfully ./log/${dname}.log | awk '{print $1}'`
    173             bad_cnt=0
    174             [ -e ./log/${dname}.bad ] && bad_cnt=`wc -l ./log/${dname}.bad | awk '{print $1}'`
    175             wlog "成功更新:${succ_cnt}条数据,${bad_cnt}条失败"
    176         fi
    177 
    178         # 执行完毕,将${dname}.unl添加至${sname}.old
    179         cat ./data/${dname}.unl >> ./data/${sname}.old
    180     done
    181 }
    182 ###############################################################################
    183 # main
    184  main() {
    185     wlog "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
    186     wlog "开始执行"
    187     handle $1
    188     wlog "执行完毕"
    189     wlog "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
    190 }
    191 
    192 if [ $# -ne 1 ];then
    193     echo "Usage $0 file"
    194     exit 1
    195 else
    196     main $1
    197 fi
  • 相关阅读:
    透视校正插值
    投影矩阵推导
    编程思想-小即是美
    Win10使用小技巧
    TotalCommander 之 快捷键
    TotalCommander 之 配置
    TotalCommander 之 日常使用技巧
    上士闻道,勤而行之;中士闻道,若存若亡;下士闻道,大笑之。不笑不足以为道。
    《诫子书》
    青春不是年华,而是心境
  • 原文地址:https://www.cnblogs.com/wbjxxzx/p/4546055.html
Copyright © 2011-2022 走看看