sql >> Base de Datos >  >> RDS >> Sqlserver

¿Cómo upsert pandas DataFrame a la tabla de Microsoft SQL Server?

Hay dos opciones:

  1. Usar un MERGE declaración en lugar de INSERT ... ON CONFLICT .
  2. Utilice una UPDATE declaración con JOIN , seguido de un INSERT condicional .

La documentación de T-SQL para MERGE dice:

Sugerencia de rendimiento:el comportamiento condicional descrito para la declaración MERGE funciona mejor cuando las dos tablas tienen una combinación compleja de características coincidentes. Por ejemplo, insertar una fila si no existe o actualizar una fila si coincide. Cuando simplemente actualice una tabla en función de las filas de otra tabla, mejore el rendimiento y la escalabilidad con instrucciones básicas INSERT, UPDATE y DELETE.

En muchos casos, es más rápido y menos complicado simplemente usar el UPDATE separado y INSERT declaraciones.

engine = sa.create_engine(
    connection_uri, fast_executemany=True, isolation_level="SERIALIZABLE"
)

with engine.begin() as conn:
    # step 0.0 - create test environment
    conn.execute(sa.text("DROP TABLE IF EXISTS main_table"))
    conn.execute(
        sa.text(
            "CREATE TABLE main_table (id int primary key, txt varchar(50))"
        )
    )
    conn.execute(
        sa.text(
            "INSERT INTO main_table (id, txt) VALUES (1, 'row 1 old text')"
        )
    )
    # step 0.1 - create DataFrame to UPSERT
    df = pd.DataFrame(
        [(2, "new row 2 text"), (1, "row 1 new text")], columns=["id", "txt"]
    )

    # step 1 - upload DataFrame to temporary table
    df.to_sql("#temp_table", conn, index=False, if_exists="replace")

    # step 2 - merge temp_table into main_table
    conn.execute(
        sa.text("""\
            UPDATE main SET main.txt = temp.txt
            FROM main_table main INNER JOIN #temp_table temp
                ON main.id = temp.id
            """
        )
    )
    conn.execute(
        sa.text("""\
            INSERT INTO main_table (id, txt) 
            SELECT id, txt FROM #temp_table
            WHERE id NOT IN (SELECT id FROM main_table) 
            """
        )
    )

    # step 3 - confirm results
    result = conn.execute(sa.text("SELECT * FROM main_table ORDER BY id")).fetchall()
    print(result)  # [(1, 'row 1 new text'), (2, 'new row 2 text')]