INSERT INTO SELECT 基于数据帧

INSERT INTO SELECT based on a dataframe

我有一个数据框 df,我想执行一个查询以将数据框中的所有值插入 table。基本上我正在尝试加载为以下查询:

INSERT INTO mytable
SELECT *
FROM mydataframe

为此,我有以下代码:

import pyodbc
import pandas as pd

connection = pyodbc.connect('Driver={' + driver + '} ;'
                            'Server=' + server + ';'
                            'UID=' + user + ';'
                            'PWD=' + pass + ';')

cursor = connection.cursor()

query = 'SELECT * FROM [myDB].[dbo].[myTable]'
df = pd.read_sql_query(query, connection)

sql = 'INSERT INTO [dbo].[new_date] SELECT * FROM :x'
cursor.execute(sql, x=df)
connection.commit()

但是,我收到以下错误:

TypeError: execute() takes no keyword arguments

有谁知道我做错了什么吗?

cursor.execute 不接受关键字参数。执行插入的一种方法可以使用以下代码片段。

cols = "`,`".join([str(i) for i in df.columns.tolist()])

# Insert DataFrame recrds one by one.
for i,row in df.iterrows():
    sql = "INSERT INTO `[dbo].[new_date]` (`" +cols + "`) VALUES (" + "?,"*(len(row)-1) + "%s)"
    cursor.execute(sql, tuple(row))

此处您遍历每一行,然后将其插入 table。

我在连接 pandas 和 SQL 服务器时也遇到了一些问题。但是我得到了这个解决方案来编写我的 df:

import pyodbc
import sqlalchemy

engine = sqlalchemy.create_engine('mssql+pyodbc://{0}:{1}@{2}:{3}/{4}?driver={5}'.format(username,password,server,port,bdName,driver))
pd.to_sql("TableName",con=engine,if_exists="append")

对于来自 Pandas 的原始 DB-API 插入查询,考虑 DataFrame.to_numpy()executemany 并避免任何顶层 for 循环。但是,在追加查询中必须使用显式列。调整以下列和 qmark 参数占位符以对应于数据框列。

# PREPARED STATEMENT
sql = '''INSERT INTO [dbo].[new_date] (Col1, Col2, Col3, ...)
         VALUES (?, ?, ?, ...)
      '''

#  EXECUTE PARAMETERIZED QUERY
cursor.executemany(sql, df.to_numpy().tolist())   
conn.commit()

(顺便说一下,在 SQL 查询中,最佳做法通常是始终显式引用列并避免 SELECT * 以提高代码可读性、可维护性甚至性能。)

感谢您的回答:) 但我使用以下代码来解决我的问题:

params = urllib.parse.quote_plus("DRIVER={SQL Server};SERVER=servername;DATABASE=database;UID=user;PWD=pass")
engine = sqlalchemy.create_engine("mssql+pyodbc:///?odbc_connect=%s" % params)
engine.connect()
query = query
df = pd.read_sql_query(query, connection)
df.to_sql(name='new_table',con=engine, index=False, if_exists='append')

请参阅下面我最喜欢的解决方案,其中包含 UPSERT 语句。

df_columns = list(df)
columns = ','.join(df_columns)
values = 'VALUES({})'.format(','.join(['%s' for col in df_columns]))
update_list = ['{} = EXCLUDED.{}'.format(col, col) for col in df_columns]
update_str = ','.join(update_list)
insert_stmt = "INSERT INTO {} ({}) {} ON CONFLICT ([your_pkey_here]) DO UPDATE SET {}".format(table, columns, values, update_str)