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 ...
随机推荐
- zabbix监控MySQL状态值获取不到值原因分析
在server端测试键值 [root@zbx-server etc]# zabbix_get -s MySQL-glibc -k "buffer_pool_wait_free" 如 ...
- Jmeter4.0 _Beanshell解析并获取json响应数据数组长度
我们在做jmeter接口测试的时候,有时候碰到开发没返回数据total,只返回了一条条记录,可是呢,我们又需要知道到底返回了多少条数据时,咋办呢?咋办呢?咋办呢? 不要急,接下来,让我们见证奇迹是如何 ...
- commons-io之FileUtils、IOUtils
原文:https://blog.csdn.net/justry_deng/article/details/93616705 commons-io简单说明:Common IO 是一个工具库,用来帮助开发 ...
- 烂笔头@WP 的博文仅供自己学习的备忘录
前记:本博主的博文仅供自己学习的备忘录. 说明:很久未用博客,登录密码已忘记,费劲找回来,特写本博文申明.因为,今天邮件收到一条博文的评论,有谩骂本博主之意,甚觉委屈.所以,写以下文字说明“1.我的博 ...
- The server time zone value '�й���ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use
java.sql.SQLException: The server time zone value '�й���ʱ��' is unrecognized or represents more tha ...
- 神经网络(12)--具体实现:如何对back propagation的正确性进行验证
我们在进行back propagation时难免会出现各种各样的问题,当出现问题的时候,我们的cost function仍然是随着迭代的次数下降的,但是这中间会有一些问题存在,那么我们如何来检查我们的 ...
- c# 数据类型转换
隐式转换 byte, short, int, long, fload, double等根据其顺序向后可以隐式自动完成类型的转换,隐式转移的前提是目标类型精度高于源类型,如:short隐式转换为int, ...
- Nginx页面图片错误 ERR_CONTENT_LENGTH_MISMATCH
现场:nginx代理的网站有的虚拟目录的图片无法正常显示,提示 ERR_CONTENT_LENGTH_MISMATCH,不断刷新页面图片一条一条的显示出来. 解决方法:找到nginx的缓存文件目录,c ...
- Zookeeper数据类型、节点类型、角色、watcher监听机制
1.Zookeeper数据类型:层次化目录结构+少量数据 Zookeeper包含层次化的目录结构,每个Znode都有唯一的路径标识,Znode可以包含数据和子节点. 其中Znode数据可以有多个版本, ...
- Hive ACID和事务表支持详解
一.ACID介绍 ACID就是常见数据库事务的四大特性:Atomicity(原子性).Consistency(一致性).Isolation(隔离性).Durability(持久性). 在Hive 0. ...