ORACLE数据导出工具

最近应公司要求导出数据为csv格式文件供业务人员存档查看,同时还需要按照指定分隔符导出其他文本格式,待数据迁移使用,就是根据指定的sql,按照指定的分隔符和文本格式导出数据。所使用的数据是oralce,由于生产环境又没有下载安装像sqluldr2之类的数据库导出工具。想着自己利用自带的sqlplus客户端写个通用的oracle导数脚本,查询资料,发现网上各种博客里描写的spool一键导出,都是花拳绣腿,用起来是真不好使,数据错位,分隔符混乱,断行显示各种问题都有,特此记录下自己的这个导出工具。

shell脚本

--help查看使用说明

#!/bin/bash
#################################################################################################################################
#   name: sql export tool for oracle   
#   desc: export use MACKUP/SPOOL with sqlplus client
#   Author          Date            version
#   Epoch-Elysian   20231129        1.0
#
#################################################################################################################################
TYPE="csv" SEPERATOR="" FILE_PATH="" SPOOL_CONF="" EXPORT_SQL="" CLIENT_LANG="AMERICAN_AMERICA.AL32UTF8" HEADER="" USE_MACKUP="Y"
function usage {
cat <<EOFUsage : sh $0 [options] -f <filepath> <sqltext>examples : sh $0 -f /home/test.csv "select * from table;"sh $0 -f /home/test.data -t text -s "|" --head="id;name;age" "select * from table;"Options 
-t, --type [ csv , text ]          导出文本类型: csv 和普通文本类型,不指定默认为[ csv ]
-f, --file                         导出文件路径
-s, --seperator                    设置字段分隔符,不指定默认情况下: csv [,] text [ TAB ]--head                             添加头部,使用[;]分割,例如:--head="id;name;age"
--lang                             设置 sqlplus 客户端会话编码,默认值:[ AMERICAN_AMERICA .AL32UTF8]
--disable-mackup                   默认使用 MACKUP 生成文本格式,导出时,特殊情况下可能会出现异常,可添加此参数禁用 MACKUP 此时程序会自动解析sql,为sql字段拼接分隔符后导出,禁用后具有局限性,对执行的sql要求如下:1)不支持 select *,必须明确指定字段名2)不支持字段别名,拼接分隔符时会导致 sql 语法错误 -- help 
EOF
}function init_options {#指定 options 操作符ARGS=$(getopt -o t:s:f: -l type:,seperator:,file:,head:,lang:,disable-mackup,help -n "$0" -- "$@")# shellcheck disable=SC2181if [ $? -ne 0 ]; thenusageexit 1fi#重新排列 getopts 拿到的参数值eval set -- "$ARGS"#循环遍历options参数列表while true; docase "$1" in-t | --type)TYPE=$2shift;;-f | --file)FILE_PATH=$2shift;;-s | --seperator)SEPERATOR=$2shift;;--head)HEADER=$2shift;;--lang)CLIENT_LANG=$2shift;;--disable-mackup)USE_MACKUP="N";;--help)usageexit 0;;--)shiftbreak;;esacshiftdone#初始化分隔符if [ "$TYPE" = "csv" ] && [ -z "$SEPERATOR" ]; thenSEPERATOR=","fiif [ "$TYPE" = "text" ] && [ -z "$SEPERATOR" ]; thenSEPERATOR=$'\t'fiif [ $# -ne 1 ]; thenecho "参数输入错误"usageexit 1fi#导数sqlEXPORT_SQL=$1
}function use_mackup_check {if [ "$USE_MACKUP" = "Y" ]; thenecho "export file use MACKUP , please ensure that sqlplus version is greater than 12.0.0.0.0, or use --disable-mackup to disable MACKUP "local versionversion=$(sqlplus -V | cut -d " " -f2-)echo "current sqlplus version:$version"fi
}#spoo1导数配置
function init_spool_conf {
local spool_conf_csv spool_conf_mackup_csv spool_conf_mackup_txt spool_conf_txt
spool_conf_csv=$(
cat <<EOF
SET linesize 20480
SET long 1024000
SET longchunksize 20480
SET termout off 
SET newp none 
SET trims on 
SET trimout on 
SET echo off 
SET pagesize 0
SET heading off 
SET feedback off 
SET trimspool on 
SET term off 
EOF
)spool_conf_mackup_csv=$(
cat <<EOF
SET long 1024000
SET longchunksize 20480
SET heading off 
SET feedback off 
SET MARKUP CSV ON DELIMITER '$SEPERATOR' QUOTE ON 
EOF
)spool_conf_mackup_txt=$(
cat <<EOF
SET long 1024000
SET longchunksize 20480
SET heading off 
SET feedback off 
SET MARKUP CSV ON DELIMITER '$SEPERATOR' QUOTE OFF 
EOF
)spool_conf_txt=$(
cat <<EOF
SET linesize 20480
SET long 1024000
SET longchunksize 20480
SET termout off
SET newp none
SET trims on
SET trimout on
SET echo off
SET pagesize 0
SET head off
SET heading off
SET feedback off
SET trimspool on
SET term off
EOF
)
case $1 in
csv)SPOOL_CONF=$([ "$2" == "Y" ] && echo "$spool_conf_mackup_csv" || echo "$spool_conf_csv");;
text)SPOOL_CONF=$([ "$2" == "Y" ] && echo "$spool_conf_mackup_txt" || echo "$spool_conf_txt");;
*)echo " not support export - type for $1"exit 1;;
esac
}function parse_and_process_sql {local sql_text="$1"local end_char=$'\n'# mack up 判断if [ "$4" = "Y" ]; then# if ! echo "$ sql _ text "| grep - e '.*;[[: space :]]*]'; then# fi# sql _ text +=";"#多条sql按;分割处理local OLD_IFS=$IFSIFS=";"#一次性读取多行纪录存入数组中local -a -p sql_listread -rd '' -a sql_list <<<"$sql_text"IFS=$OLD_IFSsql_text=""for sql in "${sql_list[@]}"; doif [ -z "$(echo "$sql" | tr -d '[:space:]')" ]; thencontinuefisql_text+="$sql;$end_char"doneEXPORT_SQL=$sql_textreturnfi#分隔符处理local type="$2" seperator="$3" split_char=""case $type incsv)split_char="||'\"$seperator\"'||";;text)split_char="||'$seperator'||";;*)echo "not support export-type for $type"exit 1;;esac#多条sql按;分割处理local OLD_IFS=$IFSIFS=";"local -a -p sql_list#一次性读取多行纪录存入数组中read -rd '' -a sql_list <<<"$sql_text"IFS=$OLD_IFSsql_text=""for sql in "${sql_list[@]}"; doif [ -z "$(echo "$sql" | tr -d '[:space:]')" ]; thencontinuefilocal fields#获取sql字段fields=$(echo "$sql" | awk -v RS="" 'BEGIN{IGNORECASE=1} {start=index($0,"SELECT");end=index($0,"FROM");print substr($0,start+6,end-start-6)}')if [ -z "$(echo "$fields" | tr -d '[:space:]')" ]; thenecho "sql解析失败...检查sql是否正确或者符合--disable-mackup相关要求"exit 1elif [ "$(echo "$fields" | tr -d '[:space:]')" = "*" ]; thenecho "export on disable mackup,not support [SELECT * FROM TABLE]" >&2exit 1fi#替换字段中的分隔符fields=$(echo "$fields" | awk -v FS="" -v OFS="" -v concat_str="$split_char" '{c=0;for(i=1;i<=NF;i++){ if($i=="(")c++;if(c<=0 && $i==",")$i=concat_str;if($i==")")c--; } print $0}')#csv 时,首尾拼拨if [ "$type" = "csv" ]; thenfields="'\"'||$fields||'\"'"fi#重新组装sqlsql_text+=$(echo "$sql" | awk -v fields="$fields" -v RS="" 'BEGIN{IGNORECASE=1} {start=index($0,"SELECT")+5;end=index($0,"FROM");head=substr($0,1,start);tail=substr($0,end);printf "%s %s %s",head,fields,tail}')sql_text+=";$end_char"done#重新组装sqlEXPORT_SQL=$sql_text
}function add_header {local header=$1 file=$2if [ -z "$header" ]; thenreturnfiheader=${header//;/$SEPERATOR}echo "start add header to export file ......"if sed -i "1i $header" "$file"; thenecho "add header >> success"elseecho "add header >> failed"exit 1fi
}#连接测试
function check_conn {
local RESULT
RESULT=$(
sqlplus -S "${DB_USER}/${DB_PWD}@${DB_NAME}" <<EOF
SET heading off;
SET feedback off;
SELECT 1 FROM DUAL;
exit 
EOF
)# shellcheck disable=SC2181
if [ $? -ne 0 ]; thenecho "connect to oracle server error ..."exit 1
elif [ -n "$RESULT" ]; thenecho "connected to oracle server >> success"
fi
}function main {
init_options "$@"
#设置终端编码和数据库一致,避免乱码
export NLS_LANG=$CLIENT_LANG
if [ -z "$FILE_PATH" ]; thenecho "请使用-f | --file 指定输出文件路径"exit 1
fi
if [ -z "$(echo "$EXPORT_SQL" | tr -d '[:space:]')" ]; thenecho "参数输入错误: sqltext "exit 1
fi
read -rp "请输入用户名:" DB_USER
read -rp "请输入库名:" DB_NAME
read -rp "请输入密码:" -s DB_PWD
#换行
echo
use_mackup_check
init_spool_conf "$TYPE" "$USE_MACKUP"
parse_and_process_sql "$EXPORT_SQL" "$TYPE" "$SEPERATOR" "$USE_MACKUP"
#检查连接
check_conn
echo "start to export sql to $FILE_PATH...export type is $TYPE"
if [ "$USE_MACKUP" = "N" ]; thenecho "export on disable mackup , sql text after process is :"echo "$EXPORT_SQL"
fi
#导出sql执行
sqlplus -S "${DB_USER}/${DB_PWD}@${DB_NAME}" <<EOF 1>/dev/null
WHENEVER SQLERROR EXIT 1;
$SPOOL_CONF 
spool $FILE_PATH 
$EXPORT_SQL 
spool off ;
exit
EOF# shellcheck disable=SC2181
if [ $? -ne 0 ]; thenecho "export sql execute error >> error , please check export sql"exit 1
elseecho "export sql >> success "
fi
#添加头部
add_header "$HEADER" "$FILE_PATH"
}
main "$@"

脚本特殊处理记录:

  • shell脚本getopt使用:init_options
  • shell脚本字符串按分隔符转数组正确姿势
        #多条sql按;分割处理local OLD_IFS=$IFSIFS=";"#一次性读取多行纪录存入数组中local -a -p sql_listread -rd '' -a sql_list <<<"$sql_text"IFS=$OLD_IFSsql_text=""for sql in "${sql_list[@]}"; doif [ -z "$(echo "$sql" | tr -d '[:space:]')" ]; thencontinuefisql_text+="$sql;$end_char"done
  •  awk替换不在括号中的逗号
fields=$(echo "$fields" | awk -v FS="" -v OFS="" -v concat_str="$split_char" '{c=0;for(i=1;i<=NF;i++){ if($i=="(")c++;if(c<=0 && $i==",")$i=concat_str;if($i==")")c--; } print $0}')
  • shell脚本处理sqlplus执行sql的异常:WHENEVER SQLERROR EXIT SQLCODE
sqlplus -S "${DB_USER}/${DB_PWD}@${DB_NAME}" <<EOF 1>/dev/null
WHENEVER SQLERROR EXIT 1;
$SPOOL_CONF 
spool $FILE_PATH 
$EXPORT_SQL 
spool off ;
exit
EOF

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/645616.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

openssl3.2/test/certs - 037 - 768-bit leaf key

文章目录 openssl3.2/test/certs - 037 - 768-bit leaf key概述笔记END openssl3.2/test/certs - 037 - 768-bit leaf key 概述 openssl3.2 - 官方demo学习 - test - certs 笔记 /*! * \file D:\my_dev\my_local_git_prj\study\openSSL\test_certs\037\my_openssl_linux_do…

树莓派3b使用selenium并更换自带的chromium浏览器版本

树莓派3b自带python3.7&#xff0c;先安装selenium pip3 install selenium3.3 卸载自带的chromium sudo apt --fix-broken install sudo apt-get purge chromium-browser sudo apt-get remove chromium-browser下载chromium 进入网址&#xff1a;http://ports.ubuntu.com/p…

简单快速取消AlertDialog的白色背景框,AlertDialog设置圆角背景

问题描述&#xff1a; 产品需求弹出的提示框是圆角&#xff0c;使用shape 设置圆角背景后&#xff0c;弹出的AlertDialog提示框四个角有白色的背景&#xff0c;据分析这个背景是 AlertDialog 父组件的背景色。 解决方法&#xff1a; 将Dialog的背景设置为透明色&#xff0c;代…

Spark累加器LongAccumulator

1.Accumulator是由Driver端总体进行维护的&#xff0c;读取当前值也是在Driver端&#xff0c;各个Task在其所在的Executor上也维护了Accumulator变量&#xff0c;但只是局部性累加操作&#xff0c;运行完成后会到Driver端去合并累加结果。Accumulator有两个性质&#xff1a; 1…

IDEA远程服务器开发

IDEA的远程开发是在本地去操远程服务器上的代码&#xff0c;可以直接将本地代码的编译,构建,调试,运行等工作都放在远程服务器上而本地运行一个客户端远程去操作服务器上的代码,就如同我们平常写代码一样。相比于云桌面成本更低,开发效率更高。 1.首先服务器配置jdk&#xff0…

第21课 在Android Native开发中架起java与c++互通的桥梁

在开始本节课&#xff0c;我尝试把项目拷贝到另一台电脑上以便继续工作&#xff0c;但出现了大量的“could not be resolved”问题&#xff0c;尝试包含新的include路径也无法解决该问题&#xff0c;最后删除了项目的Native Support&#xff0c;然后重新添加Native Support才解…

VI / VIM的使用

vi/vim 的区别简单点来说&#xff0c;它们都是多模式编辑器&#xff0c;不同的是 vim 是 vi 的升级版本&#xff0c;它不仅兼容 vi 的所有指令&#xff0c;而且 还有一些新的特性在里面。例如语法加亮&#xff0c;可视化操作不仅可以在终端运行&#xff0c;也可以运行于 x win…

python装饰器详解-笔记

一.作用域 在python中,作用域分为两种:全局作用域和局部作用域。 全局作用域是定义在文件级别的变量,函数名。而局部作用域,则是定义函数内部。 关于作用域,我们要理解两点: a.在全局不能访问到局部定义的变量 b.在局部能够访问到全局定义的变量,但是不能修改全局定义…

k8s图形化管理工具rancher

Rancher和K8s的关系&#xff0c;Rancher和K8s区别对比。简单来说&#xff0c;K8s&#xff08;Kubernetes&#xff09;为企业提供了一种一致的方式来管理任何计算基础架构&#xff0c;Rancher则是用于管理位于任何位置的Kubernetes集群的完整平台。如果用户是自己手动部署K8s集群…

Java数据结构与算法:循环链表

Java数据结构与算法&#xff1a;循环链表 大家好&#xff0c;我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 引言 在计算机科学中&#xff0c;链表是一种基础的数据结构&#xff0c…

Industrial Props Pack - PBR

库中有几个令人难以置信的低多边形模型&#xff0c;具有PBR的高质量纹理。所有未来的免费更新。可以在城市或仓库中的射击游戏中使用的高质量模型。 下载&#xff1a; ​​Unity资源商店链接 资源下载链接 效果图&#xff1a;

C# Graphics对象学习

Graphics对象用于进行绘制&#xff1b; 从哪个对象获取的Graphics&#xff0c;然后进行绘制&#xff0c;就绘制到该对象上&#xff1b; 从位图获取Graphics&#xff0c;然后进行绘制&#xff0c;绘制到该位图上&#xff1b; 从某个控件获取Graphics&#xff0c;然后绘制&…

《动手学深度学习(PyTorch版)》笔记3.7

注&#xff1a;书中对代码的讲解并不详细&#xff0c;本文对很多细节做了详细注释。另外&#xff0c;书上的源代码是在Jupyter Notebook上运行的&#xff0c;较为分散&#xff0c;本文将代码集中起来&#xff0c;并加以完善&#xff0c;全部用vscode在python 3.9.18下测试通过。…

【vue3-pbstar-admin】一款基于vue3和nodejs的简洁后台管理系统

Vue3-pbstar-admin 是一个简洁的后台解决方案&#xff0c;提供了基础的用户体系和页面接口权限配置&#xff0c;方便用户进行自定义开发&#xff0c;避免不必要的代码冗余。该方案结合了 Vue3、Element-Plus、Pinia 和 Vite 等先进技术&#xff0c;实现高效的页面布局、状态管理…

JavaScript 学习笔记(JS进阶 Day1)

「写在前面」 本文为 b 站黑马程序员 pink 老师 JavaScript 教程的学习笔记。本着自己学习、分享他人的态度&#xff0c;分享学习笔记&#xff0c;希望能对大家有所帮助。推荐先按顺序阅读往期内容&#xff1a; 1. JavaScript 学习笔记&#xff08;Day1&#xff09; 2. JavaSc…

MYSQL数据库详解(6)-- 视图存储方式触发器

MYSQL数据库详解&#xff08;6&#xff09; 视图特征&#xff1a;作用&#xff1a;创建视图使用视图删除视图 存储过程 ***为什么使用存储过程定义&#xff1a;存储过程和函数的区别缺陷&#xff1a;创建存储过程使用存储过程环境变量 局部环境变量 全局环境变量删除存储过程…

【linux】查看进程和子进程

在Linux系统中&#xff0c;可以使用多个命令来查看进程及其子进程。以下是一些常用的方法&#xff1a; 1. ps 命令 ps 命令用于显示当前进程的状态。可以结合不同的选项来查看进程及其子进程。 查看进程树&#xff1a; ps -auxf - -a 显示所有进程。 - -u 显示进程的用户/所…

上门服务小程序|预约上门服务系统开发有哪些功能?

在现代快节奏的生活中&#xff0c;压力和疲劳常常困扰着我们。为了缓解这种状况&#xff0c;越来越多的人选择去按摩店进行放松。然而&#xff0c;繁忙的工作和家庭责任往往让我们无法抽出时间去按摩店。在这种情况下&#xff0c;上门按摩服务应运而生。而随着科技的发展&#…

css实现右边边框分割线 渐变色,边框四角样式

分割线 代码 .data-item:first-of-type {border-right: 2px solid;border-image: linear-gradient(to top,rgba(0, 0, 0, 0.1) 0%,rgba(81, 110, 197, 0.76) 50%,rgba(0, 0, 0, 0.1) 100%)1;padding: 15px 0;}四角边框样式 代码 .chart-box {cursor: pointer;background: line…

Tomcat Notes: Web Security, HTTPS In Tomcat

This is a personal study notes of Apache Tomcat. Below are main reference material. - YouTube Apache Tomcat Full Tutorial&#xff0c;owed by Alpha Brains Courses. https://www.youtube.com/watch?vrElJIPRw5iM&t801s 1、Overview2、Two Levels Of Web Securi…