首页 > 解决方案 > 如何将 pandas DataFrame 插入 Microsoft SQL Server 表?

问题描述

我想将我的 pandas DataFrame 插入到 SQL Server 表中。这个问题ON CONFLICT对 PostgreSQL 有一个可行的解决方案,但是 T-SQL 没有INSERT. 我怎样才能为 SQL Server 完成同样的事情?

标签: pythonsql-serverpandassqlalchemyupsert

解决方案


有两种选择:

  1. 使用MERGE语句而不是INSERT ... ON CONFLICT.
  2. 使用UPDATE带有 a 的语句JOIN,后跟一个条件INSERT

MERGE的 T-SQL文档说:

性能提示:当两个表具有复杂的匹配特征混合时,为 MERGE 语句描述的条件行为最有效。例如,如果行不存在则插入行,或者如果匹配行则更新行。当简单地根据另一个表的行更新一个表时,使用基本的 INSERT、UPDATE 和 DELETE 语句来提高性能和可伸缩性。

UPDATE在许多情况下,简单地使用单独的andINSERT语句会更快、更简单。

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

推荐阅读