Python脚本导入Excel写入SQL Server时出现nvarchar语法错误
错误原因
你遇到的Incorrect syntax near 'nvarchar'语法错误,核心问题是INSERT语句写法不符合SQL Server语法规则:
- 字段数据类型、主键约束这类表结构定义,只能在CREATE TABLE建表阶段声明
- INSERT语句的字段列表位置只需要填写纯列名即可,你直接把建表时的类型定义复制到了INSERT语句的列列表中,SQL Server解析到
date nvarchar(10) primary key这段内容时无法识别,直接抛出语法错误。
另外代码里还有两个容易触发后续报错的隐患:
- 用
date字段作为主键风险极高,只要Excel里存在重复日期、空值、格式异常的日期值,就会触发主键冲突导致插入失败 - 循环逐行调用execute插入数据的效率极低,数据量稍大时运行速度会非常慢
修正方案
把INSERT语句里字段列表部分的类型、主键定义全部删除,只保留列名即可,修正后的完整代码如下:
import pandas as pd import pyodbc # 读取Excel data = pd.read_excel (r"C:\Users\c.stembridge\OneDrive - NEWREST GROUP SERVICES\Overtime Forecast Report.xlsx", sheet_name='Daily Hrs2') df = pd.DataFrame(data) # 连接SQL Server conn = pyodbc.connect("DRIVER={ODBC Driver 18 for SQL Server};SERVER=localhost;UID=SA;PWD=Working@2022;DATABASE=testdb;Encrypt=no;TrustServerCertificate=yes") cursor = conn.cursor() # 先判断表是否存在,避免重复运行时报表已存在的错误,可选 cursor.execute("IF OBJECT_ID('Overtime_Forecast', 'U') IS NOT NULL DROP TABLE Overtime_Forecast") # 建表 cursor.execute(''' CREATE TABLE Overtime_Forecast ( date nvarchar(10) primary key, day nvarchar(9), hrs int, dl int, catered int, hrs_diff_btwn_last_day int, catered_flight_diff int, employees_OT_count int, carriers int, whole int, half int, total_carts int ) ''') # 插入数据,注意这里列列表只写列名,不要加类型定义 for row in df.itertuples(): cursor.execute(''' INSERT INTO Overtime_Forecast ( date, day, hrs, dl, catered, hrs_diff_btwn_last_day, catered_flight_diff, employees_OT_count, carriers, whole, half, total_carts) VALUES (?,?,?,?,?,?,?,?,?,?,?,?) ''', row.Date, row.Day, row.Hrs, row.DL, row.Catered, row.Hrs_diff_btwn_last_day, row.Catered_flight_diff, row.Employees_OT_count, row.Carriers, row.Whole, row.Half, row.Total_carts ) conn.commit() # 用完关闭连接 cursor.close() conn.close()
可选优化
如果不想手写循环逐行插入,可以直接用pandas自带的to_sql方法,搭配SQLAlchemy连接,代码更简洁、插入效率更高:
import pandas as pd from sqlalchemy import create_engine from sqlalchemy.dialects.mssql import NVARCHAR, INTEGER # 读取Excel df = pd.read_excel (r"C:\Users\c.stembridge\OneDrive - NEWREST GROUP SERVICES\Overtime Forecast Report.xlsx", sheet_name='Daily Hrs2') # 创建数据库连接 conn_str = "mssql+pyodbc://SA:Working@2022@localhost/testdb?driver=ODBC Driver 18 for SQL Server&Encrypt=no&TrustServerCertificate=yes" engine = create_engine(conn_str) # 直接写入数据库,if_exists参数:replace=覆盖已有同名表,append=往已有表追加数据 df.to_sql( name="Overtime_Forecast", con=engine, if_exists="replace", index=False, # 自定义字段类型,和手动建表的类型保持一致 dtype={ "date": NVARCHAR(10), "day": NVARCHAR(9), "hrs": INTEGER, "dl": INTEGER, "catered": INTEGER, "hrs_diff_btwn_last_day": INTEGER, "catered_flight_diff": INTEGER, "employees_OT_count": INTEGER, "carriers": INTEGER, "whole": INTEGER, "half": INTEGER, "total_carts": INTEGER } )
注意:用to_sql自动建表时,如果需要设置主键,可以在插入完成后单独执行SQL语句添加约束即可。
内容的提问来源于stack exchange,提问作者user18495643
相关产品推荐
相关产品推荐

