簡體   English   中英

從 Oracle SQL 中的字符串中提取值

[英]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_countregexp_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM