在 setinputsizes() 后插入 CLOB 引发非法变量 name/number

inserting CLOB after setinputsizes() raises illegal variable name/number

我有一个 oracle table,我正在尝试从 csv 中插入大量数据(主要是长字符串)。

我发现我的字符串需要使用 CLOB 数据类型,因为它们通常超过 4000 个字符。我还发现我需要使用 'setinputsizes()' 函数或者我 运行 到 'ValueError: string data too large'.

但不知何故,使用 'setinputsizes()' 中断了我的插入查询,我得到 'ORA-01036: illegal variable name/number'?

示例:

create_query = "CREATE TABLE sequences (myid varchar(10), allele varchar(50), seq clob)"
cursor.execute (create_query)
cursor.setinputsizes(seq = cx_Oracle.CLOB)
insert_query = "INSERT INTO sequences (myid, allele, seq) VALUES ('00001;', 'HLA-A*01:01:01:01', 'CGCTGACCTGTG')" # seq truncated; in truth it's much longer hence the CLOB type
cursor.execute(insert_query)

没有 'setinputsizes()' 行,上面的查询执行得很好 - 但是当我使用超过 4000 个字符的 seq 的真实值时,它失败并显示

DatabaseError: ORA-01704: string literal too long

但是使用 'setinputsizes()' 行,我得到

DatabaseError: ORA-01036: illegal variable name/number

(注意:我知道 executemany 更适合批量插入。但是我在那里遇到了同样的错误,所以我先尝试解决这个问题。)

谁能告诉我哪里做错了以及如何解决? 谢谢!

ORA-01704: string literal too long 表示您发送到数据库的查询无法正确解析,因为有一些太长的标识符。 此标识符可以是 table 名称、列名称、函数名称(最大长度 30 字节)。

还要确保您的 seq 列没有转义问题(字符串中出现的 ' 未转义)。

当使用超过 4,000 个字符(或字节)的字符串文字插入或更新 CLOB 时,您需要将该字符串文字分配给 PL/SQL 变量,然后插入或更新 table 在 PL/SQL 块中。

示例:

DECLARE
    l_seq CLOB;
BEGIN
    l_seq := 'CGCTGACCTGTG.....CGCTGACCTGTG';

    INSERT INTO sequences (myid, allele, seq) VALUES ('00001;', 'HLA-A*01:01:01:01', l_seq);
END;
/

DatabaseError: ORA-01036: illegal variable name/number的原因是setinputsizes()调用错误。

正确的行应该是

cursor.setinputsizes(None, None, cx_Oracle.CLOB)

因为 setinputsizes() 需要同时为所有绑定变量设置(以正确的顺序!),而不是单独设置。

这需要与要输入的值的位置绑定相结合,否则会有 DatabaseError: ORA-01036: illegal variable name/number.

工作代码如下所示:

create_query = "CREATE TABLE sequences (myid varchar(10), allele varchar(50), seq clob)"
cursor.execute (create_query)
cursor.setinputsizes(None, None, cx_Oracle.CLOB)
insert_query = "INSERT INTO sequences (myid, allele, seq) VALUES (:1, :2, :3)" # seq truncated; in truth it's much longer hence the CLOB type
cursor.execute(insert_query, ['HLA00001;', 'HLA-A*01:01:01:01', seq])
conn.commit()