cx_Oracle.NotSupportedError:无法将 Python 值转换为数据库值

Posted

技术标签:

【中文标题】cx_Oracle.NotSupportedError:无法将 Python 值转换为数据库值【英文标题】:cx_Oracle.NotSupportedError: Python value cannot be converted to a database value 【发布时间】:2018-11-15 17:07:06 【问题描述】:

我正在尝试使用 Python 和 cx_Oracle 从一个表中读取数据并写入另一个数据库中的另一个表。

当我一一读取记录时,我的脚本运行良好,但是当我使用 fetchmany 获取超过 100 条记录时,脚本失败并出现错误

cx_Oracle.NotSupportedError: Python value cannot be converted to a database value

这是我要运行的脚本。

src_conn = cx_Oracle.connect(username+'/'+password+'@'+database)
src_cursor=src_conn.cursor()
tgt_conn = cx_Oracle.connect(tgt_username+'/'+tgt_password+'@'+tgt_database)
tgt_cursor=tgt_conn.cursor()
for files in file_path:
    cols=[]
    col_id=[]
    file=files.replace("\n","")
    column_list_query="select COLUMN_NAME,COLUMN_ID from all_tab_columns where owner='GDW' and table_name ='"+file+"' order by column_id"
    col=src_cursor.execute(column_list_query)
    col_list=col.fetchall()

    for value in col_list:
        cols.append(value[0])
        col_id.append(":"+str(value[1]))

    col_names="("+','.join(cols)+")"
    col_ids="("+','.join(col_id)+")"

    insert_statement='INSERT INTO '+file+' '+col_names+' VALUES '+col_ids
    select_statment="SELECT * FROM "+file
    src_cursor.bindarraysize=1000
    src_values=src_cursor.execute(select_statment)
    print("Copy contents into table :"+file)


    def ResultIter(cursor, arraysize=500):
        while True:
            results = src_cursor.fetchmany(arraysize)
            if not results:
                break
            yield results

    tgt_cursor.prepare(insert_statement)
    for result in ResultIter(src_values):

        if not result:
            break
        tgt_cursor.executemany(None,result)
        tgt_conn.commit()

【问题讨论】:

如果您正在读取和写入同一个数据库,您几乎肯定希望在 SQL 或 PL/SQL 中执行此操作,这样数据就不必通过网络返回到数据库。 我正在从一个数据库复制到另一个数据库。当我使用 sqlplus 或 toad 时,我遇到了某些数据集的问题,发现我可以使用这个脚本来克服它们。 您可以发布发生此故障时的结果吗?我已尝试复制您的问题,但到目前为止还没有成功。 【参考方案1】:

问题已报告here,您可以查看那里的cmets。

错误的原因是在第一批中,一个或多个被绑定的列总是无,但在随后的一批中,这些列中的一个现在有一个值。这已在 cx_Oracle 源代码中更正,因此您可以自己构建或等待补丁发布。

否则,目前的解决方法如下:

(1) 在一个批次中执行所有插入(但根据大小,这可能不可用)

(2) 为每个批次创建一个新游标(以便 cx_Oracle 计算每个批次的类型)

(3) 使用 cursor.setinputsizes() 指定类型和大小(可能比较麻烦)

一个演示问题的简单测试用例如下:

import cx_Oracle

conn = cx_Oracle.connect("cx_Oracle/welcome")
cursor = conn.cursor()

cursor.execute("truncate table TestTempTable")

sql = "insert into TestTempTable values (:1, :2)"
cursor.executemany(sql, [(1, None), (2, None)])
cursor.executemany(sql, [(3, None), (4, "Testing")])

【讨论】:

以上是关于cx_Oracle.NotSupportedError:无法将 Python 值转换为数据库值的主要内容,如果未能解决你的问题,请参考以下文章