You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 19:09:19