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

  由于无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. OS UIButton之UIButtonType详解-转

    我做了一个关于UIButtonType的Demo,效果如下图: UIButtonType各个类型的解释: typedef NS_ENUM(NSInteger, UIButtonType) { UIBu ...

  2. ssh远程登录连接慢的解决方法

    近期在搭建自动化集群服务,写脚本ssh批量分发公钥至其它服务器时比较缓慢,便在度娘上寻找解决方法如下: 方法一: 以ssh -v 调试模式远程登录: [root@bqh-nfs- ceshi]# ss ...

  3. @PropertySources和@ImportReSources注解

    修改默认加载的配置文件,加载指定的配置文件. @PropertySources 格式:@PropertySources(value={"classpath:xxx.xxx"}) @ ...

  4. python(open文件读取)

    一.open文件读取 1.open('file','mode')打开一个文件 file 要打开的文件名,需加路径(除非是在当前目录) mode 文件打开的模式 需要手动关闭close 2.with o ...

  5. Oracle内存管理方式由amm切换为asmm

    (一)ASMM和AMM 在Oracle 10g时,Orale推出ASMM(Automatic Shared Memory Managed),实现了SGA和PGA各自内部的自调节.在Oracle 11g ...

  6. Mongodb的主从复制

    主从服务器的实现原理 首先,主节点会把本服务的与写有关的操作记录下来,读操来不记录,这些操作就记录在local数据库中的oplog.$admin这个集合中,这是一个固定集合,大小是可以配置的,主要是通 ...

  7. linux 下安装node 并使用nginx做域名绑定

    #1 ,home目录下 下载nodejs安装包,解压 并修改文件夹名称 wget https://nodejs.org/dist/v8.11.4/node-v8.11.4-linux-x64.tar. ...

  8. IDEA实用教程(九)—— 创建Servlet

    4. 创建Servlet 1) 第一步 2) 第二步 3) 第三步 4) 第四步 由于新创建的Web项目, 没有Tomcat环境, 所以创建的Servlet会发生导包错误,如下图所示 : 因此我们需要 ...

  9. 微信小程序~基础组件

    (1)视图容器 名称 功能说明 movable-view 可移动的视图容器,在页面中可以拖拽滑动 cover-image 覆盖在原生组件之上的图片视图 cover-view 覆盖在原生组件之上的文本视 ...

  10. 初学 Size Balanced Tree(bzoj3224 tyvj1728 普通平衡树)

    SBT(Size Balance Tree), 即一种通过子树大小(size)保持平衡的BST SBT的基本性质是:每个节点的size大小必须大于等于其兄弟的儿子的size大小: 当我们插入或者删除一 ...