暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

cx-Oracle读取LOB类型数据

原创 张鹏 2022-10-21
1541

cx-Oracle读取LOB类型数据
什么是LOB类型数据
在ORACLE数据库中,LOB(Large Objects(大对象))是用来存储大量的二进制和文本数据的一种数据类型。在 Oracle8i 中开始提供 LOB 字段,在 Oracle10g 前最多只能存储 4G 数据,从 Oracle10g 开始,可以存储 8-128T 的数据,取决于你的数据库的块大小。
LOB又分为两种类型:
内部LOB类型:将数据以字节流的形式存储在数据库的内部。因而,内部LOB的许多操作都可以参与事务,也可以像处理普通数据一样对其进行备份和恢复操作。如:
BLOB:二进制大对象。定义一个 BLOB 变量,用于存储大量的二进制数据(如图像、视频、音频等),该二进制大对象存储于数据库中。
CLOB:字符型大对象(单字节字符数据)。定义一个 CLOB 变量,用于存储超长的文本数据,该字符型大对象存储于数据库中。
NCLOB:字符型大对象(多字节国家字符数据)。定义一个 NCLOB 变量,用于存储超长的文本数据,该字符型大对象存储于数据库中。
外部LOB类型:在数据库内仅存储数据在操作系统中的位置信息,而数据的实体以外部文件的形式存在于操作系统的文件系统中。因而,该类型所表示的数据是只读的,不参与事务。如:
BFILE:二进制文件。定义一个 BFILE 变量,它指向操作系统的一个文件,Oracle 会将其视为二进制数据进行处理。
以前内容转载自:Oracle - LOB(大对象数据类型),欲详细了解请移步。
cx_Oracle.LOB类型数据如何查看(读取)
日前从oracle查询数据时,本以为能正常返回需要的字符串数据,结果却返回了一个cx_Oracle.LOB object,这才第一次知道有这种类型。

找了一通资料之后发现cx_Oracle.LOB object有个read方法,我们只要先遍历cx_Oracle.LOB object,然后对每个元素使用read即可正常查看字符类型的原数据。

Python读写Oracle的BLOB类型

这应该算是我遇到的难题之一了。表结构是这样的:
CREATE TABLE aurora(
date_forecast VARCHAR2(10),
filename VARCHAR2(24),
content BLOB
);

  1. BLOB写操作
    现在我有3个python的数据,分别是:
    date_forecast = ‘2011-06-29’
    filename = ‘aurora.jpg’’
    file = open(‘aurora.jpg’, ‘rb’)’

content = fp.read()
fp.close()
网上的资料说,插入包含blob的记录,需要先插入空的blob对象,然后再update该记录——这意味着,一次INSERT操作,至少要访问3次数据库。但是,这里面有个问题无法解决:python如何给Oracle的blob对象赋值?仔细阅读Oracle的文档,发现在SQL语句中,可以使用冒号(:)来定义变量,而cx_Oracle模块中也的确有cx_Oracle.BLOB对象。至此,可以整理出这样的一个思路:
sqlStr = “INSERT INTO aurora (date_forecast, filename, content) VALUES (’%s’, ‘%s’, :blobData)” % (date_forecast,filename)
请注意blobData前边的冒号,是定义了一个叫做blobData的Oracle变量。然后,
cursor.setinputsizes(blobData=cx_Oracle.BLOB)
将blobData变量定义为cx_Oracle.BLOB的实例,终于让python和Oracle握手了。接下来,就是水到渠成的事情了,
cursor.execute(sqlStr, {‘blobData’:content})
cursor.execute(‘commit’)
2. BLOB读操作
sqlStr = "SELECT date_forecast, filename, content FROM (SELECT date_forecast, filename, content FROM aurora ORDER BY date_forecast DESC) where ROWNUM < 2 "
cursor.execute(sqlStr)
result = cursor.fetchall()
此时,result[0][2]就是BLOB对象,python如何操作它呢?
print type(result[0][2])
才想起来它是一个cx_Oracle.BLOB对象,呵呵,继续:
print dir(cx_Oracle.BLOB)
发现cx_Oracle.BLOB有一个read方法,
print type(result[0][2].read())
终于看到熟悉的str类型,搞定!
file = open(‘aurora.jpg’, “wb”)
file.write(result[0][2].read())
file.close()

oracle数据库中blob数据读取
blob b’xxxxxxx’
clob ‘xxxxxxxx’
import cx_Oracle
import datetime

connection = cx_Oracle.connect(user=“dhcc01”, password=“dhcc010803”,dsn=“172.28.30.6:1521/orcl”)

connection = cx_Oracle.connect(user=“test”, password=“rootrootrootroot”,dsn=“10.10.122.84:1521/orcl”)

connection = cx_Oracle.connect(user=“pretest03”, password=“pretest031217”,dsn=“172.20.20.8:1521/orcl”)

basePath=“C:\Users\MyComputer\Desktop\xxxxx\”

db2_filename=basePath+“db2_output.sql”
mysql_filename=basePath+“mysql_output.sql”
oracle_filename=basePath+“oracle_output.sql”
sqlserver_filename=basePath+“sqlserver_output.sql”

db2_file=open(db2_filename,‘w’)
mysql_file=open(mysql_filename,‘w’)
oracle_file=open(oracle_filename,‘w’)
sqlserver_file=open(sqlserver_filename,‘w’)

cursor = connection.cursor()

#检索库中所有表
cursor.execute(""“select table_name from user_tables “””)
tablenames=cursor.fetchall()

for tmp_tablename in tablenames:
#检索表列的信息
v_tablename=tmp_tablename[0]
param={‘tabname’:v_tablename}
cursor.execute(""“select table_name,column_name,data_type from user_tab_columns where table_name= :tabname order by column_id asc”"",param )
tablecolumns=cursor.fetchall()
#print(tablecolumns)
insert_str=‘insert into ‘+v_tablename+’(’
#检索列名,生成列语句,以逗号分隔
for column in tablecolumns:
insert_str=insert_str+column[1]+’,’
#删除多余的逗号
insert_len=len(insert_str)
insert_str=insert_str[0:insert_len-1]
insert_str+=’) values’
#print(insert_str)

#多少行提交一次
commit_count=100
#提交行计数器
commit_counter=0


cursor.execute("""select * from """+v_tablename )
#检索每行数据
for row in cursor:
    db2_valuestring='('
    mysql_valuestring='('
    oracle_valuestring='('
    sqlserver_valuestring='('

    #检索每行每列的数据,构建values语句
    for column in row:
        if isinstance(column,datetime.datetime)==True:
            db2_valuestring=db2_valuestring+"timestamp('"+column.strftime("%Y-%m-%d %H:%M:%S")+"'),"
            oracle_valuestring=oracle_valuestring+"to_date('"+column.strftime("%Y-%m-%d %H:%M:%S")+"','yyyy/mm/dd hh24:mi:ss'),"
            mysql_valuestring=mysql_valuestring+"'"+column.strftime("%Y-%m-%d %H:%M:%S")+"',"
            sqlserver_valuestring=sqlserver_valuestring+"'"+column.strftime("%Y-%m-%d %H:%M:%S")+"',"
        elif isinstance(column,int)==True:
            db2_valuestring=db2_valuestring+str(column)+","
            mysql_valuestring=mysql_valuestring+str(column)+","
            oracle_valuestring=oracle_valuestring+str(column)+","
            sqlserver_valuestring=sqlserver_valuestring+str(column)+","
        elif isinstance(column,float)==True:
            db2_valuestring=db2_valuestring+str(column)+","
            mysql_valuestring=mysql_valuestring+str(column)+","
            oracle_valuestring=oracle_valuestring+str(column)+","
            sqlserver_valuestring=sqlserver_valuestring+str(column)+","
        elif isinstance(column,str)==True:
            db2_valuestring=db2_valuestring+"'"+str(column)+"'"+","
            mysql_valuestring=mysql_valuestring+"'"+str(column)+"'"+","
            oracle_valuestring=oracle_valuestring+"'"+str(column)+"'"+","
            sqlserver_valuestring=sqlserver_valuestring+"'"+str(column)+"'"+","
        elif column is None:
            db2_valuestring=db2_valuestring+"NULL"+","
            mysql_valuestring=mysql_valuestring+"NULL"+","
            oracle_valuestring=oracle_valuestring+"NULL"+","
            sqlserver_valuestring=sqlserver_valuestring+"NULL"+","
        #lob类型处理好,blob只能用read方法,clob可直接使用
        elif isinstance(column,cx_Oracle.LOB):
            # print(v_tablename)
            # print(type(column))
            temp_lob=column.read()
            # print(temp)
            db2_valuestring=db2_valuestring+"'"+str(temp_lob)+"',"
            mysql_valuestring=mysql_valuestring+"'"+str(temp_lob)+"',"
            oracle_valuestring=oracle_valuestring+"'"+str(temp_lob)+"',"
            sqlserver_valuestring=sqlserver_valuestring+"'"+str(temp_lob)+"',"
        else:
            # print(v_tablename)
            # print(type(column))
            db2_valuestring=db2_valuestring+"'"+str(column)+"'"+","
            mysql_valuestring=mysql_valuestring+"'"+str(column)+"'"+","
            oracle_valuestring=oracle_valuestring+"'"+str(column)+"'"+","
            sqlserver_valuestring=sqlserver_valuestring+"'"+str(column)+"'"+","
    
    #删除多余的逗号
    db2_value_len=len(db2_valuestring)
    db2_valuestring=db2_valuestring[0:db2_value_len-1]
    db2_valuestring=db2_valuestring+");\n"
    db2_combinestring=insert_str+db2_valuestring

    mysql_value_len=len(mysql_valuestring)
    mysql_valuestring=mysql_valuestring[0:mysql_value_len-1]
    mysql_valuestring=mysql_valuestring+");\n"
    mysql_combinestring=insert_str+mysql_valuestring

    oracle_value_len=len(oracle_valuestring)
    oracle_valuestring=oracle_valuestring[0:oracle_value_len-1]
    oracle_valuestring=oracle_valuestring+");\n"
    oracle_combinestring=insert_str+oracle_valuestring
    
    sqlserver_value_len=len(sqlserver_valuestring)
    sqlserver_valuestring=sqlserver_valuestring[0:sqlserver_value_len-1]
    sqlserver_valuestring=sqlserver_valuestring+");\n"
    sqlserver_combinestring=insert_str+sqlserver_valuestring

    db2_file.writelines(db2_combinestring)
    mysql_file.writelines(mysql_combinestring)
    oracle_file.writelines(oracle_combinestring)
    sqlserver_file.writelines(sqlserver_combinestring)

    #行循环中每行加1,指定commit_count添加commit命令
    commit_counter+=1
    if commit_counter%commit_count==0:
        db2_file.writelines("commit;\n")
        mysql_file.writelines("commit;\n")
        oracle_file.writelines("commit;\n")

#每张表结束再提交一次
#表如果有空行,会出现多个commit,可以不用处理
db2_file.writelines("commit;\n")
mysql_file.writelines("commit;\n")
oracle_file.writelines("commit;\n")

db2_file.close()
mysql_file.close()
oracle_file.close()
sqlserver_file.close()

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论