我正在尝试为pandas Dataframe 写一个动态的sql导出函数。到目前为止,我正在阅读dataframes列dtypes并编写“create table”查询。由于T-SQL没有CREATE TABLE IF NOT EXISTS
功能,我不得不编写此解决方案。代码如下所示,其中data_df
是一个非空的pandas DataFrame:
table_columns = data_df.columns
target_table = 'Some table name'
col_dtype = []
data_coldtypes = data_df.dtypes.apply(lambda x: x.name).to_dict()
for k, v in data_coldtypes.items():
if 'int' in v.lower():
col_dtype.append(k + ' bigint')
elif 'float' in v.lower():
col_dtype.append(k + ' float')
elif 'datetime' in v.lower():
col_dtype.append(k + ' datetime')
else:
col_dtype.append(k + ' varchar(max)')
create_query = f"""IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='{target_table}' AND xtype='U')
CREATE TABLE [dbo].[{target_table}] ({', '.join(col_dtype)});"
现在我还想直接用这个dataframe的相应数据填充新创建的表,这就是为什么我还创建了一个INSERT
查询,看起来像这样:
insert_query = f"INSERT INTO [dbo].[{target_table}] " \
f"([{'], ['.join(table_columns)}]) VALUES "\
f"({', '.join(['?'] * len(table_columns))});"
# Transforming the dataframe to a tuple-dataset
dataset_tuple = [tuple(None if (pd.isna(value))
else value for value in row) for row in data.to_numpy()]
每个语句都是独立的,但现在是我不理解的奇怪部分。当我尝试用fast_executemany = True
执行这两个语句时,插入语句将被跳过。代码如下所示,其中get_connection
只是一个帮助函数,用于返回相应服务器的连接:
with get_connection(db_conn_url, 'mssql') as conn:
with conn.cursor() as cursor:
cursor.fast_executemany = True
cursor.execute(create_query)
cursor.executemany(insert_query, (dataset_tuple))
print('TEST: inserted')
使用此代码,表创建成功,但未填充(不会调用末尾的print语句),但没有错误消息。注解掉cursor.fast_executemany
选项或cursor.execute(create_query)
命令可以使insert语句工作,所以我猜它与fast_exectuemany
选项有关。有没有人遇到过类似的问题,或者知道是什么导致了这种行为?我很高兴每个提示或不同的代码逻辑创建一个表,如果不存在,并直接填充它的基础上的 Dataframe 信息。谢谢!
其他有用的代码:
def get_connection(db_url, sql_type):
conn = None
try:
if sql_type == 'mssql':
conn = pyodbc.connect(db_url)
yield conn
finally:
conn.commit()
conn.close()
1条答案
按热度按时间vq8itlhq1#
经过几次测试,我认为司机是问题所在。在
db_url
字符串中使用ODBC Driver 17 for SQL Server
解决了这个问题。但是turbodbc仍然是一个很好的选择