使用 cx_Oracle 中 csv 文件中的变量更新数据库

Posted

技术标签:

【中文标题】使用 cx_Oracle 中 csv 文件中的变量更新数据库【英文标题】:Update database using variable from csv file in cx_Oracle 【发布时间】:2021-05-30 22:08:02 【问题描述】:

在使用 cx_Oracle 和 Python3.6.8 在 Oracle 数据库中执行更新命令时遇到错误ORA-01036:非法变量名称/编号

我想使用 CSV 文件 (db_results.csv) 中的变量值并执行更新命令。

db_results.csv 文件如下所示:

id, order_id, product, Courier, state
01, ORD987, Keyboard, DHL, TX
02, ORD976, Charger, Blue Dart, NY

我的代码:

con = cx_Oracle.connect("abc/abc@abc")
cur = con.cursor()

with open(r'D:\db_results.csv') as file:
    next(file)
    for line in file:
        x = line.replace('\n', ' ').replace('\r', '')
        columns = x.split(",")
        y = columns[1]
    SQL = "update inventory set model='301547' where order_id = '?'"
    cur.execute(SQL, y)
    con.commit()
con.close()

在 cx_Oracle 中使用 UPDATE 是否有任何特定语法?试图找到这方面的例子,但目前还没有找到。

【问题讨论】:

供未来读者参考,cx_Oracle 文档位于cx-oracle.readthedocs.org/en/latest/index.html,在github.com/oracle/python-cx_Oracle/tree/master/samples 有示例 【参考方案1】:

ORA-01036 由于 oracle 的占位符类型错误而引发,而更喜欢使用以冒号开头的整数,例如 :1 , :2

不要忘记修剪第二个占位符的值以获得 去掉 y 值周围的空格

无需在 DML 中嵌入参数,而是对其进行转换 到一个元组,例如(301547, y)

...
with open(r'D:\db_results.csv') as file:
    next(file)
    for line in file:
        x = line.replace('\n', ' ').replace('\r', '')
        columns = x.split(",")
        y = columns[1]
        SQL = "UPDATE inventory SET model=:1 WHERE order_id = TRIM(:2)"
        cur.execute(SQL, (301657, y))
    con.commit()
con.close()

【讨论】:

嗨,Barbaros,我尝试使用以下代码,但出现错误。 cur.executemany(SQL, (301547, y)) TypeError: parameters 应该是序列/字典列表或指定语句执行次数的整数 对不起@GauravMarothia,我不小心把很多留在了那里,请按编辑后重试。 成功了...非常感谢@Barbaros Özhan 嗨,Barbaros,代码运行没有任何错误,但数据库中的值仍未更新。你能帮忙吗? @GauravMarothia 您是否像在原始代码中一样在 DML 之后添加 con.commit() ?您确定表中存在匹配的order_id 值吗?【参考方案2】:

为每个 CSV 行调用一次 cur.execute()(如已接受的答案所示)会非常慢,不推荐。

相反,看看使用cur.executemany(),类似于cx_Oracle文档Loading CSV Files into Oracle Database中的代码:

with open('testsp.csv', 'r') as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=',')
    sql = "insert into test (id,name) values (:1, :2)"
    data = []
    for line in csv_reader:
        data.append((line[0], line[1]))
        if len(data) % batch_size == 0:
            cursor.executemany(sql, data)
            data = []
    if data:
        cursor.executemany(sql, data)
    con.commit()

在您的情况下,SQL 将是 UPDATE 语句,您只需要使用您想要的值构造 data 变量。

【讨论】:

以上是关于使用 cx_Oracle 中 csv 文件中的变量更新数据库的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 cx_Oracle 在 Python 中返回 SQLPLUS 变量

使用 Python 设置 cx_Oracle 环境变量

Python应用实战系列-如何通过Python来操作Oracle数据库:cx_Oracle

在 to_date 函数中使用 cx_oracle 变量时无法正确绑定

为 python 安装 cx_oracle

为啥 pd.read_csv 不接受 Windows 文件路径中的变量名?