基于SQLSERVER实现:含分隔符字符串数据转换为多值IN列表


基于SQLSERVER实现:含分隔符字符串数据转换为多值IN列表


场景描述:数据表有一个字符串,如 '3,1,2'
你希望在where 子句中使用上述字符串,但是下面的SQL会由于EMPNO列是数值字段而执行失败。
select * from emp where empno in ('3,1,2')
原因是EMPNO是数值类型,而IN列表里却只有一个字符串。你其实希望字符串能够被当作逗号分割的数值列表。


解决思路:
把字符串打散,变成单个的EmpNo。
问:如何打散?
答:遍历字符串,解析字符串,用数据库函数把字符串里的每个元素转换为有效的EMPNO。


实现:
1、遍历字符串:
select substring(csv.emps,iter.pos,len(csv.emps)) as c
from
(select ','+'3,1,2'+',' as emps) csv,
(select row_number() over(order by id) as pos from sysobjects)iter
where iter.pos<=len(csv.emps)
此处结果集:每行都比前一行少一个字符,是冗余的全集,可从中提取所有的字符串子项。
2、解析字符串:
筛选以逗号开头的行,然后在那一行找到下一个逗号,并留下两个逗号之间的所有字符,这一步完成后,接着把要找到的字符串转化为数字。

select convert(int,substring(c,2,charindex(',',c,2)-2)) as empno from(
select substring(csv.emps,iter.pos,len(csv.emps)) as c
from
(select ','+'3,1,2'+',' as emps) csv,
(select row_number() over(order by id) as pos from sysobjects)iter
where iter.pos<=len(csv.emps)
)
至此,实现字符串=>树值列表的转换。

完整例子:
select * from emp where empno in (
select convert(int,substring(c,2,charindex(',',c,2)-2)) as empno from(
select substring(csv.emps,iter.pos,len(csv.emps)) as c
from
(select ','+'3,1,2'+',' as emps) csv,
(select row_number() over(order by id) as pos from sysobjects)iter
where iter.pos<=len(csv.emps)
)
)
说明:
1、select row_number() over(order by id) as pos from sysobjects 用于生成位置的集合,语句可以替换。
前提是结果集为从1自增的集合且集合的行数>=字符串长度即可
2、'3,1,2' 也可以替换为从某个表中select得到的字符串。

posted @ 2021-02-25 10:52  shuevil  阅读(530)  评论(0编辑  收藏  举报