SQLAlchemy中SQL查询的单引号语法错误问题排查与解决
问题原因与解决方法
你的问题出在SQL语法上——生成的语句里LIKE 'Love'%是错误写法,通配符%必须放在单引号内部,数据库会把'Love'当成完整字符串,后面的%就成了无意义的语法碎片,所以才会抛出语法错误。
为什么会出现这个情况?因为你用参数绑定时,:searchFor会被自动包裹成带单引号的字符串,而你写的:searchFor%会被解析成'你的输入'%,直接把%留在了引号外面,完全不符合SQL规则。
下面是具体的解决步骤,还会帮你规避潜在的安全风险:
1. 先解决SQL注入风险(重要!)
你直接把用户传入的searchBy拼进SQL语句里,这是很危险的——如果有人传入恶意的SQL片段(比如title); DROP TABLE books;--),会直接破坏你的数据库。所以第一步必须做列名白名单验证:
from flask import abort # 定义允许搜索的列名(根据你的实际表结构调整) allowed_columns = ["title", "isbn", "name"] if searchBy not in allowed_columns: abort(400, description="无效的搜索字段,仅支持书名、ISBN、作者名")
2. 修正LIKE语句的参数绑定
因为参数绑定会自动给字符串加单引号,所以我们需要在Python代码里把通配符%和用户输入的内容拼接好,再传给SQL:
# 准备带通配符的搜索值 search_for_wildcard = f"{searchFor}%" # 执行查询 books = db.execute( f""" SELECT * FROM books JOIN authors ON books.author_id = authors.id WHERE ({searchBy} = :search_for) OR ({searchBy} LIKE :search_for_wildcard) """, {"search_for": searchFor, "search_for_wildcard": search_for_wildcard} ).fetchall()
现在生成的SQL会变成(title = 'Animal Farm') OR (title LIKE 'Animal Farm%'),完全符合语法要求,不会再报错。
更推荐的SQLAlchemy ORM写法
如果你用SQLAlchemy的ORM方式,能完全避免手动拼接SQL,代码更安全也更易维护:
from sqlalchemy import or_ from your_models import Book, Author # 导入你的模型类 # 列名映射白名单 column_mapping = { "title": Book.title, "isbn": Book.isbn, "name": Author.name } if searchBy not in column_mapping: abort(400, description="无效的搜索字段") target_column = column_mapping[searchBy] # 构建查询 books = db.session.query(Book, Author)\ .join(Author, Book.author_id == Author.id)\ .filter( or_( target_column == searchFor, target_column.like(f"{searchFor}%") ) ).all()
这样不仅解决了语法错误,还彻底规避了SQL注入的风险,是更规范的写法。
内容的提问来源于stack exchange,提问作者Wesley Gonçalves
相关产品推荐
相关产品推荐

