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

  由于无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 ];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=$
  36. db_pass=$
  37. db_name=$
  38. tb_own=$
  39. tb_name=$
  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 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=$
  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 '^[ \t]*$'|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/,\r?\n\)/\n\)/' $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=$
  83. db_pass=$
  84. db_name=$
  85. data_file=$
  86. tb_own=$
  87. sql_line=$
  88. tb_name=$
  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 echo off termout off trimout on trimspool on linesize
  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=$
  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 '\015'|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 '^[ \t]*$'|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 !~ /^[ \t]*$/)arr[$0]+=1;next}{if($0 in arr || $0 ~ /^[ \t]*$/);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 ];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=
  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 $
  188. wlog "执行完毕"
  189. wlog "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
  190. }
  191.  
  192. if [ $# -ne ];then
  193. echo "Usage $0 file"
  194. exit
  195. else
  196. main $
  197. fi

Shell同步数据到oracle数据库的更多相关文章

  1. 利用TOAD实现把EXCEL数据导入oracle数据库

    利用TOAD实现把EXCEL数据导入oracle数据库 工具:   Toad11.7z(百度搜索,直接下载) 1.将Excel文件中某些字段导入到Oracle数据库的对应表 连接想要导入的数据库 ,然 ...

  2. 批量Excel数据导入Oracle数据库

    由于一直基于Oracle数据库上做开发,因此常常会需要把大量的Excel数据导入到Oracle数据库中,其实如果从事SqlServer数据库的开发,那么思路也是一样的,本文主要介绍如何导入Excel数 ...

  3. FIREDAC(DELPHI10 or 10.1)提交数据给ORACLE数据库的一个不是BUG的BUG

    发现FIREDAC(DELPHI10 or 10.1)提交数据给ORACLE数据库的一个不是BUG的BUG,提交的表名大小写是敏感的. 只要有一个表名字母的大小写不匹配,ORACLE就会认为是一个不认 ...

  4. Java使用iBatis批量插入数据到Oracle数据库

    Java使用iBatis批量插入数据到Oracle数据库 因为我们的数据跨库(mysql,oracle),单独取数据的话需要遍历好多遍,所以就想着先从mysql数据库中取出来的数据然后在oracle数 ...

  5. 代码执行批量Excel数据导入Oracle数据库

    由于基于Oracle数据库上做开发,因此常常会需要把大量的Excel数据导入到Oracle数据库中,其实如果从事SqlServer数据库的开发,那么思路也是一样的,本文主要介绍如何导入Excel数据进 ...

  6. ODP方式,大批量数据写入ORACLE数据库

    项目中在同步数据的时候,需要把获得的数据DataTable,写入oracle数据库 因为System.Data.OracleClient写入方式写入大批量数据特别慢,改用Oracle.DataAcce ...

  7. 【转】通过Hibernate将数据 存入oracle数据库例子

    一. Hibernate介绍 Hibernate是基于对象/关系映射(ORM,Object/Relational Mapping)的一个解决方案.ORM方案的思想是将对象模型表示的对象映射到关系型数据 ...

  8. 极限挑战—C#+ODP 100万条数据导入Oracle数据库仅用不到1秒

    链接地址:http://www.cnblogs.com/armyfai/p/4646213.html 要:在这里我们将看到的是C#中利用ODP实现在Oracle数据库中瞬间导入百万级数据,这对快速批量 ...

  9. 使用PLSQL导入excel数据至oracle数据库

    https://blog.csdn.net/qq_42909551/article/details/82108754 https://jingyan.baidu.com/album/14bd256e2 ...

随机推荐

  1. Hadoop常用命令及范例

    hadoop中的zookeeper,hdfs,以及hive,hbase都是hadoop的组件,要学会熟练掌握相关的命令及其使用规则,下面就是一些常用命令及对hbase和hive的操作语句,同时也列出了 ...

  2. LAMP环境搭建之编译安装指南(php-5.3.27.tar.gz)

    测试环境:CentOS release 6.5 (Final) 软件安装:httpd-2.2.27.tar.gz   mysql-5.1.72.tar.gz   php-5.3.27.tar.gz 1 ...

  3. There is no getter for property named 'PRODUCT_ID' in 'class java.lang.String'

    背景:心血来潮之际,准备搭建以下多月未曾碰触过的Mybatis框架,体验一番原生之美.殊不知能力有限,错误百出.特抒此文以纪念此坑.问题:想在sql管理中来统一处理一些简单的判断,但是添加判断之后参数 ...

  4. Android笔记(五十七)Android总结:基础篇

    什么是安卓 Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发.目前发行版本是6.0 安卓平台的优势 ...

  5. Python开发之路:目录篇

    第一部分:Python基础知识 本篇主要python基础知识的积累和学习,其中包括python的介绍.基本数据类型.函数.模块及面向对象等.  第一篇:Python简介  第二篇:Python基本知识 ...

  6. shell脚本——正则表达式

    什么是正则表达式 正则表达式分为基础正则和扩展正则,都是为了匹配符合预期要求的字符串 正则表达式与通配符的区别 只需要记住,对文件内容或是展示文本的操作都是正则,而对目录或文件名的操作则都是通配符(例 ...

  7. React系列,jsx

    <script type="text/babel"> var name = "kimoo"; var fn = ()=> "kimo ...

  8. 从零开始配置MacBook Pro

    购买macbook, 是因为它的效率性.由于我第一次使用macbook,所以按照我开发的习惯和参照了其他人的文章进行配置我的个人mac,希望我的设置对你们也有所帮助 1.基本配置 查找我的Mac 系统 ...

  9. Luogu P1627 中位数

    Luogu P1627 中位数 先记录目标数的位置,并且把数组映射为: $$a[i]=\begin{cases}-1,a[i]<b\0,a[i]=b\1,a[i]>b\end{cases} ...

  10. Oracle数据库使用游标查询结果集所有数据

    --Oracle使用游标查询结果集所有数据 DECLARE myTabelName NVARCHAR2():=''; --表名 myTableRowComment NVARCHAR2():=''; - ...