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

FastAPI+SQLAlchemy调用MSSQL存储过程插入数据时参数报错求助

解决FastAPI+SQLAlchemy调用MSSQL带输出参数存储过程的问题

你在调用带输出参数的MSSQL存储过程时遇到了几个典型问题,我来帮你逐一梳理并解决:

问题根源分析

  1. 参数标记不匹配错误:你用SQLAlchemy的text()包裹了整个SQL语句,但raw_connection()返回的是原生DBAPI游标,并不支持text()对象,这会导致驱动误解析参数数量。
  2. 无结果返回错误:你的存储过程执行的是插入操作而非查询,fetchall()自然拿不到结果;而且输出参数需要单独提取,不能用查询结果的方式获取。
  3. 重复连接资源浪费:你已经在database.py中初始化了数据库引擎,没必要在接口里重复创建连接,复用已有资源即可。

修正后的完整代码

我们直接复用database.py里的引擎,正确处理存储过程的输入/输出参数:

from fastapi import APIRouter, Request, Depends, HTTPException
from fastapi.responses import JSONResponse
from sqlalchemy.exc import ProgrammingError
from dependencies import get_db
# 导入database.py中已初始化的引擎
from database import engine

@router.post("/create/CostCenter/")  # 插入操作建议用POST而非GET,符合REST规范
async def create_cost_center(request: Request, db=Depends(get_db)):
    try:
        connection = engine.raw_connection()
        try:
            cursor_obj = connection.cursor()
            # 定义存储过程调用,用?作为参数占位符(MSSQL ODBC驱动标准)
            proc_query = "EXEC AcctsCostCentersAddV001 ?, ?, ? OUTPUT"
            
            # 准备参数:前两个是输入,第三个是输出参数(用None占位)
            input_params = ("Test", "Test", None)
            
            # 执行存储过程,自动绑定参数
            cursor_obj.execute(proc_query, input_params)
            
            # 获取输出参数:通过游标_output_parameters属性提取第三个参数(索引2)
            err_msg = cursor_obj._output_parameters[2]
            
            # 提交事务,确保插入操作生效
            connection.commit()
            
            print(f"存储过程执行成功,输出ErrMsg: {err_msg}")
            return JSONResponse({"status": "success", "err_msg": err_msg})
        
        finally:
            # 确保游标和连接关闭,释放资源
            cursor_obj.close()
            connection.close()
    
    except IndexError:
        raise HTTPException(status_code=404, detail="Not found")
    except ProgrammingError as e:
        print(e)
        raise HTTPException(status_code=400, detail="Invalid Entry")
    except Exception as e:
        print(e)
        raise HTTPException(status_code=500, detail=f"unknown error caused by CostCenter API request handler: {str(e)}")

关键细节说明

  • 参数占位符规范:MSSQL的ODBC驱动使用?作为参数标记,不要硬编码参数值(避免SQL注入风险)。
  • 输出参数提取:执行后通过cursor._output_parameters获取输出参数,索引对应参数传入的顺序(第三个参数对应索引2)。
  • REST规范优化:把@router.get改为@router.post,因为插入操作属于修改资源的行为,POST语义更合适。
  • 资源复用:直接使用database.py中初始化的引擎,避免重复创建连接池,减少资源消耗。

测试验证

  1. 先在MSSQL中手动执行存储过程确认功能正常;
  2. 启动FastAPI服务,用POST请求调用/create/CostCenter/接口;
  3. 检查数据库是否新增了记录,同时接口会返回存储过程设置的err_msg: Test。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 20:24:06