当源数据位于Pandas Dataframe中时,我不确定如何使用命名的绑定变量从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()
尼尔斯
答案 0 :(得分:1)
如果您打算使用命名绑定变量,则需要执行以下操作:
[{"a" : 1, "b" : "Dog"}, {"a" : 2, "b" : "Cat"}]
换句话说,您需要创建词典列表而不是列表列表。
答案 1 :(得分:0)
当然,安东尼是对的。以下代码(从我的原始问题进行了修改)对此进行了演示。请注意,命名绑定变量: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