应避免直接拼接like参数以防sql注入和参数嗅探,需转义处理;多关键词匹配须拆分后用exists关联;高亮需charindex定位+stuff从右往左替换;全文检索结果需回查原始字段再高亮。

存储过程里用 LIKE 做模糊匹配,但别直接拼接参数
直接写 WHERE name LIKE '%' + @keyword + '%' 看似简单,实际埋了两个雷:一是 SQL 注入(用户输 ' OR 1=1 -- 就完蛋),二是参数嗅探——首次传短词生成的执行计划,后续传长句就卡住。必须用 QUOTENAME(@keyword, '''') 转义单引号,再套一层 REPLACE(..., '''', '''''') 处理嵌套引号。如果业务允许前缀匹配(比如“搜张三”只查姓张三的人),优先用 name LIKE @keyword + '%',这样能走索引。
多关键词空格分隔时,先拆成表变量再 JOIN 或 EXISTS
用户输入 '200g 不锈钢 316L',不能靠 LIKE '%200g%不锈钢%316L%' 这种硬拼——它要求所有词按顺序紧挨着出现,不符合“任一匹配”需求。正确做法是建一个字符串分割函数(如 GETRECORDS),把输入转成单列结果集,再用 EXISTS 关联:
SELECT p.* FROM Products p
WHERE EXISTS (
SELECT 1 FROM dbo.GETRECORDS(@keywords) k
WHERE p.PRD_NO LIKE '%' + k.RECORD + '%'
OR p.NAME LIKE '%' + k.RECORD + '%'
OR p.SPC LIKE '%' + k.RECORD + '%'
)
注意三点:① GETRECORDS 必须去重并过滤空字符串;② 每个 LIKE 条件都带前后 %,否则只匹配完整字段值;③ 别在 ON 子句里做这个关联,JOIN 会引发笛卡尔积爆炸。
高亮提取需用 CHARINDEX + STUFF 手动包裹关键词
SQL Server 没有原生高亮函数,得自己截取+替换。核心逻辑是:对每个匹配关键词,在原始字段中定位起始位置,用 STUFF 把前后插入 <em></em> 标签。难点在于避免重复包裹(比如“数据库”和“数据”同时存在时,“数据库”被包两次)。稳妥做法是先用 CHARINDEX 找出所有关键词位置,排序后从右往左逐个 STUFF(防止左侧修改影响右侧偏移量)。示例片段:
DECLARE @highlighted NVARCHAR(MAX) = @content; SELECT @highlighted = STUFF(@highlighted, pos, LEN(kw), '<em>' + kw + '</em>') FROM (SELECT CHARINDEX(kw, @content) AS pos, kw FROM @keywords_table) t WHERE pos > 0 ORDER BY pos DESC;
这里 @keywords_table 是已去重、已转义的关键词临时表;ORDER BY pos DESC 是关键,否则中间插入会偏移后续位置。
全文检索 CONTAINS 不能直接高亮,得回查原始字段再处理
用 CONTAINS(content_col, @search_term) 查得快,但它只返回行,不告诉你关键词在哪。想高亮,必须先查出主键或唯一标识,再用上一节的方法对原始字段做 STUFF。更麻烦的是:如果 @search_term 含通配符(如 '数据库*'),CONTAINS 会匹配“数据库系统”“数据库设计”,但你无法从结果反推具体匹配了哪个变体——所以高亮时得把所有可能的衍生词(从同义词库或分词器来)都纳入 @keywords_table,再统一扫描。另外,CONTAINS 对参数长度敏感,加 OPTION (RECOMPILE) 强制重编译执行计划,避免短词计划复用到长句上卡死。











