如何在 pandas 数据帧的 cx_Oracle 中使用带有批量插入(executemany)的命名绑定

How to use named binds with bulk inserts (executemany) in cx_Oracle from pandas dataframe

当源数据位于 Pandas 数据帧中时,我不确定如何使用命名绑定变量从 Python 3 批量插入 Oracle。下面的代码显示了我的尝试。使用未命名的绑定,这很容易,但容易出错,因为绑定的顺序需要与 Dataframe 中的列相同。

    "Named pandas binds with cursor.executemany in cx_oracle, how ?"
    import pandas as pd
    import cx_Oracle
    # create table t( a number, b varchar2 (20 char));
    df = pd.DataFrame(data={'a': [1, 2], 'b': ["Dog", "Cat"]})
    conn = cx_Oracle.connect('/@DB')
    cur = conn.cursor()
    # Bulk insert, numbered binds work
    cur.execute("truncate table t")
    cur.executemany("insert into t (a, b) values (:1, :2)", df.values.tolist())
    print(pd.read_sql("select a, b from t", con=conn))
    # Insert, named binds work
    cur.execute("truncate table t")
    cur.execute("insert into t (a, b) values (:cc, :dd)", dd="Donkey", cc=1)
    print(pd.read_sql("select a, b from t", con=conn))
    # Bulk insert, named binds do not work
    cur.execute("truncate table t")
    cur.executemany("insert into t (a, b) values (:cc, :dd)", dd=df['b'].values.tolist(), cc=df['a'].values.tolist())
    # TypeError: Required argument 'parameters' (pos 2) not found
    print(pd.read_sql("select a, b from t", con=conn))
    #
    conn.commit()
    cur.close()
    conn.close()

尼尔斯

如果您打算使用命名绑定变量,则需要改为执行以下操作:

[{"a" : 1, "b" : "Dog"}, {"a" : 2, "b" : "Cat"}]

换句话说,您需要创建字典列表而不是列表列表。

安东尼当然是对的。以下代码(从我原来的问题修改而来)演示了这一点。请注意,命名绑定变量 :b, :a 与数据框中的列顺序相反,即使这样也是匹配的(这说明了我想要命名绑定的主要原因,这是为了防止依赖绑定的顺序和数据框列相同)

谢谢。

"""
Named cx_Oracle bind variables with cursor.executemany and pandas dataframe as input
The trick is to convert the dataframe to a list of dictionaries
"""
import pandas as pd
import cx_Oracle
# create table t(a number, b varchar2 (20 char));
df = pd.DataFrame(data={'a': [1, 2], 'b': ["Dog", "Cat"]})
print(df.to_dict('records'))
conn = cx_Oracle.connect('/@DB')
cur = conn.cursor()
cur.executemany("insert into t (b, a) values (:b, :a)", df.to_dict('records'))
print(pd.read_sql("select a, b from t", con=conn))
conn.rollback()
cur.close()
conn.close()
# Output
#[{'a': 1, 'b': 'Dog'}, {'a': 2, 'b': 'Cat'}]
#   A    B
# 0  1  Dog
# 1  2  Cat