oracle的spool工具可以将数据导出为文本格式,有很强的功能和实用性,如果能灵活应用,能带来很多好处和便捷。
下面是我写的两个示例脚本,使用着可以直接拷贝使用,如有更好的改进,请补充。
在unix/linux下,vi sqlexport.sh,下面是 sqlexport.sh的文件内容:
#!/bin/sh
if [ $# -ne 3 ]; then
echo "usage:$0 user/passwd@dbstr sqlfile exportfile";
exit 1;
fi
dbstr=$1;
sqlfile=$2;
outfile=$3;
echo $dbstr;
sqlplus $dbstr<<EOF
set pages 9999
set heading off
set echo off
set feedback off
@$sqlfile
exit;
EOF
mv out.txt $outfile
编写sql模版
template.sql
下面是文件内容:
set termout off
set echo off
set feedback off
set heading off
set verify off
--pagesize 0用来去除空行
set pagesize 0
set trimspool on
spool out.txt
select 'analyze table ' || owner || '.' || table_name ||
' estimate statistics sample 5000 rows;'
from dba_tables
where owner in ('DEV');
select
'analyze index '||owner||'.'||index_name||' compute statistics;'
from dba_indexes
where owner in ('DEV');
spool off
使用者可以替换template.sql里面的sql语句,就可以导出自己想要的数据了。
然后执行命令./sqlexport.sh dev/chenli@testdb tables.sql 2.txt
打开2.txt就是自己想要的参数导出数据了
脚本sqlexport.sh有三个参数,第一个参数是sqlplus登录数据库的命令串,如user/passwd@dbstr格式,第二个参数就是sql文件名,第三个参数是导出文件名,使用的时候只要按照template的样式,修改其中的查询sql语句就可以了。
提供另外一个例子,内容如下:
#! /usr/bin/sh
DAY=`date "+%Y%m%d"`
BILLING_CYCLE=`date "+%Y%m"`
out_file=''
dest_file=''
#第一个参数是帐期yyyymm
if [ $# -eq 1 ]
then
BILLING_CYCLE=$1
fi
out_file="Bill_NUMBER_TO_ACCESS_NUMBER_"$BILLING_CYCLE.txt
dest_file="Bill_NUMBER_TO_ACCESS_NUMBER_"$BILLING_CYCLE
sqlplus bboss/bboss@cfcs1a<<EOF
--生成虚拟计费号到铁通号码映射表
set serverout on;
declare
gs_ErrMsg varchar(100);
sql_text varchar2(2000);
bill_month number(8) := 0;
field_value1 varchar2(300);
field_value2 varchar2(300);
str_len1 number := 0;
str_len2 number := 0;
i_index number := 0;
j_index number := 0;
start_value number := 0;
end_value number := 0;
--从定购属性中查找155号码和铁通接入号间的关系
cursor c1 is
select t1.bill_id,t1.city_id, t2.feature_value value
From group_sub t1, group_order_feature t2
where t1.order_id = t2.order_id
and t1.plan_id = '70000340'
and t2.feature_id = 5002000400
and t1.rec_status = 1
and t2.rec_status = 1;
begin
select to_number(to_char(sysdate,'yyyymm')) into bill_month from dual;
begin
--首先把以前的记录置为无效,只有当前生成的记录是有效,这样只需要一个简单sql就能实现spool抽取数据
update crc_num_rela set rec_status=0 where rec_status=1;
--sql_text := 'update crc_num_rela set rec_status=0 where rec_status=1';
--execute immediate sql_text;
exception when others then
null;
end;
--遍历所有记录
for rec in c1 loop
field_value1 := rec.value;
str_len1 := length(field_value1);
--
while str_len1 > 0
loop
i_index := instr(field_value1,';');
if i_index = 0 and str_len1 > 0 then
i_index := str_len1;
end if;
field_value2 := substr(field_value1, 1, i_index-1);
field_value2 := trim(field_value2);
str_len2 := length(field_value2);
field_value1 := substr(field_value1, i_index+1, str_len1-i_index);
str_len1 := length(field_value1);
if str_len2 > 0 then
j_index := instr(field_value2,'-');
--dbms_output.put_line('field_value2=' || field_value2 || ',j_index=' || to_char(j_index) || ',str_len2=' || to_char(str_len2));
if j_index = 0 then
start_value := to_number(field_value2);
end_value := to_number(field_value2);
else
start_value := to_number( substr(field_value2,1,j_index-1) );
end_value := to_number( substr(field_value2,j_index+1,str_len2-j_index) );
end if;
--循环,将分解后的数据插入临时表tmp
loop
--dbms_output.put_line(to_char(start_value));
--sql_text := 'insert into tmp(misdn,cnn_num) values(''' || to_char(rec.bill_id) || ''',''' || to_char(start_value) || ''')';
--dbms_output.put_line(sql_text);
--execute immediate sql_text;
insert into crc_num_rela(bill_id,crc_num,city_id,bill_month,rec_status,create_date)
values(rec.bill_id,start_value,rec.city_id,bill_month,1,sysdate);
start_value := start_value + 1;
EXIT WHEN start_value > end_value;
end loop;
end if;
end loop;
end loop;
commit;
end;
/
exit;
EOF
unlink prepare.sql
cat<<EOF >>prepare.sql
set term off
set heading off
set pages 0
set feedback off
set trimout on
set trimspool on
spool $out_file
select bill_id||',' || crc_num ||',' || to_char(city_id) ||','|| to_char(bill_month) from crc_num_rela where rec_status=1;
spool off
quit;
EOF
#用spool生成文件
sqlplus bboss/bboss@cfcs1a @prepare.sql
#如果正确地生成了文件,修改名字为要求的文件名
if [ -f "$out_file" ]; then
mv $out_file $dest_file
fi
unlink prepare.sql
#生成ftp上传脚本
unlink ftp.script
cat<<EOF >>ftp.script
open 10.70.9.29
user chenli chenli
put $dest_file
EOF
#运行ftp上传文件脚本
cat ftp.script | ftp -n
unlink ftp.script