Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comment upsert pandas DataFrame à la table Microsoft SQL Server?

Il y a deux options :

  1. Utiliser un MERGE au lieu de INSERT ... ON CONFLICT .
  2. Utiliser une UPDATE déclaration avec un JOIN , suivi d'un INSERT conditionnel .

La documentation T-SQL pour MERGE indique :

Conseil de performance :Le comportement conditionnel décrit pour l'instruction MERGE fonctionne mieux lorsque les deux tables ont un mélange complexe de caractéristiques correspondantes. Par exemple, insérer une ligne si elle n'existe pas ou mettre à jour une ligne si elle correspond. Lorsque vous mettez simplement à jour une table en fonction des lignes d'une autre table, améliorez les performances et l'évolutivité avec les instructions de base INSERT, UPDATE et DELETE.

Dans de nombreux cas, il est plus rapide et moins compliqué d'utiliser simplement le UPDATE séparé et INSERT déclarations.

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')]