Как использовать именованные привязки с массовыми вставками (executemany) в cx_Oracle из pandas dataframe - PullRequest
0 голосов
/ 24 сентября 2018

Я не уверен, как выполнить массовую вставку в Oracle из Python 3, используя именованные переменные связывания, когда исходные данные находятся в Pandas Dataframe.Код ниже показывает мою попытку.С безымянными привязками это довольно просто, но ошибочно, поскольку порядок привязок должен быть таким же, как столбцы в 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()

Нильс

Ответы [ 2 ]

0 голосов
/ 25 сентября 2018

Энтони, конечно, прав.Следующий код (модифицированный из моего исходного вопроса) демонстрирует это.Обратите внимание, что именованные переменные связывания: 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
0 голосов
/ 25 сентября 2018

Если вы намерены использовать именованные переменные связывания, вам нужно будет сделать следующее:

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

Другими словами, вам нужно создать список словарей вместо списка списков.

...