:在 SQL Server 某个表中有一个 id 字段是 int 类型,如何实现 id 模糊查找?
在 SQL Server 某个表中,有一个 id 字段是 int 类型的,用户需要实现 id 的模糊查找,例如查包含 12 的所有单据,能这样写吗:
select id from test_table where id like '%12%'
有没有更好的方法?
如果下面这个包含文本内容的like是否会报错:
select id from test_table where id like '%1张三%'

先说结论
✅ 语法上可以跑,SQL Server 会隐式转换,但强烈不推荐 where id like '%12%' 这种写法!
-- id 是 int
select id from test_table where id like '%12%'
执行时 SQL Server 内部等价于:
select id from test_table where CAST(id AS VARCHAR(10)) like '%12%'
它的致命问题
无法走索引:对字段做隐式转换,id 上如果有索引,直接失效,变成全表扫描,数据量大的时候很慢;
隐式转换有坑:排序规则、数字超长、某些区域语言下可能出现转换报错或者意外结果;
语义别扭:like 本来是字符串运算符,拿给数字用可读性很差。
方案 1:优先推荐,显式转换,把条件改写成SARG 友好写法(尽量用这个)
注意:%在前 不管怎么写都不能走普通 B 树索引,只要需求是「包含 12」这种中间匹配,本身就不适合普通索引。
如果业务经常要做这种数字包含模糊检索,要单独设计。
显式写法(可读性更好,方便你掌控转换类型):
select id
from test_table
where CAST(id AS VARCHAR(20)) LIKE '%12%';
或者 CONVERT:
select id
from test_table
where CONVERT(VARCHAR(20), id) LIKE '%12%';
对比原来隐式写法:功能结果一模一样,只是把隐式转换改成你看得见的显式转换,性能没有提升,只是更可控、方便排查问题。
方案 2:如果业务量很大、经常做这种「数字包含检索」(真正更好的方案)
int 本身就不是为了 “模糊包含” 设计的,%xx% 属于全文 / 字符串检索场景:
方案 A:增加一个字符串冗余字段,持久化存储 id 的文本形式
新增字段 id_str VARCHAR(20),新增 / 修改数据时同步填充 CAST(id AS VARCHAR(20)),然后给 id_str 建索引:
-- 建索引
CREATE INDEX IX_test_table_idstr ON test_table(id_str);
-- 查询
select id from test_table where id_str like '%12%';
⚠️ 依然:like '%12%' 前缀通配符,普通 B 树索引还是用不上,这个索引帮不到前缀模糊。
方案 B:全文索引(SQL Server Full-Text Search)
适合高频、大数据量的 “包含” 检索:
对 id_str 建立全文索引,用 CONTAINS 查询,性能远高于 like '%xx%'。
方案 C:业务层面规避(最优工程方案)
很多单据编号这种需求,本来就不应该存成 int。
单据号有前导零、需要模糊检索、分段编码 → 直接设计成 varchar 类型,从根源上避免数字转字符串的问题。
方案 3:用数学方式判断(非常不推荐,了解即可)
比如找数字里包含 12,用取模、除法拆数字,写法极其复杂,而且同样全表扫描,可读性爆炸差,极易写错,只适合学习,生产千万别用。
总结一句话
where id like '%12%' 能执行,但是隐式转换、索引失效,不建议直接写;
临时用、数据量不大:改成 CAST(id AS VARCHAR(20)) LIKE '%12%';
经常要模糊检索单据号:单据号直接存 varchar,或者上全文检索;
只要需求是 %关键词% 中间包含,普通 B 树索引天生无法优化,不要幻想加个索引就能提速。
附加高级问题
如果是:
select id from test_table where id like '%1张三%'
也就是中间 like 的内容不是纯数字,会不会导致出错?
先说结论:会隐式转换,大概率直接报错,少数情况不会报错但结果完全错乱,绝对不能这么写!
-- id 是 int
select id from test_table where id like '%1张三%'
原理拆解
LIKE 两边要求是字符串类型。
SQL Server 会做类型优先级判断:int 优先级高于 varchar,所以它不是把 id 转字符串,而是尝试把右边的字符串常量 '%1张三%' 转成 int!
等价于:
select id from test_table where id = CAST('%1张三%' AS int)
👉 '%1张三%' 里面有汉字「张三」,根本转不成整数,直接抛出转换异常:
Conversion failed when converting the varchar value '%1 张三 %' to data type int.
和上一条 id like '%12%' 的关键区别
where id like '%12%'
右边 '%12%' 这个字符串,可以成功转成数字 12,所以 SQL Server 不会报错,然后变成 id=12 的比较?
这里纠正刚才上一轮里一个容易混淆的点:
很多人以为 id like '%12%' 是把 id 转字符串,实际要看执行计划里的隐式转换方向!
当参数是字面量 '%12%',它是 varchar,int 优先级更高,SQL Server 优先尝试把 varchar 转 int。
👉 '%12%' 去掉 % 是 12,刚好能转数字,所以语句能跑,但语义已经不是 “包含 12”,变成 id=12!
这是一个超级经典大坑!很多开发踩坑:以为是模糊匹配,实际变成精准等于!
重点:
id like '%12%':不报错,但不是模糊检索,等价于 id=12id like '%1张三%':里面有汉字,无法转 int → 直接抛转换错误
想要实现【id(int)模糊匹配包含 “1 张三” 这种混合内容】正确写法
你必须强制把 id 转为字符串,把比较方向反过来:
select id
from test_table
where CAST(id AS VARCHAR(20)) LIKE '%1张三%'
此时逻辑:把数字 id 变成字符串,再去匹配。
当然这个业务本身逻辑很怪:id 是纯数字,字符串永远不可能出现 “张三”,这条查询永远返回空,但是语法不会报错。
一句话总结区分
int字段 like '纯数字带%':能执行,但隐式转换方向是右边转 int,变成等值查询,不是模糊包含,属于逻辑 bug;
int字段 like '带中文/字母的字符串':直接报转换失败错误;
- 想稳定实现「数字转字符串后做模糊包含」:必须显式
CAST(id AS varchar) LIKE 'xxx',控制转换方向。
补充测试脚本你可以直接跑验证
-- 测试表
create table test_table(id int);
insert test_table values(12),(112),(123),(212);
-- ① 坑:看起来是like%12%,实际是id=12,只出来一条
select id from test_table where id like '%12%';
-- ② 报错:含中文
-- select id from test_table where id like '%1张三%';
-- ③ 正确写法,真正模糊包含,能查出12,112,123,212
select id from test_table where CAST(id as varchar(20)) like '%12%';
该文章在 2026/10/17 18:27:51 编辑过