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

含多单引号输入场景下如何使用参数化查询实现LIKE/ILIKE查询

带LIKE/ILIKE的参数化查询构造规范

核心原则:参数化查询的驱动会自动处理所有输入内容中的特殊字符(包括单引号、反斜杠等)的转义流程,完全不需要手动对输入做转义或字符串拼接,从根源上避免SQL语法错误和注入风险。

1. 基础LIKE/ILIKE参数化的正确实现

构造这类查询时,不要将通配符%直接写在SQL语句的占位符两侧硬编码,优先在应用代码层完成通配符和用户输入的拼接,再将完整的匹配值传入参数占位符,这种写法对所有数据库、所有数据库驱动都有最好的兼容性。

正确写法示例

以PostgreSQL(支持原生ILIKE不区分大小写匹配)、Python psycopg2驱动为例:

  1. 拿到用户的原始输入值
  2. 在代码层完成通配符拼接,生成最终的匹配参数
    match_param = f"%{user_input}%"
  3. 执行完全参数化的查询,SQL语句中不嵌入任何用户输入的原始内容:
    cursor.execute(
        "SELECT * FROM device_records WHERE device_name ILIKE %s",
        (match_param,)
    )
    

这种写法下,哪怕用户输入中包含大量单引号(比如枚举格式字符串'ACCESS_POINT', 'DESKTOP', 'GATEWAY'),驱动都会自动将单引号转义为SQL安全的格式,既不会触发语法错误,也不会有注入风险。

绝对禁止的错误写法

  • 不要手动拼接原始SQL字符串:例如直接通过字符串拼接生成"SELECT * FROM device_records WHERE device_name LIKE '%" + user_input + "%'",这类写法完全失去了参数化查询的防护作用,只要输入包含单引号就会直接触发SQL语法错误,还存在严重的注入风险。
  • 不要手动对输入中的单引号做转义处理(例如将单引号替换为两个单引号再拼接):参数化流程已经完成了所有必要的转义,手动处理反而会导致最终匹配的内容和用户原始输入不一致。

2. 处理带单引号的枚举格式输入的场景

针对输入为'ACCESS_POINT', 'DESKTOP', 'GATEWAY'...这类带单引号、逗号分隔的枚举字符串场景,可根据业务需求选择两种实现方案:

方案1:需要对完整枚举串做模糊匹配

直接将用户传入的完整原始枚举串,在代码层拼好通配符后作为参数值传入占位符即可,不需要手动修改枚举串里的单引号:

# 原始输入:"'ACCESS_POINT', 'DESKTOP', 'GATEWAY'"
raw_enum_input = get_user_input()
match_param = f"%{raw_enum_input}%"
cursor.execute(
    "SELECT * FROM device_records WHERE associated_tags ILIKE %s",
    (match_param,)
)

方案2:需要匹配枚举串中任意一个枚举项的值

相比LIKE模糊匹配,这种场景优先用精确匹配的IN查询,效率更高、避免通配符带来的全表扫描问题:

  1. 在代码层将原始枚举串按逗号拆分,逐个去掉每个枚举项前后的空白和包裹的单引号,生成纯值列表
    value_list = [item.strip().strip("'") for item in raw_enum_input.split(",")]
  2. 将列表作为参数值传入驱动支持的数组占位符语法,完成参数化查询:
    # PostgreSQL 场景,用ANY匹配数组值
    cursor.execute(
        "SELECT * FROM device_records WHERE device_type = ANY(%s)",
        (value_list,)
    )
    

3. 常见避坑提示

  • 不要为了省事在SQL层硬编码拼接通配符:例如写ILIKE '%' || :param || '%'这类逻辑,虽然在部分数据库下可以运行,但不同数据库的字符串拼接语法存在差异(例如SQL Server用+拼接、MySQL用CONCAT()函数拼接),可移植性很差,优先在代码层完成通配符拼接是更稳妥的选择。
  • 跨数据库实现不区分大小写匹配时,不需要硬编码ILIKE:如果你的查询需要兼容不支持ILIKE关键字的数据库(例如MySQL),可以通过同时包裹字段和参数值为小写的方式实现,同样用参数化传值即可:
    SELECT * FROM device_records WHERE LOWER(device_name) LIKE LOWER(%s)
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.25 13:15:03