[英]Extract values from string in Oracle SQL
我正在從 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 有沒有辦法提取這種信息?
您可以同時使用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(str1,'=') 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
其中之一是使用字符串函數。 這是一個帶有解釋的示例方法。
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 的子串。 要提取的下一個子字符串在第一個=字符之后開始,其長度計算為第 4 個換行符與第一個=字符的位置差。
同樣,如果您在同一行源數據中需要提取多行字符串,則需要應用類似的邏輯。
一種更簡單的方法是利用 Oracle 的 PL/SQL 功能並創建一個函數(在內部分步分解字符串),然后在 SQL 中調用該函數。 可以使代碼更具可讀性。 您將在 PL/SQL 中使用相同的字符串函數。 但是,您可以執行一些步驟,使以后可能需要管理您的代碼的其他人更容易遵循代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.