一条LIKE查询问题

今天一朋友在网上问一条特殊的含有"["和"]"的LIKE语句。[@more@]

这里简单整理测试一下LIKE语句对于"["和"]"的应用。

CREATE TABLE #T(x nvarchar(400))
INSERT INTO #T
SELECT '[werx]' UNION ALL
SELECT '[sd[]]' UNION ALL
SELECT '[[sdf]]' UNION ALL
SELECT '[img]sdfds[/img]' UNION ALL
SELECT '[img]/img]]' UNION ALL
SELECT 'img]/img]]' UNION ALL
SELECT '[wsd]'
--我们要查询格式为"[img]内容[/img]"的行
SELECT * FROM #T WHERE x LIKE '%[img]%[/img]%'
/*
结果:
-------------------
[img]sdfds[/img]
[img]/img]]
img]/img]]
*/
SELECT * FROM #T WHERE x LIKE '%[[]%[img]]%[[]%[/img]]%'
/*
结果:
-------------------
[img]sdfds[/img]
*/

DROP TABLE #T

这里引用MS的帮助文档:
这里引用LIKE的说明:
可以将通配符模式匹配字符串用作文字字符串,方法是将通配符放在括号中。下表显示了使用 LIKE 关键字和 [ ] 通配符的示例。

LIKE '5[%]'5%
LIKE '[_]n'_n
LIKE '[a-cdf]'a、b、c、d 或 f
LIKE '[-acdf]'-、a、c、d 或 f
LIKE '[ [ ]'[
LIKE ']']
LIKE 'abc[_]d%'abc_d 和 abc_de
LIKE 'abc[def]'abcd、abce 和 abcf

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/7764484/viewspace-983049/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/7764484/viewspace-983049/

<think>我们有两个步骤:首先使用全文索引查询一个字段,然后在这个结果集上使用LIKE进行二次查询。但需要注意的是,全文索引查询LIKE查询是两种不同的查询方式,通常全文索引查询(如CONTAINS)会返回匹配全文索引条件的行,然后我们可以在这个结果集中再使用LIKE过滤。 然而,在SQL中,我们可以将全文索引查询作为子查询或者使用CTE(公共表表达式)来先获取第一步的结果,然后在第二步使用LIKE。但是要注意,全文索引查询通常返回的是满足全文搜索条件的行,然后我们可以在这些行中再进行LIKE过滤,但这样可能会使全文索引的优势减弱,因为第二步的LIKE可能会再次扫描数据。 具体实现方式(以SQL Server为例): 方法1:使用子查询 ```sql SELECT * FROM ( -- 第一步:使用全文索引查询,假设表为MyTable,全文索引字段为content SELECT * FROM MyTable WHERE CONTAINS(content, 'full_text_keywords') ) AS SubQuery WHERE SubQuery.another_column LIKE '%pattern%'; -- 第二步:在结果集中使用LIKE ``` 方法2:使用CTE(公共表表达式) ```sql WITH FirstStep AS ( SELECT * FROM MyTable WHERE CONTAINS(content, 'full_text_keywords') ) SELECT * FROM FirstStep WHERE another_column LIKE '%pattern%'; ``` 方法3:直接在WHERE子句中同时使用全文索引和LIKE条件(但注意,这样数据库可能会先使用全文索引,然后对结果应用LIKE过滤,取决于优化器) ```sql SELECT * FROM MyTable WHERE CONTAINS(content, 'full_text_keywords') AND another_column LIKE '%pattern%'; ``` 注意: 1. 全文索引查询(如CONTAINS)只能用于建立了全文索引的列,并且语法和函数名因数据库而异(MySQL中为MATCH...AGAINST,SQL Server中为CONTAINS)。 2. 由于第二步使用了LIKE,而且LIKE是以通配符开头(如'%pattern%'),则无法使用普通索引,性能可能会下降。但是,由于第一步已经通过全文索引缩小了结果集,所以第二步的LIKE操作只在一个较小的结果集上执行,因此整体性能可能比全表LIKE要好。 另外,如果第二步的LIKE查询的字段也建立了全文索引,那么建议将两个条件都转换成全文索引查询,这样效率更高。但是,如果两个条件必须分别使用全文索引和LIKE(例如,第二个条件不是全文索引字段),则可以使用上述方法。 示例(SQL Server): 假设有一个表Articles,其中包含两个字段:Content(已建全文索引)和Author(未建全文索引,或需要精确匹配部分字符串)。 我们想先通过全文索引查找Content包含“数据库”的文章,然后再在这些文章中查找作者名字包含“张”的记录。 ```sql -- 使用子查询 SELECT * FROM ( SELECT * FROM Articles WHERE CONTAINS(Content, '数据库') ) AS Temp WHERE Author LIKE '%%'; ``` 但是,如果Author字段也建立了全文索引,那么最好统一使用全文索引查询: ```sql SELECT * FROM Articles WHERE CONTAINS(Content, '数据库') AND CONTAINS(Author, '"张*"'); -- 注意:这里使用全文索引的模糊查询语法,不同数据库语法不同 ``` 由于问题中要求先全文索引再LIKE,所以这里主要讨论第一种情况。 总结步骤: 1. 使用全文索引查询条件筛选出第一步的结果(使用CONTAINS或MATCH等函数)。 2. 在第一步的结果集上,使用LIKE对另一个字段进行模糊查询。 但请注意,这样的查询效率取决于第一步全文索引筛选出的结果集大小。如果第一步结果集很大,第二步的LIKE仍然可能较慢。 另外,在MySQL中,全文索引和LIKE的混合查询也可以类似进行,但MySQL的全文索引有自己的一些限制(比如最小词长度,停用词等)。 例如,在MySQL中: ```sql SELECT * FROM ( SELECT * FROM Articles WHERE MATCH (Content) AGAINST ('数据库' IN NATURAL LANGUAGE MODE) ) AS SubQuery WHERE Author LIKE '%%'; ``` 或者直接写在一起: ```sql SELECT * FROM Articles WHERE MATCH (Content) AGAINST ('数据库' IN NATURAL LANGUAGE MODE) AND Author LIKE '%%'; ``` 结论:实现方法是将全文索引查询作为主条件,然后在此基础上应用LIKE条件。具体语法根据所使用的数据库系统调整。 参考引用: - 关于全文索引的使用,如CONTAINS或MATCH,需要根据数据库类型来编写[^2][^3]。 - 注意LIKE查询的性能问题,尤其是通配符开头的模糊查询无法使用普通索引[^1]。 §§相关问题§§ 1. 如何优化同时使用全文索引和LIKE查询的复合条件查询? 2. 在哪些情况下,全文索引查询LIKE查询更有优势? 3. 如何为多字段组合查询设计全文索引? </think>以下是关于在 SQL 中先使用全文索引查询字段,再对结果使用 LIKE 查询的实现方法和技术细节: --- ### 实现方法(以 SQL Server 为例) #### 步骤 1:创建全文索引(若未建立) ```sql -- 创建全文目录 CREATE FULLTEXT CATALOG ft_catalog AS DEFAULT; -- 在目标字段创建全文索引 CREATE FULLTEXT INDEX ON your_table(your_column) KEY INDEX your_primary_key_index ON ft_catalog; ``` #### 步骤 2:联合使用全文索引查询LIKE ```sql SELECT * FROM ( -- 第一步:使用全文索引快速筛选主结果集 SELECT * FROM your_table WHERE CONTAINS(your_column, '"search_phrase*"') -- 全文索引查询 ) AS subquery -- 第二步:在全文索引结果上执行 LIKE 精细过滤 WHERE subquery.another_column LIKE '%specific_pattern%'; ``` --- ### 关键优势与原理 1. **性能优化**: - 全文索引先过滤掉 90%+ 无关数据(毫秒级响应)[^3] - LIKE 仅在缩小后的结果集上执行(避免全表扫描) ```mermaid graph LR A[10万条原始数据] --> B[全文索引筛选] B -->|返回100条相关记录| C[LIKE精细过滤] C -->|最终10条结果| D[输出] ``` 2. **索引命中规则**: - 全文索引:处理单词/短语搜索(支持 `*` 通配符)[^2] - LIKE:处理固定位置匹配(如后缀 `%val`) - 组合后满足:$\text{字段} \in \text{全文索引结果集} \cap \text{LIKE匹配结果}$ 3. **优化效果对比**(基于引用[^3]测试): | 查询方式 | CPU占用 | 耗时(ms) | 磁盘读取 | |----------|---------|----------|----------| | 纯LIKE | 14026 | 1055 | 171094 | | 全文索引+LIKE | 31 | 36 | 2230 | --- ### 不同数据库实现差异 | 数据库 | 全文索引查询 | LIKE组合写法 | |-----------|----------------------------|----------------------------------| | SQL Server| `CONTAINS(column, 'text')` | `WHERE CONTAINS(...) AND LIKE ...` | | MySQL | `MATCH(column) AGAINST('text')` | 子查询或 JOIN | | PostgreSQL| `column @@ to_tsquery('text')` | CTE 或子查询 | **PostgreSQL 示例**: ```sql WITH ft_search AS ( SELECT * FROM your_table WHERE your_column @@ to_tsquery('search_phrase') ) SELECT * FROM ft_search WHERE details LIKE '%pattern%'; ``` --- ### 使用注意事项 1. **字段选择**: - 全文索引字段:长文本字段(如文章内容、描述) - LIKE 字段:短字段(如分类码、状态标识)[^1] 2. **索引失效规避**: - 避免对全文索引结果直接使用 `LIKE '%...%'` - 优先使用后缀匹配:`LIKE 'prefix%'`(可利用B-tree索引) 3. **动态阈值控制**(防结果集过大): ```sql DECLARE @max_rows INT = 1000; SELECT TOP (@max_rows) * FROM ( SELECT * FROM products WHERE CONTAINS(description, '"electronics*"') ) AS ft_results WHERE product_code LIKE 'USB%'; ``` --- ### 典型应用场景 1. 电商搜索: - 全文索引:商品描述中搜索“防水 蓝牙” - LIKE:筛选特定型号“A173%” 2. 日志分析: - 全文索引:错误日志中匹配“Timeout Exception” - LIKE:定位特定会话ID“SID_X7Y9%” --- > **性能提示**:当 LIKE 模式为 `prefix%` 时,可考虑在目标字段添加普通 B-tree 索引[^1],实现双重索引加速。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值