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

在Django中调用SQL Server存储过程时nvarchar转datetime出错

Django调用SQL Server存储过程传递datetime值报错问题

报错信息

执行代码时触发类型转换错误:

django.db.utils.ProgrammingError: ('42000', '[42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Error converting data type nvarchar to datetime. (8114) (SQLExecDirectW)')

直接拼接datetime变量时,出现语法错误:

django.db.utils.ProgrammingError: ('42000', "[42000] [Microsoft][SQL Server Native Client 11.0][SQL Server]Incorrect syntax near '-'. (102) (SQLExecDirectW)")

直接传递datetime对象则抛出类型错误:

TypeError: can only concatenate str (not "datetime.datetime") to str

问题代码

最初的实现代码:

fromDate = datetime(2022, 1, 1)
toDate = datetime(2022, 12, 31)
dealershipId = request.GET['dealershipId']
cursor = connection.cursor()
cursor.execute(f"EXEC proc_LoadJobCardbyDateRange [@Fromdate={fromDate}, @Todate={toDate}, @DealershipId={dealershipId}]")
result = cursor.fetchall()

尝试的另一种写法:

cursor.execute("EXEC proc_LoadJobCardbyDateRange @Fromdate="+fromDate+", @Todate='2022-12-31 00:00:00', @DealershipId="+dealershipId)

错误原因

  1. 类型拼接错误:直接用+拼接datetime对象和字符串,会触发类型不兼容错误;即使转成字符串,拼接后SQL语句中的日期未加单引号,会被SQL解析成减法运算(如2022-1-1),引发语法错误。
  2. 参数格式与语法错误:用f-string传递datetime时,Python默认的字符串格式不符合SQL Server的datetime解析要求,且存储过程调用时错误地用方括号包裹参数列表,导致SQL解析失败。
  3. 未使用参数化查询:手动拼接/格式化SQL语句,既存在SQL注入风险,又无法让Django自动完成Python类型到SQL Server数据类型的转换,引发类型转换报错。

正确解决方法

使用Django数据库游标的参数化查询,这是官方推荐的安全传参方式,能自动处理类型转换,同时避免SQL注入。

方法1:标准参数化写法

fromDate = datetime(2022, 1, 1)
toDate = datetime(2022, 12, 31)
dealershipId = request.GET['dealershipId']
cursor = connection.cursor()

# 用%s作为占位符,第二个参数传入参数列表
cursor.execute(
    "EXEC proc_LoadJobCardbyDateRange @Fromdate=%s, @Todate=%s, @DealershipId=%s",
    [fromDate, toDate, dealershipId]
)
result = cursor.fetchall()

方法2:适配SQL Server的pyodbc占位符写法

如果上述方式不生效,可使用pyodbc的?占位符:

cursor.execute(
    "EXEC proc_LoadJobCardbyDateRange @Fromdate=?, @Todate=?, @DealershipId=?",
    (fromDate, toDate, dealershipId)
)

关键注意事项

  • 禁止手动拼接SQL语句:无论是f-string还是+拼接,都会带来安全风险和类型问题。
  • 参数化查询自动处理类型转换:Django会自动将Python的datetime对象转换成SQL Server可识别的datetime类型,无需手动转字符串。
  • 存储过程调用语法:参数列表不需要用方括号包裹,直接使用@参数名=占位符格式即可。

内容的提问来源于stack exchange,提问作者Maisum

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 10:45:47