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

  由于无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. Winmanager,NERDTree和MiniBufExplorer

    NERDTree树形浏览文件 MiniBufExplorer多文件同时编辑 Winmanager将NERDTree和MiniBufExplorer界面整合 下载 http://www.vim.org/ ...

  2. arm9的时钟和定时器

    时钟 两种能够提供时钟的方式: 1) 晶振 2) PLL(也就是锁相环):通用PLL需啊一个晶振,和对晶体特定频率分频或倍频的锁相环电路. 学习ARM9时钟的四步: 1) 晶振:12MHZ 2) 有多 ...

  3. Python学习日记(十三) 递归函数和二分查找算法

    什么是递归函数? 简单来说就是在一个函数中重复的调用自己本身的函数 递归函数在调用的时候会不断的开内存的空间直到程序结束或递归到一个次数时会报错 计算可递归次数: i = 0 def func(): ...

  4. Android笔记(六十)Android总结:四大组件——BroadcastReceiver篇

    什么是BroadcastReceiver BroadcastReceiver是Android体系的四大组件之一,本质上是一种全局的监听器,用于监听系统全局的广播消息,正式因为其本质为全局监听,因此可以 ...

  5. Shodan information gathering use parameter

    1.we sue the Search Engines Shodan we can gather much information on the line web , such we want to ...

  6. 零基础python教程-用Python设计你的第一个小游戏

    学以致用,既然学习了python就要让它来实现我们想做的东西,这次咱就用python来做个简单小游戏,在实践中不断成长. 1.游戏代码: 输入数字,来猜测原作者心中所想的数字,猜中夸你,猜不中不夸你, ...

  7. machine learning (4)---feature scaling

    feature scaling:缩小或扩大feature的值,使所有的feature处于类似的范围,这样进行gradient descnet时更快趋向最小值.因为不同的feature的范围相差很大时, ...

  8. Django源码分析rest_framework 关于re_path('^publish/', views.PublishView.as_view()总结

    1. ApiView 定义一个cbc视图 class BookView (APIView):pass re_path(r"books/$", views.BookView.as_v ...

  9. PostgreSQL 抛出错误信息(错误行号)

    抛出错误行号是我们在写SQL中常用到的,在SQL Server和Oracle中都很简单,但是在PostgreSQL怎么实现呢?在网上查了下资料只有pg_exception_context包含错误行,我 ...

  10. Acwing P288 休息时间 题解

    Analysis 首先假设一天的第N小时与后一天的第一个小时不相连, 这种情况下DP转移比较好想 dp[i][j][0/1]dp[i][j][0/1]表示 考虑一天的前i个小时,已经休息了j小时,且第 ...