数据抽取到临时表(存储过程test(num)执行该操作),在将表中数据写入到txt文件,最后将txt打包zip
原先一直和代码打交道,做任何事都考虑的是使用代码完成,所以一开始就写了份代码:
1:读取配置配置文件(里面写了要操作的号)excel
emptyimport jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
//dmuser
public class load_excl {
List lis = new ArrayList();
public List findlist(String str) {
try {
Workbook book = Workbook.getWorkbook(new File(str));
// 获得第一个工作表对象
Sheet sheet = book.getSheet(0);
// 得到第一列第一行的单元格
System.out.println("数据添加到列表begin");
for (int i = 0; i < 10; i++) {
int stat = 3;
Cell cell1 = sheet.getCell(0, i );
// Cell cell2 = sheet.getCell(3, i + 2);
String result = cell1.getContents();
// String result2 = cell2.getContents();
if (result == null || result == "" || "".equals(result)) {
break;
}
lis.add(result);
}
System.out.println("数据添加到列表end");
book.close();
} catch (Exception e) {
System.out.println(e);
}
return lis;
}
public static void main(String[] args) {
load_excl a=new load_excl();
List abc= a.findlist("D://batchno.xls");
for (String s : abc) {
System.out.println(s);
}
}
}
2:执行存储过程
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* @Author: Smile [[email protected]]
* @Description:
* @Date; 2017/9/9 14:54
*/
public class oracle125 {
public void add(String li){
String driver = "oracle.jdbc.driver.OracleDriver";
String url = "jdbc:oracle:thin:@ip:1521:ods";
String user = "用户名";
String pwd = "密码";
Connection conn = null;
CallableStatement cs = null;
try {
Class.forName(driver);
conn = DriverManager.getConnection(url, user, pwd);
//P_119():存储过程
cs = conn.prepareCall("{ call P_119(?) }");
cs.setString(1, li);
cs.execute();
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (cs != null) {
cs.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
}
}
}
}
3:执行shell脚本
emptyimport ch.ethz.ssh2.ChannelCondition;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
/**
* @Author: Smile [[email protected]]
* @Description:
* @Date; 2017/9/9 11:52
*/
public class RemoteShellExecutor {
private Connection conn;
/** 远程机器IP */
private String ip;
/** 用户名 */
private String osUsername;
/** 密码 */
private String password;
private String charset = Charset.defaultCharset().toString();
private static final int TIME_OUT = 1000 * 5 * 60;
/**
* 构造函数
* @param ip
* @param usr
* @param pasword
*/
public RemoteShellExecutor(String ip, String usr, String pasword) {
this.ip = ip;
this.osUsername = usr;
this.password = pasword;
}
/**
* 登录
* @return
* @throws IOException
*/
private boolean login() throws IOException {
conn = new Connection(ip);
conn.connect();
return conn.authenticateWithPassword(osUsername, password);
}
/**
* 执行脚本
*
* @param cmds
* @return
* @throws Exception
*/
public int exec(String cmds) throws Exception {
InputStream stdOut = null;
InputStream stdErr = null;
String outStr = "";
String outErr = "";
int ret = -1;
try {
if (login()) {
// Open a new {@link Session} on this connection
Session session = conn.openSession();
// Execute a command on the remote machine.
session.execCommand(cmds);
stdOut = new StreamGobbler(session.getStdout());
outStr = processStream(stdOut, charset);
stdErr = new StreamGobbler(session.getStderr());
outErr = processStream(stdErr, charset);
session.waitForCondition(ChannelCondition.EXIT_STATUS, TIME_OUT);
System.out.println("outStr=" + outStr);
System.out.println("outErr=" + outErr);
ret = session.getExitStatus();
} else {
throw new Exception("登录远程机器失败" + ip); // 自定义异常类 实现略
}
} finally {
if (conn != null) {
conn.close();
}
IOUtils.closeQuietly(stdOut);
IOUtils.closeQuietly(stdErr);
}
return ret;
}
/**
* @param in
* @param charset
* @return
* @throws IOException
* @throws UnsupportedEncodingException
*/
private String processStream(InputStream in, String charset) throws Exception {
byte[] buf = new byte[1024];
StringBuilder sb = new StringBuilder();
while (in.read(buf) != -1) {
sb.append(new String(buf, charset));
}
return sb.toString();
}
}
4:整体调用循环
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: Smile [[email protected]]
* @Description:
* @Date; 2017/9/9 14:15
*/
public class shelltest {
public static void main(String[] args) throws Exception {
//连接oracle
// OracleConnect con=new OracleConnect();
// write your code here
//读取 oracle 中的批次号
load_excl excl =new load_excl();
oracle125 orcl125 =new oracle125();
List lis=new ArrayList();
lis=excl.findlist("D://batchno.xls");
//循环批次号
for (String li : lis) {
// 设置执行完的状态
System.out.println("当前批次号:"+li);
//连接oracle,执行存储过程
System.out.println("数据入库");
orcl125.add(li);
System.out.println("数据end");
//执行shell脚本
Thread.sleep(10*1000);
RemoteShellExecutor executor = new RemoteShellExecutor("ip", "用户名", " 密码");
// 执行myTest.sh 参数为java Know dummy
String abc="/picclife/tools/ciitc/119.sh "+li;
System.out.println(executor.exec(abc));
System.out.println(li+"批次完成");
/* try {
String shpath="/home/felven/word2vec/demo-classes.sh";
Process ps = Runtime.getRuntime().exec(shpath);
int exitValue= ps.waitFor();
if(0!=exitValue){
isOK="no";
System.err.println("call shell failed.errorcodeis:"+exitValue);
//停止继续循环执行
break;
}
BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream()));
StringBuffer sb = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
String result = sb.toString();
System.out.println(result);
}
catch (Exception e) {
e.printStackTrace();
}
*/
}
}
}
其实所有的对数据的操作不考虑空间,时间等因素都可以通过存储过程+shell脚本完成
下面介绍使用shell+oracle存储过程结合完成需求
oracle:游标(类似list),循环(while,for),触发器(拦截器),存储过程(类 中的main),函数(函数),判断(if)===》Java语言
综上所有对数据的操作都在存储过程中完成,打包写入txt等文件用shell完成
我们可能用到的场景:
1:循环执行整个脚本
2:shell脚本调用存储过程
3:shell脚本调用打包程序
4:shell脚本验证数据文件个数是否正确
5:验证表是否存在
6:shell脚本步骤写人log文件
7:如何判断存储过程是否执行正确
8:验证文件的大小是否超限
9:对shell脚本传参数
##################shell 循环 文本 数据 如果数据等于abc结束######################
while read var1
do
if [ $var1 -eq 'abc' ]
then
break
fi
done < batchno.txt
########################shell执行存储过程############################
sqlplus -s 用户/密码@//ip:端口/service_name <
set serveroutput on;
set timing on;
//test()是存储过程名
exec test(1);
commit;
exit;
EOF
########################shell读取oracle中的数据存到BATC,做变量 #################
BATC=`sqlplus -s circ_user/user_circ <
SELECT T.BATC FROM INTFUSER.abc T WHERE ROW
NUM = 1;
exit;
EOF`
############获取多变量#####
ftp_v=` sqlplus -s prip_user/prip_user<
SELECT T.SFTP_IP,
T.SFTP_USER,
T.SFTP_PASSWORD
FROM PRIP_INTF_INFO T;
exit
EOF
`
ftp_ip=`echo $ftp_v | awk -F' ' '{print $1}'`
ftp_user=`echo $ftp_v | awk -F' ' '{print $2}'`
ftp_passwd=`echo $ftp_v | awk -F' ' '{print $3}'`
####如果使用的时候直接使用字符串
也可以将sql的语句变量拼接起来,例如使用ftp上传的时候
v_ftp=` sqlplus -s prip_user/prip_user<
SELECT
T.SFTP_USER||','||
T.SFTP_PASSWORD ||' sftp://'||
T.SFTP_IP
FROM PRIP_INTF_INFO T;
exit
EOF
`
结果:v_ftp:rbsx000100,eqsU3w sftp://10.110.41.150
lftp -u $v_ftp<
put $FTILE_NAME --文件的名
bye --结束ftp的命令
EOF
########################调用打包程序#######################################
####调用另一个脚本#####
./test2.sh
####打包#######
#!/bin/sh
#进入路径
cd /picclife/tools/cross
#删除要存放文件夹下的全部文件
rm -rf /picclife/tools/cross/circ/*
##########数据从oracle临时表到文件######################
/oraexpdata/sqluldr2_linux64_10204.bin 用户名/密码 query="SELECT * FROM tablename" charset=UTF8 file="/picclife/tools/cross/F_"$BATC"_00%b.txt" rows=
10000000 batch=yes field=0x7c
############数据文件打包#######################
##文件名##
file="H_"$BATCHNO"_001.zip"
##要打包到#####
cd /picclife/tools/cross/bak
##########打包######################
7za a -tzip -r $pici /picclife/tools/cross/circ/000100
####################shell脚本压缩文件txt文件个数(文件的个数 可能会有 a_123_1.txt a_123_2.txt 文件视为1个),写入日志############
## awk -F_ 对结果的每一行数据按_分割 {print$3}:获取第三个字段 uniq:去重 wc:行数 字数 字节数 (wc写在前面+文件位置/名称,wc写在文件后面要先打开或读取文件例如more test.txt wc) awk 按空格分awk -F: '/root/' /etc/passwd 搜索/etc/passwd有root关键字的所有行 最后结果输出到log_10G.out文件
echo `unzip -v /picclife/tools/ciitc/bak/H_$BATCHNO_001.zip| grep ".txt"|awk -F_ '{print$3}'|uniq|wc|awk '{print $1}'` >>/picclife/tools/ciitc/log_10G.out
#######################验证表是否存在###################################
tab=`sqlplus -s querydep/querydeptwo <
set feedback off;
set pagesize 0;
set verify off;
set echo off;
select count(*) from user_tables where table_name = 'BS_BATCHNO';
exit;
EOF`
##不存在则创建表################
if [ $tab -eq 0 ]
then
echo "NOT EXISTS"
sqlplus -s querydep/querydeptwo <
set feedback off;
set pagesize 0;
set verify off;
set echo off;
create table BS_BatchNo(
BatchNo varchar2(20) not null,
TransactionNo varchar2(24) not null
);
exit;
EOF;
fi;
#################创建表也可以创建相同的表结构,不包含数据################
create table abc AS select * from b1 where 1=0
################验证文件的大小是否超限 超过10G 或者小于0G(-size -0G), ############################
find /picclife/tools/cross/bak/ -size +10G -exec ls -ld {} \; >>/picclife/tools/ciitc/log_10G.out
###########如何判断存储过程是否执行正确#########################################
其实存储过程是可以往表写数据的,如果存储过程报错,就插入一条错误日志进入表
在shell中查询错误数据量大于0,就终止,break 跳出循环,就能结束继续操作
#也可以 在脚本出错的时候终止脚本的执行 exit ,在循环和if都可用exit停止
[oracle@ODSDEVDB09 ~]$ more ./test1.sh
#!/bin/sh
while read va
do
if [ $va == 100 ]
then
exit
fi
echo $va
done < abc
[oracle@ODSDEVDB09 ~]$ ./test1.sh
abc
tt
[oracle@ODSDEVDB09 ~]$ cat -n abc
1 abc
2 tt
3 100
4 abcd
5 zxy
shell里面流程同代码中的流程,先循环读取文本需要处理的号,在找到对应的存储过程,将数据装入txt,最后打包,并校验正确性
######################对shell脚本传参数#############################
[oracle@ODSDEVDB09 ~]$ cat test2.sh
#!/bin/bash
echo "first :" $1
echo "second: " $2
[oracle@ODSDEVDB09 ~]$ ./test2.sh
first :
second:
[oracle@ODSDEVDB09 ~]$ ./test2.sh abc 123
first : abc
second: 123
###########################shell的文本替换###################################
sed 是一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出
sed ‘s/ / g’ file (实际上文本木有改) 全部替换
[oracle@ODSDEVDB09 ~]$ cat abc
bc
dd hello heolhello
hellofdhellogdayhello
zxyizxyasdwuzxaszxysqswqzxy
am ddddddddddddddddabdfea
a bb aa cc
hello word
[oracle@ODSDEVDB09 ~]$ sed 's/hello/world/g' abc
bc
dd world heolworld
worldfdworldgdayworld
zxyizxyasdwuzxaszxysqswqzxy
am ddddddddddddddddabdfea
a bb aa cc
world word
[oracle@ODSDEVDB09 ~]$ cat abc
bc
dd hello heol hello
hellofdhellogdayhello
zxyizxyasdwuzxaszxysqswqzxy
am ddddddddddddddddabdfea
a bb aa cc
hello word
#################################################
vim :s :文本替换命令,需要使用vim 在线打开文件,在做处理
vim abc
bc
dd jjllo jjol jjllo
bc
dd jjllo jjol jjllo
hellofdhellogdayhello
ttittasdwuzxasttsqswqtt
am ddddddddddddddddabdfea
a ss aa cc
hello word
:g/tt/s//hello/g //全部替换
bc
dd jjllo jjol jjllo
bc
dd jjllo jjol jjllo
hellofdhellogdayhello
helloihelloasdwuzxashellosqswqhello
am ddddddddddddddddabdfea
a ss aa cc
hello word
: 1 ,$ s/hello/2017/g //全部替换
bc
dd jjllo jjol jjllo
bc
dd jjllo jjol jjllo
2017fd2017gday2017
2017i2017asdwuzxas2017sqswq2017
am ddddddddddddddddabdfea
a ss aa cc
2017 word
find /a/b/c -name '*.txt'| xargs cat| wc -l //获取目录文件夹c下txt文件的总行数
xargs:获取管道的参数,以流的形式 传递给下一个参数