提问人:user2293950 提问时间:9/10/2014 最后编辑:Alex Myersuser2293950 更新时间:5/7/2019 访问量:204
如何在oracle中选择子字符串?
How to select sub string in oracle?
问:
我有一个场景,我的数据如下所示:
第18章 第10单元 第16节
- 案例 1:我想从上面的字符串中选择第 18 章。
- 案例 2 : 我想从上面的字符串中选择单元 10。
- 案例 3 : 我想从上面的字符串中选择第 16 节。
答:
我会使用(文档),以及正确的正则表达式。例如:REGEXP_SUBSTR
select regexp_substr('Chapter 18 Unit 10 Sect 16', 'Chapter \d*') from dual;
--Will return: Chapter 18
select regexp_substr('Chapter 18 Unit 10 Sect 16', 'Unit \d*') from dual;
--Will return: Unit 10
select regexp_substr('Chapter 18 Unit 10 Sect 16', 'Sect \d*') from dual;
--Will return: Sect 16
当然,如果你将字符串存储在表中,那么你只需使用这种查询来获得多个结果:Chapter xx Unit yy Sect zz
select regexp_substr(info_column, 'Chapter \d*') from mytable;
您可以替换为 或\d
[0-9]
[[:digit:]]
评论
substr
我会使用旧的 SUBSTR 而不是 REGEXP。由于 REGEXP 会占用太多的 CPU 资源。
您的要求非常简单。
对于数据,如果您希望第 18 章作为输出:Chapter 18 Unit 10 Sect 16
只需执行:
Select substr(column, 1, 10) from table
同样,您可以对其他输出执行此操作。
编辑:伙计们,你们中的一些人可能会想,为什么我要强调旧的 SUBSTR 而不是 REGEXP。只需打开跟踪,然后查看跟踪输出即可。我同意,在较新的版本中,Oracle 对 REGEXP 进行了大量改进。但是,到目前为止,我还没有看到一个我满意的案例。我可能错了,所以,如果有人有测试用例,我真的很想看看。这对我们所有人来说都是一次很好的学习。
更新以显示上述关于 REGULAR EXPRESSION 的测试用例比 SUBSTR + INSTR 更快,是错误的!
正则表达式:
SQL> DECLARE
2 l_start NUMBER := dbms_utility.get_cpu_time;
3 BEGIN
4 FOR i IN (WITH t
5 AS (SELECT 'Chapter '
6 || LEVEL
7 || ' Unit '
8 || LEVEL
9 || ' Sect '
10 || LEVEL d
11 FROM dual
12 CONNECT BY ROWNUM < 100000)
13 SELECT Regexp_substr(d, 'Chapter [0-9]*') chapter,
14 Regexp_substr(d, 'Unit [0-9]*') unit,
15 Regexp_substr(d, 'Sect [0-9]*') sect
16 FROM t) LOOP
17 NULL;
18 END LOOP;
19
20 dbms_output.Put_line('time taken by REGULAR EXPRESSION : '
21 || ( dbms_utility.get_cpu_time - l_start )
22 || ' hsec');
23 END;
24
25 /
time taken by REGULAR EXPRESSION : 61 hsec
PL/SQL procedure successfully completed.
子 + INSTR :
SQL> DECLARE
2 l_start NUMBER := dbms_utility.get_cpu_time;
3 BEGIN
4 FOR i IN (WITH t
5 AS (SELECT 'Chapter '
6 || LEVEL
7 || ' Unit '
8 || LEVEL
9 || ' Sect '
10 || LEVEL d
11 FROM dual
12 CONNECT BY ROWNUM < 100000)
13 SELECT Substr(d, 1, Instr(d, ' ', 1, 2) - 1)
14 chapter,
15 Substr(d, Instr(d, ' ', 1, 2),
16 Instr(d, ' ', 1, 4) - Instr(d,
17 ' ', 1, 2))
18 unit,
19 Substr(d, Instr(d, ' ', 1, 4), Length(d) - Instr(d, ' ', 1,
20 4)
21 + 1)
22 sect
23 FROM t) LOOP
24 NULL;
25 END LOOP;
26
27 dbms_output.Put_line('time taken by SUBSTR + INSTR : '
28 || ( dbms_utility.get_cpu_time - l_start )
29 || ' hsec');
30 END;
31
32 /
time taken by SUBSTR + INSTR : 28 hsec
PL/SQL procedure successfully completed.
因此,可以清楚地看到 SUBSTR + INSTR 花费的时间不到 REGULAR EXPRESSION 的一半。
评论
我的版本,在数据长度不固定时很有用。!这可能有点泛泛而谈
最后一个参数 实际返回相应的案例结果!regexp_substr
SELECT level as case ,
regexp_substr('Chapter 180 Unit 10 Sect 16 World 100', '\w* \d*( )*',1,level) as result
FROM dual
CONNECT BY level <= CEIL(regexp_count('Chapter 180 Unit 10 Sect 16 World 100',' ')/2)
结果:
CASE RESULT
---------- ------------------------
1 Chapter 180
2 Unit 10
3 Sect 16
4 World 100
评论
EXADATA
EXADATA
使用 substr:
declare
l_start number := DBMS_UTILITY.get_cpu_time;
begin
for i in (
with t as (
select 'Chapter ' || level || ' Unit ' || level || ' Sect ' || level d from dual connect by rownum < 100000
)
select substr(d, 1, instr(d, ' ', 1, 2) - 1) chapter
, substr(d,
instr(d, ' ', 1, 2),
instr(d, ' ', 1, 4) - instr(d, ' ', 1, 2)
) unit
, substr(d,
instr(d, ' ', 1, 4),
length(d) - instr(d, ' ', 1, 4) + 1
) sect
from t
)
loop
null;
end loop;
DBMS_OUTPUT.put_line((DBMS_UTILITY.get_cpu_time - l_start) || ' hsec');
end;
126 hsec
使用正则表达式:
declare
l_start number := DBMS_UTILITY.get_cpu_time;
begin
for i in (
with t as (
select 'Chapter ' || level || ' Unit ' || level || ' Sect ' || level d from dual connect by rownum < 100000
)
select regexp_substr(d, 'Chapter [0-9]*') chapter
, regexp_substr(d, 'Unit [0-9]*') unit
, regexp_substr(d, 'Sect [0-9]*') sect
from t
)
loop
null;
end loop;
DBMS_OUTPUT.put_line((DBMS_UTILITY.get_cpu_time - l_start) || ' hsec');
end;
190 hsec
所以正则表达式的解决方案速度较慢,但它更具可读性,如果我是你,我会使用正则表达式。
评论
上一个:无法显示 Toast
下一个:PHP 字数数组计数
评论
chapter 45 unit 145 sect 2