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

  由于无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

  代码如下:

  

 #!/usr/bin/ksh 

 DEBUG="false"
if [ $DEBUG = "true" ];then
orig_dir="."
else
cd
. ./.profile
orig_dir="${HOME}"
fi
v_date=`date +%Y%m%d%H%M%S`
###############################################################################
# 日志文件,大于20M时压缩半数行
cd $orig_dir
log="$orig_dir/log/alpha.log"
[ ! -d $orig_dir/log ] && mkdir $orig_dir/log
[ ! -d $orig_dir/cfg ] && mkdir $orig_dir/cfg
[ ! -d $orig_dir/data ] && mkdir $orig_dir/data
if [ -e $log ];then
log_size=`ls -l $log | awk '{printf("%d",$5)}'`
if [ -n "$log_size" -a $log_size -gt ];then
half_line=`awk 'END{printf("%d",NR/2)}' $log`
perl -ni -e "print if(\$.>$half_line)" $log
fi
fi
###############################################################################
# 写日志
wlog() {
echo "`date +%Y-%m-%d' '%H:%M:%S`: $*">>$log
}
###############################################################################
# 函数:get_col_type 获取列、类型
# 传递参数:用户名 密码 数据库名 表所有者 表名
get_col_type() {
db_user=$
db_pass=$
db_name=$
tb_own=$
tb_name=$
tmp=./cfg/${tb_name}.tmp
tb_name="${tb_own}.${tb_name}"
sqlplus ${db_user}/${db_pass}@${db_name}<<EOF
set heading off feedback off pagesize verify off echo off
spool $tmp
desc ${tb_name};
spool off
quit
EOF
}
###############################################################################
# 函数:make_ctl 生成控制文件
# 传递参数:目的表名
make_ctl() {
d_name=$
ctl_file=./data/${d_name}.ctl
echo "load data" > $ctl_file
echo "infile './data/${d_name}.unl'" >> $ctl_file
echo "append into table ${d_name}" >> $ctl_file
echo "fields terminated by '|'" >> $ctl_file
echo "(" >> $ctl_file
cat ./cfg/${d_name}.ini|grep -v '^[ \t]*$'|grep -v '^#'|while read column col_type
do
case $col_type in
NUMBER|VARCHAR|VARCHAR2)
echo "$column," >> $ctl_file ;;
DATE)
echo "$column \"to_date(:$column,'yyyymmddhh24miss')\"," >> $ctl_file ;;
*)
wlog "未识别的类型:$col_type" ;;
esac
done
echo ")" >> $ctl_file
# 替换末尾的,)为)
perl -pi -e 'undef $/;s/,\r?\n\)/\n\)/' $ctl_file
} ###############################################################################
# 函数:select_sql 查询数据
# 传递参数:用户名 密码 数据库名 数据文件名 表所有者 查询语句 表名
# select CALL_ID||'|'||to_char(END_TIME,'yyyymmddhh24miss')||'|'||CALLER||'|'||SERVICE_NO||'|'||CALL_PURPOSE from tablename;
select_sql() {
db_user=$
db_pass=$
db_name=$
data_file=$
tb_own=$
sql_line=$
tb_name=$
sql_line="$sql_line from ${tb_own}.${tb_name}"
wlog "查询sql:$sql_line"
# set closep '|'
sqlplus -S /nolog<<EOF
set heading off feedback off newpage none pagesize echo off termout off trimout on trimspool on linesize
conn ${db_user}/${db_pass}@${db_name}
spool ${data_file}
$sql_line;
spool off
quit
EOF
} ###############################################################################
# 函数:handle 处理数据
# 传递参数:配置文件
handle() {
table_name=$
cat $table_name|grep -v '^#'|while read suser sname dname
do
# 如果dname为空,默认使用sname
[ -z "$dname" ] && dname=$sname
sname=`echo $sname | tr 'A-Z' 'a-z'`
dname=`echo $dname | tr 'A-Z' 'a-z'` [ -e ./log/${dname}.log ] && : > ./log/${dname}.log
[ -e ./log/${dname}.bad ] && : > ./log/${dname}.bad
[ -e ./log/${dname}.unl ] && : > ./log/${dname}.unl if [ ! -e ./cfg/${dname}.ini ];then
wlog "不存在./cfg/${dname}.ini,开始获取${dname}列配置..."
get_col_type dest_db_user dest_db_pass DBNAME dest_db_user $dname
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
fi
wlog "根据./cfg/${dname}.ini拼接查询sql..."
wlog "${dname}列配置为:"
line="select"
cat ./cfg/${dname}.ini|grep -v '^[ \t]*$'|grep -v '^#'|while read column col_type
do
wlog "$column $col_type"
case $col_type in
NUMBER|VARCHAR|VARCHAR2)
line="${line} $column;" ;;
DATE)
line="${line} to_char($column,'yyyymmddhh24miss');" ;;
*)
wlog "未识别的类型:$col_type" ;;
esac
done
[ $DEBUG = "true" ] && wlog "line:$line"
# 去掉最后一个分号,替换所有分号为|
line=${line%;*}
line=${line//,/"||'|'||"}
[ $DEBUG = "true" ] && wlog "line:$line" # 不存在$sname.old时创建$sname.old
[ ! -e ./data/${sname}.old ] && touch ./data/${sname}.old if [ ! -s ./data/${sname}.old ];then
wlog "./data/${sname}.old为空,从目的表获取数据..."
select_sql dest_db_user dest_db_pass DBNAME ./data/${sname}.old dest_db_user "$line" $dname
wlog "目的表数据获取成功,从源表获取数据..."
fi select_sql source_db_user source_db_pass SDBNAME ./data/${sname}.new $suser "$line" $sname
# 对比文件,选出在new中但不在old中的行
if [ -s ./data/${sname}.old ];then
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
else
cp ./data/${sname}.new ./data/${dname}.unl
fi
data_lines=`awk 'END{print NR}' ./data/${dname}.unl`
if [ ! -e ./data/${dname}.ctl ];then
wlog "不存在./data/${dname}.ctl,开始生成./data/${dname}.ctl "
make_ctl ${dname}
fi if [ $data_lines -eq ];then
wlog "本次无数据需要更新"
else
wlog "本次需要更新${data_lines}条数据"
wlog "执行sqlldr..."
sqlldr dest_db_user/dest_db_pass@DBNAME control=./data/${dname}.ctl direct=true log=./log/${dname}.log bad=./log/${dname}.bad
succ_cnt=`grep successfully ./log/${dname}.log | awk '{print $1}'`
bad_cnt=
[ -e ./log/${dname}.bad ] && bad_cnt=`wc -l ./log/${dname}.bad | awk '{print $1}'`
wlog "成功更新:${succ_cnt}条数据,${bad_cnt}条失败"
fi # 执行完毕,将${dname}.unl添加至${sname}.old
cat ./data/${dname}.unl >> ./data/${sname}.old
done
}
###############################################################################
# main
main() {
wlog "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
wlog "开始执行"
handle $
wlog "执行完毕"
wlog "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
} if [ $# -ne ];then
echo "Usage $0 file"
exit
else
main $
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. Android 常用开源库总结(持续更新)

    前言 收集了一些比较常见的开源库,特此记录(已收录350+).另外,本文将持续更新,大家有关于Android 优秀的开源库,也可以在下面留言. 一 .基本控件 TextView HTextView 一 ...

  2. Android查看应用方法数

    当一个项目快速迭代时,难免引进各种依赖,从而导致单个apk超过65k的限制.如何查询apk的方法数也是每个Android Developer必备技能. 我使用的是 dex-method-counts  ...

  3. Linux下MySQL的数据文件存放在哪里的??

    http://bbs.csdn.net/topics/390620630 mysql> show variables like '%dir%';+------------------------ ...

  4. 微信小程序 wxml 中使用 js函数

    原文链接 1.在 utils 目录下 新建`filter.wxs` var filters = { toFix: function (value) { return value.toFixed(2) ...

  5. VLAN实验2:配置Trunk接口

    实验环境公司规模较大200多个员工.内部网络是一个较大的局域网,有两台交换机S1和S2来负责员工网络的接入,接入交换机之间通过汇聚交换机S3相连.公司通过划分VLAN来隔离广播域,由于员工较多,同部门 ...

  6. Python 过滤a文件中每一行内容,保存到b文件中

    #coding=utf-8print 1#初始化文件crash_log.log with open('e:/1/crash_log.log','w')as f: f.close() def fw(se ...

  7. LG3768 简单的数学题

    P3768 简单的数学题 题目描述 输入一个整数n和一个整数p,你需要求出$(\sum_{i=1}^n\sum_{j=1}^n ijgcd(i,j))~mod~p$,其中gcd(a,b)表示a与b的最 ...

  8. SVM: 实际中使用SVM的一些问题

    使用SVM包来求θ,选择C与核函数 我们使用已经编写好的软件包(这些软件包效率高,用得多,是经无数人证明已经很好的可以使用的软件包)来求θ,而不是自己去编写软件来求它们(就像我们现在很少编写软件来求x ...

  9. *JavaScript标准参考教程 - 阮一峰

    参考 页向对象编程的模式(继承&模块化)

  10. Hive节点及原理

    1.什么是Hive:hive是一种基于hadoop的数据仓库,能够将结构化的数据映射成一张表,并提供HQL进行查询.其数据是存储在hdfs上,本质是将sql命令转化成MapReduce来执行. 2.H ...