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 ...
随机推荐
- Hadoop常用命令及范例
hadoop中的zookeeper,hdfs,以及hive,hbase都是hadoop的组件,要学会熟练掌握相关的命令及其使用规则,下面就是一些常用命令及对hbase和hive的操作语句,同时也列出了 ...
- LAMP环境搭建之编译安装指南(php-5.3.27.tar.gz)
测试环境:CentOS release 6.5 (Final) 软件安装:httpd-2.2.27.tar.gz mysql-5.1.72.tar.gz php-5.3.27.tar.gz 1 ...
- There is no getter for property named 'PRODUCT_ID' in 'class java.lang.String'
背景:心血来潮之际,准备搭建以下多月未曾碰触过的Mybatis框架,体验一番原生之美.殊不知能力有限,错误百出.特抒此文以纪念此坑.问题:想在sql管理中来统一处理一些简单的判断,但是添加判断之后参数 ...
- Android笔记(五十七)Android总结:基础篇
什么是安卓 Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发.目前发行版本是6.0 安卓平台的优势 ...
- Python开发之路:目录篇
第一部分:Python基础知识 本篇主要python基础知识的积累和学习,其中包括python的介绍.基本数据类型.函数.模块及面向对象等. 第一篇:Python简介 第二篇:Python基本知识 ...
- shell脚本——正则表达式
什么是正则表达式 正则表达式分为基础正则和扩展正则,都是为了匹配符合预期要求的字符串 正则表达式与通配符的区别 只需要记住,对文件内容或是展示文本的操作都是正则,而对目录或文件名的操作则都是通配符(例 ...
- React系列,jsx
<script type="text/babel"> var name = "kimoo"; var fn = ()=> "kimo ...
- 从零开始配置MacBook Pro
购买macbook, 是因为它的效率性.由于我第一次使用macbook,所以按照我开发的习惯和参照了其他人的文章进行配置我的个人mac,希望我的设置对你们也有所帮助 1.基本配置 查找我的Mac 系统 ...
- Luogu P1627 中位数
Luogu P1627 中位数 先记录目标数的位置,并且把数组映射为: $$a[i]=\begin{cases}-1,a[i]<b\0,a[i]=b\1,a[i]>b\end{cases} ...
- Oracle数据库使用游标查询结果集所有数据
--Oracle使用游标查询结果集所有数据 DECLARE myTabelName NVARCHAR2():=''; --表名 myTableRowComment NVARCHAR2():=''; - ...