SQL 遍历字符串,你想遍历一个字符串,并以一个字符一行的形式把它们显示出来,但 SQL 没有 Loop
循环功能。例如,你想把 EMP
表的 ENAME
等于 KING
的字符串拆开来显示为 4 行,每行一个字符。
SQL 遍历字符串 问题描述
你想遍历一个字符串,并以一个字符一行的形式把它们显示出来,但 SQL 没有 Loop
循环功能。例如,你想把 EMP
表的 ENAME
等于 KING
的字符串拆开来显示为 4 行,每行一个字符。
SQL 遍历字符串 解决方案
使用笛卡儿积生成以每行一个字符的形式来显示字符串所需要的行数。然后,使用数据库内置的字符串解析函数提取我们感兴趣的字符(如果是 SQL Server 的话,要用 SUBSTRING
替换 SUBSTR
)。
1 select substr(e.ename,iter.pos,1) as C
2 from (select ename from emp where ename = 'KING') e,
3 (select id as pos from t10) iter
4 where iter.pos <= length(e.ename)
C
-
K
I
N
G
SQL 遍历字符串 扩展知识
要遍历一个字符串里的全部字符,关键在于要先和另一个表做连接查询,该表必须有足够多的行以保证循环操作的次数。本例使用的是 T10
表,该表有 10 行记录(它只有一列,列名为 ID
,它的值分别是从 1 到 10)。也就是说,上述查询最多返回 10 行。
下面的例子省略了 ENAME
解析处理,仅展示了 E
和 ITER
的笛卡儿积(例如,某个员工的名字和 T10
表的 10 行数据的笛卡儿积)。
select ename, iter.pos
from (select ename from emp where ename = 'KING') e,
(select id as pos from t10) iter
ENAME POS
---------- ----------
KING 1
KING 2
KING 3
KING 4
KING 5
KING 6
KING 7
KING 8
KING 9
KING 10
内嵌视图 E
的行数是 1,而内嵌视图 ITER
的行数是 10,所以得到的笛卡儿积就是 10 行。产生这样一个笛卡儿积是使用 SQL 来模拟循环操作的第一步。
![](https://img.geek-docs.com/sql/tip.png) 把 `T10` 表作为一个数据透视表是常用技巧。
这个解决方案使用 WHERE
子句在查询语句返回了 4 行数据之后跳出了循环。为了保证结果集的行数等于给定员工名字的字符个数,WHERE
子句把 ITER.POS <= LENGTH(E.ENAME)
作为条件。
select ename, iter.pos
from (select ename from emp where ename = 'KING') e,
(select id as pos from t10) iter
where iter.pos <= length(e.ename)
ENAME POS
---------- ----------
KING 1
KING 2
KING 3
KING 4
现在我们得到的记录行数和 E.ENAME
的字符数一样多,接下来可以把 ITER.POS
作为 SUBSTR
的参数,这样就能遍历字符串里的每个字符。ITER.POS
的值会逐行递增,这样每一行都能从 E.ENAME
里提取出一个连续的字符。这就是该解决方案的工作原理。
根据不同的任务目标,我们或许不需要为一个字符串里的每个字符都产生一行数据。下面的查询展示了一个遍历 E.ENAME
的例子,但是查询结果打印的却是字符串的不同部分(不只是单个字符)。
select substr(e.ename,iter.pos) a,
substr(e.ename,length(e.ename)-iter.pos+1) b
from (select ename from emp where ename = 'KING') e,
(select id pos from t10) iter
where iter.pos <= length(e.ename)
A B
---------- ------
KING G
ING NG
NG ING
G KING
在本章的实例中,最常见的使用场景包括遍历字符串并为其中的每个字符产生一行数据,或者遍历字符串并根据某些特别的字符或分隔符来生成相应行数的记录。