Saltar al contenido

REEMPLAZAR filas en la tabla de base de datos mysql con pandas DataFrame

Esta es el arreglo más acertada que encomtrarás dar, pero mírala pausadamente y analiza si se puede adaptar a tu trabajo.

Solución:

Con el lanzamiento de pandas 0.24.0, ahora hay una forma oficial de lograr esto al pasar un método de inserción personalizado al to_sql función.

Pude lograr el comportamiento de REPLACE INTO pasando este invocable a to_sql:

def mysql_replace_into(table, conn, keys, data_iter):
    from sqlalchemy.dialects.mysql import insert
    from sqlalchemy.ext.compiler import compiles
    from sqlalchemy.sql.expression import Insert

    @compiles(Insert)
    def replace_string(insert, compiler, **kw):
        s = compiler.visit_insert(insert, **kw)
        s = s.replace("INSERT INTO", "REPLACE INTO")
        return s

    data = [dict(zip(keys, row)) for row in data_iter]

    conn.execute(table.table.insert(replace_string=""), data)

Lo pasarías así:

df.to_sql(db, if_exists='append', method=mysql_replace_into)

Alternativamente, si desea que el comportamiento de INSERT ... ON DUPLICATE KEY UPDATE ... en su lugar, puedes usar esto:

def mysql_replace_into(table, conn, keys, data_iter):
    from sqlalchemy.dialects.mysql import insert

    data = [dict(zip(keys, row)) for row in data_iter]

    stmt = insert(table.table).values(data)
    update_stmt = stmt.on_duplicate_key_update(**dict(zip(stmt.inserted.keys(), 
                                               stmt.inserted.values())))

    conn.execute(update_stmt)

Créditos a https://stackoverflow.com/a/11762400/1919794 por el método de compilación.

Hasta esta versión (0.17.1) No puedo encontrar ninguna forma directa de hacer esto en pandas. Informé una solicitud de función para el mismo. Hice esto en mi proyecto con la ejecución de algunas consultas usando MySQLdb y luego usando DataFrame.to_sql(if_exists='append')

Suponer

1) product_id es mi principal key en la tabla PRODUCTO

2) feed_id es mi principal key en la tabla XML_FEED.

VERSIÓN SIMPLE

import MySQLdb
import sqlalchemy
import pandas

con = MySQLdb.connect('localhost','root','my_password', 'database_name')
con_str = 'mysql+mysqldb://root:[email protected]/database_name'
engine = sqlalchemy.create_engine(con_str) #because I am using mysql
df = pandas.read_sql('SELECT * from PRODUCT', con=engine)
df_product_id = df['product_id']
product_id_str = (str(list(df_product_id.values))).strip('[]')
delete_str = 'DELETE FROM XML_FEED WHERE feed_id IN (0)'.format(product_id_str)
cur = con.cursor()
cur.execute(delete_str)
con.commit()
df.to_sql('XML_FEED', if_exists='append', con=engine)# you can use flavor='mysql' if you do not want to create sqlalchemy engine but it is depreciated

Tenga en cuenta: – El REPLACE [INTO] La sintaxis nos permite INSERT una fila en una tabla, excepto que si un UNIQUE KEY (incluso PRIMARY KEY) se produce una infracción, la fila anterior se elimina antes que la nueva INSERT, por lo tanto, no hay infracción.

Necesitaba una solución genérica para este problema, así que me basé en la respuesta de Shiva; tal vez sea útil para otros. Esto es útil en situaciones en las que toma una tabla de una base de datos MySQL (total o filtrada), actualiza/agrega algunas filas y desea realizar una REPLACE INTO declaración con df.to_sql().

Encuentra el primario de la tabla. keysrealiza una declaración de eliminación en la tabla MySQL con todos keys desde el marco de datos de pandas, y luego inserta el marco de datos en la tabla MySQL.

def to_sql_update(df, engine, schema, table):
    df.reset_index(inplace=True)
    sql = ''' SELECT column_name from information_schema.columns
              WHERE table_schema = 'schema' AND table_name = 'table' AND
                    COLUMN_KEY = 'PRI';
          '''.format(schema=schema, table=table)
    id_cols = [x[0] for x in engine.execute(sql).fetchall()]
    id_vals = [df[col_name].tolist() for col_name in id_cols]
    sql = ''' DELETE FROM schema.table WHERE 0 '''.format(schema=schema, table=table)
    for row in zip(*id_vals):
        sql_row = ' AND '.join([''' ='' '''.format(n, v) for n, v in zip(id_cols, row)])
        sql += ' OR () '.format(sql_row)
    engine.execute(sql)
    
    df.to_sql(table, engine, schema=schema, if_exists='append', index=False)

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *