首页 > 解决方案 > executemany() 正在将最后一行数据更新到表中的所有行

问题描述

我有一个要求,我在一个 df 中有一些输入数据,需要将“名称”列与其他具有相同列的 df 进行比较,如果找到匹配项,我需要将这些数据更新到我的表中。

问题:我的 data_to_update 的最后一行适用于所有列。

到目前为止我已经尝试过:

import pandas as pd
import numpy as np
import cx_Oracle

conn = cx_Oracle.connect('xxxxx', 'yyyyyy',dsn_tns)
cursor = conn.cursor()

data = [{'name': 'ABC', 'col1': 10, 'col2': 20, 'col3': 'John'},
        {'name': 'DEF', 'col1': 30, 'col2': 40, 'col3': 'Peter'},
        {'name': 'PQR', 'col1': 50, 'col2': 60, 'col3': 'Mary'},
        {'name': 'XYZ', 'col1': 70, 'col2': 80, 'col3': 'Robert'}]
df = pd.DataFrame(data)

data2 = [{'name': 'ABC', 'col1': 10, 'col2': 20000, 'col3': 'XXXX'},
        {'name': 'DEF', 'col1': 30, 'col2': 40, 'col3': 'Peter'},
        {'name': 'PQR', 'col1': 50, 'col2': 60, 'col3': 'Mary'},
        {'name': 'XYZ', 'col1': 70, 'col2': 80000, 'col3': 'YYYY'}]
df2 = pd.DataFrame(data)
    
df['match'] = np.where(df['name'].isin(df2['name']), 1, 0)

exist_df = df[df['match'] == 1]
del exist_df['match']

new_df = df[df['match'] == 0]
del new_df['match']

update_list = exist_df['name'].tolist()

to_update =  "','".join(update_list)
to_update1 = "('" + to_update + "')"

data_to_update = [tuple(x) for x in exist_df[['col2','col3']].values]

update_query = ''' update mytable set col2 =: col2, col3 =: col3 where name in ''' + to_update1

cursor.executemany(update_query,data_to_update)
conn.commit()

我之前的表格数据是:

name  col1  col2  col3
ABC    10    20   John
DEF    30    40   Peter
PQR    50    60   Mary
XYZ    70    80   Robert

上面代码运行后的数据为:

name  col1  col2     col3
XYZ    70    80000   YYYY
XYZ    70    80000   YYYY
XYZ    70    80000   YYYY
XYZ    70    80000   YYYY

但处理后的预期表数据:

name  col1  col2    col3
ABC    10   20000   XXXX
DEF    30    40     Peter
PQR    50    60     Mary
XYZ    70   80000   YYYY

任何帮助都非常感谢,在此先感谢!

标签: pythonsqlpython-3.xoracledataframe

解决方案


您需要为每个名称执行单独的语句。更改您的元组,使其也包含该name列,然后您可以将其与占位符匹配。executemany然后将使用其对应的值更新每一行。

data_to_update = [tuple(x) for x in exist_df[['col2','col3', 'name']].values]
sql = 'UPDATE table SET col2 = :col2, col3 = :col3 WHERE name = :name'
cursor.executemany(sql, data_to_update)

推荐阅读