FastAPI处理MySQL主键/唯一键冲突时异常捕获不生效如何解决
问题原因
你的代码存在3个核心错误导致异常无法正确捕获:
- 错误的判断逻辑:你写的
if query is None永远不会成立,query是你手动拼接的SQL字符串,不可能为空。主键/唯一键冲突是执行SQL插入语句时MySQL返回的错误,会以异常的形式抛出,你完全没有捕获这部分异常。 - 存在SQL注入风险:直接用
%拼接SQL字符串,不仅可能触发特殊字符报错,还会被恶意用户注入攻击,必须用驱动自带的参数化查询方法。 - 资源未正确释放:异常场景下游标和数据库连接不会主动关闭,容易造成连接泄漏。
修复后的代码
# 建议把import放到文件头部,不要写到接口函数里 import mysql.connector from fastapi import HTTPException @app.post(path='/create') def create_record(request: Request, sid: str = Form(...), name: str = Form(...), last_name: str = Form(...), email: str = Form(...), add: str = Form(...), gpa: str = Form(...)): cnx = None cursor = None try: cnx = mysql.connector.connect(user='NOPE', host='NOPE', database='NOPE', password='NOPE') cursor = cnx.cursor() # 用参数化查询,不要自己拼SQL query = "INSERT INTO `StudentInfo`.`Student` (`StudentId`, `FirstName`, `LastName`, `Email`, `Address`, `GPA`) VALUES (%s, %s, %s, %s, %s, %s);" # execute第二个参数传参数列表,驱动会自动做转义 cursor.execute(query, (sid, name, last_name, email, add, gpa)) cnx.commit() return templates.TemplateResponse("extend_5.html", {"request": request}) # 捕获MySQL的唯一键冲突异常 except mysql.connector.IntegrityError as e: # 冲突的时候回滚事务 if cnx: cnx.rollback() raise HTTPException( status_code=400, # 客户端参数错误用400比500更合理 detail="学生ID或邮箱已存在,请检查输入后重试,或联系管理员。" ) # 其他数据库异常也可以统一捕获处理 except Exception as e: if cnx: cnx.rollback() raise HTTPException(status_code=500, detail="服务器内部错误,请联系管理员。") finally: # 不管成功失败都关闭游标和连接 if cursor: cursor.close() if cnx: cnx.close()
补充说明
- 唯一键冲突对应的MySQL异常类是
mysql.connector.IntegrityError,捕获该异常即可精准判断是主键/唯一键重复的场景。 - 建议错误码用400而不是500,500是服务端未知错误,重复提交属于用户输入错误,用4xx类状态码更符合HTTP规范。
内容的提问来源于stack exchange,提问作者Myst
相关产品推荐
相关产品推荐

