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
代码如下:
#!/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数据库的更多相关文章
- 利用TOAD实现把EXCEL数据导入oracle数据库
利用TOAD实现把EXCEL数据导入oracle数据库 工具: Toad11.7z(百度搜索,直接下载) 1.将Excel文件中某些字段导入到Oracle数据库的对应表 连接想要导入的数据库 ,然 ...
- 批量Excel数据导入Oracle数据库
由于一直基于Oracle数据库上做开发,因此常常会需要把大量的Excel数据导入到Oracle数据库中,其实如果从事SqlServer数据库的开发,那么思路也是一样的,本文主要介绍如何导入Excel数 ...
- FIREDAC(DELPHI10 or 10.1)提交数据给ORACLE数据库的一个不是BUG的BUG
发现FIREDAC(DELPHI10 or 10.1)提交数据给ORACLE数据库的一个不是BUG的BUG,提交的表名大小写是敏感的. 只要有一个表名字母的大小写不匹配,ORACLE就会认为是一个不认 ...
- Java使用iBatis批量插入数据到Oracle数据库
Java使用iBatis批量插入数据到Oracle数据库 因为我们的数据跨库(mysql,oracle),单独取数据的话需要遍历好多遍,所以就想着先从mysql数据库中取出来的数据然后在oracle数 ...
- 代码执行批量Excel数据导入Oracle数据库
由于基于Oracle数据库上做开发,因此常常会需要把大量的Excel数据导入到Oracle数据库中,其实如果从事SqlServer数据库的开发,那么思路也是一样的,本文主要介绍如何导入Excel数据进 ...
- ODP方式,大批量数据写入ORACLE数据库
项目中在同步数据的时候,需要把获得的数据DataTable,写入oracle数据库 因为System.Data.OracleClient写入方式写入大批量数据特别慢,改用Oracle.DataAcce ...
- 【转】通过Hibernate将数据 存入oracle数据库例子
一. Hibernate介绍 Hibernate是基于对象/关系映射(ORM,Object/Relational Mapping)的一个解决方案.ORM方案的思想是将对象模型表示的对象映射到关系型数据 ...
- 极限挑战—C#+ODP 100万条数据导入Oracle数据库仅用不到1秒
链接地址:http://www.cnblogs.com/armyfai/p/4646213.html 要:在这里我们将看到的是C#中利用ODP实现在Oracle数据库中瞬间导入百万级数据,这对快速批量 ...
- 使用PLSQL导入excel数据至oracle数据库
https://blog.csdn.net/qq_42909551/article/details/82108754 https://jingyan.baidu.com/album/14bd256e2 ...
随机推荐
- SuperTab
Tab快捷键提示功能 下载 http://www.vim.org/scripts/script.php?script_id=1643 安装 # vi supertab.vmb : UseVimball ...
- object-c 连接mysql
1. 通读 'mysql的使用' 2. 在Target->build setting 修改配置 User Header Search Paths 加入 /usr/local/mysql/incl ...
- Air for ANE:一星期的调试笔记
来源:http://blog.csdn.net/hero82748274/article/details/8656674 第一次尝试ANE的东西,让我感觉到很折腾人.adobe 出的这个方案虽然可以解 ...
- c# zip写comment注释
//生成的压缩文件为test.zip using (FileStream fsOut = File.Create("test.zip")) { //ZipOutputStream类 ...
- javascript_19-DOM初体验
DOM DOM: 文档对象模型(Document Object Model),又称为文档树模型.是一套操作HTML和XML文档的API. DOM可以把HTML和XML描述为一个文档树.树上的每一个分支 ...
- Linux磁盘管理——Ext2文件系统
前言 通常而言,对于一块新磁盘我们不是直接使用,而是先分区,分区完毕后格式化,格式化后OS才能使用这个文件系统.分区可能会涉及到MBR和GPT问题.至于格式化和文件系统又有什么关系? 这里的格式化指的 ...
- 分布式结构化存储系统-HBase访问方式
分布式结构化存储系统-HBase访问方式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. HBase提供了多种访问方式,包括HBase shell,HBase API,数据收集组件( ...
- h5中hash的用法实例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- php进行判断PC还是手机端代码
之前网站判断移动还是手机跳转都是用js实现,今天给大家分享一个自己用的php判断移动或者PC <?php function check_wap() { if (isset($_SERVER['H ...
- test20190805 夏令营NOIP训练20
100+0+0=100,由于第二题写挂rank 1就没了 山 xyz现在站在一个斜坡面前 这个斜坡上依次排布这n座山峰,xyz打算爬上其中的一座 因为xyz体力不好,所以他只能爬上最矮的一座山 又因为 ...