批量导出oracle中的对象
背景
Oracle数据库中有table,view,procedure,function,package,type等对象,需要将这些对象导出到不同的文件中。
常用的方法有3种:
1. 通过开发工具直接导出。优点:导出的格式好;缺点:无法自动化。
2. 写一个spool进行导出。优点:实现自动化;缺点:如果长度过程,会自动折行(可能是没有找到解决办法)。
3. 编写一个小程序进行导出。本文采用此方法。
思路
要求:将数据库A中的对象a1,a2,a3..an保存到文件file1中,将b1,b2,b3..bn保存到文件file2中,将c1,c2,c3..cn保存到文件file3中。
思路如下:
1. Input:
a) 数据库A的连接:connect_string
b) file1 file2 file3要保存的文件夹:result_dir
c) 说明文件:list_file,用于说明文件file1要保存哪些对象,file2要保存哪些对象。。。
2. list_file的格式:
#file1
type1 a1
type2 a2
type3 a3
...
typen an
#file2
type1 b1
type2 b2
type3 b3
...
typen bn
#file3
type1 c1
type2 c2
type3
...
typen cn
其中,文件名已“#”开头,type指对象的类型(table,view...),a1指对象的名字,type和a1中间以tab键隔开。
3. 流程:
定义一个方法:__get_object_list(这些方法见python实现),用于读取文件list_file,确定每个目标文件对应的对象。
解析完list_file之后,进行循环,每次生成一个目标文件。生成目标文件的方法为__get_list_ddl。
不同的对象有不同的定义,比如table,需要获取其定义、注释、索引等信息,而procedure仅仅获取其定义。这些工作由方法__get_single_ddl实现。
4. 相关SQL:
获取定义主要通过DBMS_METADATA.GET_DDL实现,获取表注释通过SQL查询实现。
--调用GET_DDL之前的设置
BEGIN
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'STORAGE', FALSE);
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'SQLTERMINATOR', TRUE);
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE);
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'TABLESPACE', FALSE);
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'CONSTRAINTS', TRUE);
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'REF_CONSTRAINTS', TRUE);
--DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'CONSTRAINTS_AS_ALTER', TRUE);
END;
--对用之后恢复初始化
BEGIN
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'DEFAULT');
END;
--获取某个对象的DDL
SELECT DBMS_METADATA.GET_DDL(:1,:2) FROM DUAL
--获取注释
SELECT ' COMMENT ON TABLE ' || T.TABLE_NAME || ' IS ''' || T.COMMENTS || ''' ;'
FROM USER_TAB_COMMENTS T
WHERE T.COMMENTS IS NOT NULL
AND T.TABLE_NAME = :1
UNION ALL
SELECT ' COMMENT ON COLUMN ' || T.TABLE_NAME || '.' || T.COLUMN_NAME || ' IS ''' || T.COMMENTS || ''' ;'
FROM USER_COL_COMMENTS T
WHERE T.COMMENTS IS NOT NULL
AND T.TABLE_NAME = :1
--获取索引
SELECT DBMS_METADATA.GET_DDL('INDEX', I.INDEX_NAME)
FROM USER_INDEXES I
WHERE I.INDEX_NAME NOT IN (SELECT X.CONSTRAINT_NAME
FROM USER_CONSTRAINTS X)
AND I.TABLE_NAME = :1
ORDER BY INDEX_NAME DESC
python实现
import cx_Oracle,os,sys class OraExpDDl:
"""
usage:
ora=OraExpDDl()
ora.open(connect_string)
export_ddl(list_file,result_dir)
ora.close()
"""
def __init__(self):
self.connect=''
self.cursor=''
self.status=False def __get_single_ddl(self, object_type,object_name):
object_type=object_type.upper()
object_name=object_name.upper()
print(' {0}:{1}'.format(object_type,object_name))
l=[]
#check
sql=""" SELECT COUNT(*)
FROM USER_OBJECTS T
WHERE T.OBJECT_NAME = '{0}'
AND T.OBJECT_TYPE = '{1}'""".format(object_name,object_type)
self.cursor.execute(sql)
cnt=self.cursor.fetchone()
if cnt[0]==0:
print(' {0}:{1} does not exists'.format(object_type,object_name))
return l
l.append('prompt create {0} {1}'.format(object_type,object_name))
#object
print(' ddl')
sql="""SELECT DBMS_METADATA.GET_DDL('{0}', '{1}')
FROM DUAL""".format(object_type,object_name)
self.cursor.execute(sql)
l.extend([i[0] for i in self.cursor.fetchall()])
if object_type=='TABLE':
#index
print(' index')
sql="""SELECT DBMS_METADATA.GET_DDL('INDEX', I.INDEX_NAME)
FROM USER_INDEXES I
WHERE I.INDEX_NAME NOT IN (SELECT X.CONSTRAINT_NAME
FROM USER_CONSTRAINTS X)
AND I.TABLE_NAME = '{0}'
ORDER BY INDEX_NAME DESC""".format(object_name)
self.cursor.execute(sql)
l.extend([i[0] for i in self.cursor.fetchall()])
#comment
print(' comment')
sql="""SELECT ' COMMENT ON TABLE ' || T.TABLE_NAME || ' IS ''' || T.COMMENTS || ''' ;'
FROM USER_TAB_COMMENTS T
WHERE T.COMMENTS IS NOT NULL
AND T.TABLE_NAME = '{0}'
UNION ALL
SELECT ' COMMENT ON COLUMN ' || T.TABLE_NAME || '.' || T.COLUMN_NAME || ' IS ''' || T.COMMENTS || ''' ;'
FROM USER_COL_COMMENTS T
WHERE T.COMMENTS IS NOT NULL
AND T.TABLE_NAME = '{0}'""".format(object_name)
self.cursor.execute(sql)
l.extend([i[0] for i in self.cursor.fetchall()])
return l def __get_list_ddl(self, object_list,file_name):
#init
sql_before="""
BEGIN
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'STORAGE', FALSE);
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'SQLTERMINATOR', TRUE);
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'SEGMENT_ATTRIBUTES', FALSE);
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'TABLESPACE', FALSE);
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'CONSTRAINTS', TRUE);
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'REF_CONSTRAINTS', TRUE);
--DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'CONSTRAINTS_AS_ALTER', TRUE);
END;
"""
sql_after= """
BEGIN
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM, 'DEFAULT');
END;
"""
#start
self.cursor.execute(sql_before)
f=open(file_name,'wb') #get and write
for i in object_list:
str_list=self.__get_single_ddl(i[0],i[1])
f.write(chr(10).join(str_list).encode('utf-8'))
f.write(chr(10).encode('utf-8'))
#end
f.close()
self.cursor.execute(sql_after)
return 0 def __get_object_list(self,list_file):
r=[]
state=0
label=''
data=[]
# read data
f=open(list_file);
l=[i.strip() for i in f.readlines() if len(i.strip())>0]
f.close()
# parse data
for i in l:
if state==1:
if i[0]!='#':
tmp=i.split('\t')
if len(tmp)<2:
raise Exception("parse file object_list_file error")
data.append((tmp[0],tmp[1]))
else:
if len(data)>0:
r.append((label,data))
label=i[1:]
data=[]
if state==0:
if i[0]=='#':
label=i[1:]
state=1
if len(data)>0:
r.append((label,data))
return r def open(self,connect_string):
"""
connect_string:database connection
build a connection of oracle
"""
def OutputTypeHandler(cursor, name, defaultType, size, precision, scale):
if defaultType == cx_Oracle.CLOB:
return cursor.var(cx_Oracle.LONG_STRING, 80000, cursor.arraysize)
try:
self.connect=cx_Oracle.connect(connect_string)
self.connect.outputtypehandler=OutputTypeHandler
self.cursor=self.connect.cursor();
self.status=True
except:
self.status=False
print("can't open: ",connect_string) def close(self):
"""
close the connection
"""
if self.status:
self.status=False
try:
self.cursor.close()
self.connect.close();
except:
self.status=False def export_ddl(self,list_file,result_dir):
"""
list_file:the objects you want export
result_dir:directory of result file
"""
#check
if not self.status:
print("disconnect")
return 1
if not os.path.isfile(list_file):
print("file {0} does not exists".format(list_file))
return 2
if not os.path.isdir(result_dir):
print("result dir {0} does not exists".format(result_dir))
return 3
try:
object_list=self.__get_object_list(list_file)
except:
print("list file parse error")
return 4 #do
for i in object_list:
print(i[0])
file_name=os.path.join(result_dir,i[0])
self.__get_list_ddl(i[1],file_name)
print("export ddl finish")
return 0 def export_ddl(connect_string,list_file,result_dir):
"""
connect_string:database connection
list_file:the objects you want export
result_dir:directory of result file
"""
ora=OraExpDDl()
ora.open(connect_string)
ora.export_ddl(list_file, result_dir)
ora.close() if __name__=='__main__':
if len(sys.argv)<4:
print("please input parameter:connection,sql_dir,object_file_path")
else:
export_ddl(sys.argv[1],sys.argv[2],sys.argv[3])
结束
刚开始的实现,打算使用写个spool来实现,可是发现如果对象的定义太长的话,生成的代码会折行。这个没有找到解决办法,所以就打算使用脚本来实现。还有一个原因就是,需要导出的文件已utf-8格式编码,换行符为unix样式的。
python用的比较多,所以就使用python实现。因为有很多电脑没有安装Python,所以如果能用java重新编写适用性会更强点。
批量导出oracle中的对象的更多相关文章
- 用sql语句导出oracle中的存储过程和函数
用sql语句导出oracle中的存储过程和函数: SET echo off ; SET heading off ; SET feedback off ; SPOOL 'C:/PRC.SQL' repl ...
- 使用OTT处理oracle中的对象(一) OTT配置
OTT是OCI中访问对象类型数据的重要工具,它将数据库中的对象数据类型或集合类型映射为C++中的结构体类型.OTT是Oracle自带的,但是使用前必须配置一下环境变量.在计算机->属性-> ...
- Python批量执行oracle中的insert语句
从oracle导出一个表的数据,导出的格式是insert语句,数据量30万. 直接在PL/SQL Developer中执行,速度非常慢,脚本中也是100条数据提交一次.因为需要的时间太长,每次中断后, ...
- oracle中的对象创建及删除语句【原创】
oracle对象 1.表 a)创建表1 create table students( id number(10), stuno number(10) , sex varchar2(2), age in ...
- 批量修改Sqlserver中数据库对象的所属架构
执行以下SQL,将执行结果拷贝出来,批量执行既可. SELECT 'ALTER SCHEMA dbo TRANSFER ' + s.Name + '.' + p.Name FROM sys.Proce ...
- (原)matlab导出oracle中blob的jpg数据到图片
转载请注明出处: https://www.cnblogs.com/darkknightzh/p/10092965.html function write_blob_info(blob) len = b ...
- 批量导出ppt中内嵌的图片
某个ppt中很多页,然后插入了很多图片,且图片都是被压缩的,看起来非常费劲,所以想着一次性把图片另存为,找了接近一个小时,终于被我找到啦,分享给大家: 1.直接把ppt的后缀修改为rar 2.解压ra ...
- python导出oracle中的表内容,并生成excel文件
export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK; ### 如果oracle表中有中文输出,为防止乱码,执行脚本前,需要先制定字符集: #!/usr/bin/pyth ...
- Oracle中如何导出存储过程、函数、包和触发器的定义语句?如何导出表的结构?如何导出索引的创建语句?
Oracle中如何导出存储过程.函数.包和触发器的定义语句?如何导出表的结构?如何导出索引的创建语句? QQ群里有人问:如何导出一个用户下的存储过程? 麦苗答:方法有多种,可以使用DBMS_MET ...
随机推荐
- 初识javascript变量和基本数据类型
1.1首先,学习使用firebug控制台.设置一下firefox 中的配置选项,以便使控制台中的javascript警告更为严格...以方便我们更好的找出程序中不必要的bug. 1. 在火狐浏览器fi ...
- PyCharm3.0默认快捷键(翻译的)
PyCharm3.0默认快捷键(翻译的) PyCharm Default Keymap 1.编辑(Editing) Ctrl + Space 基本的代码完成(类.方法.属性)Ctrl + Alt ...
- MySQL数据库备份--mysqldump用法
导出要用到MySQL的mysqldump工具,基本用法是: shell> mysqldump [OPTIONS] database [tables] 如果你不给定任何表,整个数据库将被导出. ...
- MVC5 + EF6 + Bootstrap3 (16) 客户端验证
Slark.NET-博客园 http://www.cnblogs.com/slark/p/mvc5-ef6-bs3-get-started-client-side-validation.html 系列 ...
- 聚类算法:K-means
2013-12-13 20:00:58 Yanjun K-means算法是很典型的基于距离的聚类算法,采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大.该算法认为簇是由距离 ...
- 最简单jquery轮播图效果
样式部分 <style type="text/css"> *{;;} ul,ol{list-style:none;} #box{width:420px;height:6 ...
- 【USACO 2.4】The Tamworth Two
题意:C代表cows,F代表farmer,一开始都向北,每分钟前进1步,如果前方不能走,则这分钟顺时针转90°,问多少步能相遇,或者是否不可能相遇,10*10的地图. 题解:dfs,记录状态,C和F的 ...
- 使用matlab进行空间拟合
假设有这么一组数据, x=[4 5 6 7 8 4 8 10]'; y=[56 56 56 56 56 60 60 60]';z=[6 6 6 9 6 19 6 6]'; 要求出其平面方程z=C+Ax ...
- 教你一招:Word中的文字转换成表格,把表格转换成文字
在使用office软件时,常常会在Word中加入表格,这时候我们一般想到的是,建立表格,然后一格一格的填写;或者用Excel表格制作在复制到Word文档中.其实在Word中就可以将文本文档转换成电子表 ...
- [Think In Java]基础拾遗1 - 对象初始化、垃圾回收器、继承、组合、代理、接口、抽象类
目录 第一章 对象导论第二章 一切都是对象第三章 操作符第四章 控制执行流程第五章 初始化与清理第六章 访问权限控制第七章 复用类第九章 接口 第一章 对象导论 1. 对象的数据位于何处? 有两种方式 ...