cx_Oracle 使用 CLOB 执行many

发布于 2024-11-19 03:11:57 字数 1014 浏览 5 评论 0原文

我正在尝试解析多个 CSV 并使用 cx_Oracle 将它们的数据插入到表中。我使用execute 插入到表中没有问题,但是当我尝试使用executemany 执行相同的过程时,出现错误。我的代码使用有效的执行,

with open(key,'r') as file:
    for line in file:
        data = data.split(",")
        query = "INSERT INTO " + tables[key] + " VALUES ("
        for col in range(len(data)):
            query += ":" + str(col) + ","
        query = query[:-1] + ")"            
        cursor.execute(query, data)

但是当我将其替换为时

with open(key,'r') as file:
    list = []
    for line in file:
        data = data.split(",")
        list.append(data)
    if len(list) > 0:
        query = "INSERT INTO " + tables[key] + " VALUES ("
        for col in range(len(data)):
            query += ":" + str(col) + ","
        query = query[:-1] + ")"            
        cursor.prepare(query)
        cursor.executemany(None,list)

,在尝试插入具有 CLOB 列且数据超过 4000 字节的表时,出现“ValueError:字符串数据太大”。当表没有 CLOB 列时,Executemany 效果很好。有没有办法告诉cx_Oracle 在执行many 时将适当的列视为CLOB?

I am attempting to parse multiple CSVs and insert their data into tables using cx_Oracle. I have no problem inserting into the tables using execute but when I try the same procedure with executemany I get an error. My code using execute that works is

with open(key,'r') as file:
    for line in file:
        data = data.split(",")
        query = "INSERT INTO " + tables[key] + " VALUES ("
        for col in range(len(data)):
            query += ":" + str(col) + ","
        query = query[:-1] + ")"            
        cursor.execute(query, data)

but when I replace it with

with open(key,'r') as file:
    list = []
    for line in file:
        data = data.split(",")
        list.append(data)
    if len(list) > 0:
        query = "INSERT INTO " + tables[key] + " VALUES ("
        for col in range(len(data)):
            query += ":" + str(col) + ","
        query = query[:-1] + ")"            
        cursor.prepare(query)
        cursor.executemany(None,list)

I get "ValueError: string data too large" when trying to insert into a table that has CLOB columns and the data is over 4000 bytes. Executemany works great when the table doesn't have a CLOB column. Is there a way I can tell cx_Oracle to treat the appropriate columns as CLOBs when it does executemany?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

孤独岁月 2024-11-26 03:11:57

尝试将大列的输入大小设置为cx_Oracle.CLOB。如果您有二进制数据,则可能不起作用,但应该适用于 CSV 中的任何文本。 2K 值可能低于其需要的值。

请注意,当涉及 CLOB 列时,executemany 似乎要慢很多,但仍然比重复执行要好:

def _executemany(cursor, sql, data):
    '''
    run the parameterized sql with the given dataset using cursor.executemany 
    if any column contains string values longer than 2k, use CLOBS to avoid "string
    too large" errors.

    @param sql parameterized sql, with parameters named according to the field names in data
    @param data array of dicts, one per row to execute.  each dict must have fields corresponding
                to the parameter names in sql
    '''
    input_sizes = {}
    for row in data:
        for k, v in row.items():
            if isinstance(v, basestring) and len(v) > 2000:
                input_sizes[k] = cx_Oracle.CLOB
    cursor.setinputsizes(**input_sizes)
    cursor.executemany(sql, data)

Try setting the input size for the large columns to cx_Oracle.CLOB. Might not work if you have binary data, but should work for any text you have in a CSV. The 2K value is probably lower than it needs to be.

Note that executemany seems to be a lot slower when there are CLOB columns involved, but still better than repeated executes:

def _executemany(cursor, sql, data):
    '''
    run the parameterized sql with the given dataset using cursor.executemany 
    if any column contains string values longer than 2k, use CLOBS to avoid "string
    too large" errors.

    @param sql parameterized sql, with parameters named according to the field names in data
    @param data array of dicts, one per row to execute.  each dict must have fields corresponding
                to the parameter names in sql
    '''
    input_sizes = {}
    for row in data:
        for k, v in row.items():
            if isinstance(v, basestring) and len(v) > 2000:
                input_sizes[k] = cx_Oracle.CLOB
    cursor.setinputsizes(**input_sizes)
    cursor.executemany(sql, data)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文