我正在从Oracle的描述字段中提取可能的值。他们有成千上万,我想到了使用SQL来做。
问题在于可能的值会在说明中嵌入“可接受的值:”或“可接受的值:”之后。
此外,这些值还包含代码和说明,例如。
00 =无代码
01 =附加代码
我需要提取可能的值。
这在Oracle表中。
这是源表:
表1
VAR_NAME VAR_DESC
Test 1 Code identifying test 1
Acceptable values:
00=No code
01=Additional Code
Test 2 Code identifying test 2
Acceptable value:
44=No code
这是输出表:
VAR_NAME VAR_DESC CODE DESCRIPTION
Test 1 Code identifying test 1 00 No code
Acceptable values:
00=No code
01=Additional Code
Test 1 Code identifying test 1 01 Additional Code
Acceptable values:
00=No code
01=Additional Code
Test 2 Code identifying test 2 44 No code
Acceptable value:
44=No code
Oracle中是否有一种方法可以提取此类信息?
答案 0 :(得分:1)
您可以同时使用regexp_count
和regexp_instr
。关键字符为=
和回车符(chr(10)
),如下所示:
with table1(var_name,var_desc) as
(
select 'Test 1',
'Code identifying test 1
Acceptable values:
00=No code
01=Additional Code' from dual union all
select 'Test 2',
'Code identifying test 2
Acceptable value:
44=No code' from dual union all
select 'Test 3',
'Code identifying test 3'
from dual
), table2(var_name,str1,description) as
(
select var_name,
case when regexp_count(var_desc,chr(10)) > 0 then
regexp_substr(var_desc,'[^=]+',regexp_instr(var_desc,chr(10), 1, level))
end,
case when regexp_count(var_desc,chr(10)) > 0 then
regexp_substr(var_desc,'=(.*)+',regexp_instr(var_desc,chr(10), 1, level))
end
from table1
connect by level <= regexp_count(var_desc,chr(10))
and prior var_name = var_name
and prior sys_guid() is not null
)
select t1.*,
decode(regexp_count(str1,chr(10)),1,str1) as code, ltrim(str2,'=') as description
from table2 t2
join table1 t1 on t1.var_name = t2.var_name
where decode(regexp_count(str1,chr(10)),1,str1) is not null
order by t1.var_name, code;
VAR_NAME VAR_DESC CODE DESCRIPTION
-------- ----------------------- ---- -----------
Test 1 Code identifying test 1 00 No code
Acceptable values:
00=No code
01=Additional Code
Test 1 Code identifying test 1 01 Additional Code
Acceptable values:
00=No code
01=Additional Code
Test 2 Code identifying test 2 44 No code
Acceptable value:
44=No code
答案 1 :(得分:0)
其中之一是使用字符串函数。这是带有说明的示例方法。
with source_table as (select
'Code identifying test 1
Acceptable values:
00=No code
01=Additional Code' val
from dual)
select substr(val, instr(val, chr(10), 1, 2)+1 ,2) code
,substr(val, instr(val, '=', instr(val,chr(10), 1, 2), 1)+1 , ( instr(val,chr(10), 1, 3) - instr(val,'=', 1, 1) ) ) description
from source_table;
说明
第1步:使用数据创建表:我不是使用临时表并添加测试数据,而是使用 WITH 子句来欺骗表的创建。在这种情况下,我创建了一个名称为 source_table 的表,该表具有一列 val 。它有一行数据,它是source_table第1行中 VAR_DESC 列中的值。您不需要这样做,因为您已经有一个数据库中包含数据的表。
with source_table as (select
'Code identifying test 1
Acceptable values:
00=No code
01=Additional Code' val
from dual)
现在用于实际的字符串提取。 INSTR 查找子字符串在字符串中的位置。 SUBSTR 从字符串中提取一个子字符串。因此,我要做的是,我试图确定您数据中的模式。要提取的第一个数据点位于第二个换行符(chr(10))字符之后。一旦有了这个位置,我就从这一点开始提取长度为2的子字符串。下一个要提取的子字符串在第一个 = 字符之后开始,其长度已计算为第四个 newline 字符与第一个字符之间的位置差 = 个字符。
同样,如果需要在同一行源数据中提取多行字符串,则需要应用类似的逻辑。
更简单的方法是利用Oracle的PL / SQL功能并创建一个函数(该函数在内部将字符串分步拆分),然后在SQL中调用该函数。可以使代码更具可读性。您将在PL / SQL中使用相同的字符串函数。但是您可以执行此步骤,使以后可能需要管理您代码的其他人更容易遵循该代码。