【问题标题】:Problems when updating an MySQL database, python更新 MySQL 数据库时的问题,python
【发布时间】:2022-01-22 14:38:31
【问题描述】:

在下面的示例中,有两个数据帧 df 和 df1。我还有一个带有两个表的 MySQL 数据库。 Tables1 和 Table2,都和 df 有相同的列。

我想做的是:

  1. 使用 df1 在 table1 中找到正确的行,
  2. 将行移动到 table2 并更新列 'REMOVED'(从 False 到 True)和 'REMOVED_DATE(从 None 到 '2022-01-10)。
  3. 从 table1 中删除行

在你下面看到我的努力。但它不起作用,我可以想象有更好的解决方案可用。任何帮助将不胜感激。

df=pd.DataFrame({'ID':[25, 10],
              'DATE':['2021-11-13', '2021-12-03'],
              'LOC': ['NY', 'ML'],
                'MAIL':['person1@gmail.com', 'person2@gmail.com'],
                 'NR': ['100000', '200000'],
                'REMOVED': [False, False],
                 'REMOVED_DATE':[None,None]})

df1=pd.DataFrame({'ID':[25],
                  'REMOVED':[True],
                 'REMOVED_DATE':['2022-01-11']})

cols = "`,`".join([str(i) for i in df.columns.tolist()]) #use df to mirror the columns in the tables in the database.

for i, row in df1.iterrows():
    id=row['ID']
    sql=f"SELECT ID FROM table1 WHERE id={id}" # Check if ID is in table1.
    cursor.execute(sql)
    z=cursor.fetchall()
    
    if not z:
        print('insert') # if not, move on.
  
    else: #If ID in, update, move and delete
        sql=f"""UPDATE table1 SET (`" +cols + "`) VALUES (" + "%s,"*(len(row)-1) + "%s) WHERE id={id}""" # Update the whole row where ID match.
        cursor.execute(sql, tuple(row))
        mydb.commit()
        sql=f"""INSERT INTO table2 SELECT * FROM table1 WHERE id={id}""" #insert it into table2
        cursor.execute(str(sql), tuple(row))
        mydb.commit()
        sql=f"""DELETE from table1 WHERE id={id}""" # Delete it from table1
        cursor.execute(sql)
        mydb.commit()

【问题讨论】:

  • 您在cursor.execute() 中缺少UPDATE 语句的参数。
  • 如果要删除行,为什么要更新 table1?
  • 更好的解决方案或许是先将其移动到 table2 然后更新它?

标签: python mysql


【解决方案1】:

您无需更新 table1 - 规范中没有任何内容表明需要这样做,无论如何您都要删除它。

table1 复制到table2 时,您的代码不会更改REMOVEDREMOVED_DATE。为此,您可以将SELECT * 替换为选择除这些之外的所有列,然后在SELECT 列表中替换所需的新值。

您还应该使用参数化查询,而不是用 f 字符串替换值。

cols = ",".join(f"`{col}`" for col in df.columns.tolist())
new_cols = ",".join('%s' if col in ('REMOVED', 'REMOVED_DATE') else f"`{col}`" for col in df.columns.tolist())
insert_sql=f"""INSERT INTO table2 ({cols}) SELECT {new_cols} FROM table1 WHERE id=%s""" #insert it into table2
delete_sql = """DELETE from table1 WHERE id=%s"""
select_sql = "SELECT ID FROM table1 WHERE id=%s"

for i, row in df1.iterrows():
    id=row['ID']
    cursor.execute(select_sql, (id,))
    row = cursor.fetchone()

    if not row:
        print('insert') # if not, move on.

    else: #If ID in, update, move and delete
        cursor.execute(insert_sql, (False, '2022-01-10', id))
        cursor.execute(delete_sql, (id,))
        mydb.commit()

在移动和删除时,每组操作应该只提交一次,这样它们就是一个原子集。

【讨论】:

  • 非常感谢。我现在正在尝试。我认为您的代码的第一行有一个 () 到多个(列之后。应该是: cols = ",".join(f"{col}" for col in df.columns.tolist())
  • 第二行也是如此。
  • 不应该将 iterrows 行用作执行中的第二个参数吗?
  • 为什么?您正在从表中复制,而不是从数据框中复制。数据框只是用于获取 ID。
  • 如果您需要将 df 中的所有列以相同的顺序替换到查询中,则仅在 execute() 中使用 tuple(row)。大多数情况下你只需要一些列,所以你写(row['col1'], row['col2'])
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-24
  • 2015-11-25
  • 2011-12-03
  • 1970-01-01
  • 2017-05-08
  • 2017-08-27
相关资源
最近更新 更多