FastAPI对接SQL Server执行PATCH/PUT报错无法更新identity列如何解决
FastAPI + SQL Server PATCH/PUT更新报错解决方案
报错原因
你遇到的报错是SQL Server的原生限制:
(pyodbc.ProgrammingError) ('42000', "[42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Cannot update identity column 'id'.")
identity属性修饰的列是SQL Server的自增主键,数据库层面禁止手动修改该字段的值,报错是因为你的更新逻辑把id字段放到了UPDATE语句的SET子句中。
修复方案
- 方案1:单独定义更新专用的Pydantic模型
不要复用包含id字段的创建/返回模型作为PATCH/PUT的请求体模型,单独定义不含主键、所有字段可选的更新模型,适配部分更新的需求:
from pydantic import BaseModel from typing import Optional # 示例:更新模型不包含id字段,所有字段可选 class ItemUpdate(BaseModel): name: Optional[str] = None price: Optional[float] = None description: Optional[str] = None
接口路径函数中使用该模型,更新时仅取用户传入的非空字段赋值:
@app.patch("/items/{item_id}") def update_item(item_id: int, update_data: ItemUpdate, db: Session = Depends(get_db)): # 按路径参数的id查询待更新记录 target_item = db.query(Item).filter(Item.id == item_id).first() if not target_item: return {"code": 404, "msg": "目标记录不存在"} # 仅更新用户传入的字段,exclude_unset会过滤掉未赋值的字段 for field, value in update_data.dict(exclude_unset=True).items(): setattr(target_item, field, value) db.commit() db.refresh(target_item) return target_item
- 方案2:ORM更新时显式排除id字段
如果你直接使用ORM的update方法批量更新,在转参时显式排除id字段即可:
# 错误写法:会把id字段带入更新逻辑触发报错 db.query(Item).filter(Item.id == item_id).update(update_data.dict()) # 正确写法:排除id字段 db.query(Item).filter(Item.id == item_id).update(update_data.dict(exclude={"id"}))
- 方案3:手写SQL时检查UPDATE语句结构
如果是手写原生SQL执行更新,确保id仅出现在WHERE条件中作为筛选参数,不要放到SET子句里:
-- 错误写法 UPDATE item SET id = ?, name = ? WHERE id = ? -- 正确写法 UPDATE item SET name = ?, price = ? WHERE id = ?
内容的提问来源于stack exchange,提问作者daffa ekanara
相关产品推荐
相关产品推荐

