Разделенная труба разделенная строка - Oracle SQL - PullRequest
0 голосов
/ 22 мая 2019

У меня есть таблица со следующей структурой:

table1

f_name           f_content
test1.txt        |0002434299|354534|535345345|05|||BCV RESULT # 174|Test 12%|
test2.txt        |543566677|HTTYE|9w5w RRLL|05|||BBN RESULT # 144|Test 15#%|3

Мне нужно отделить f_content с помощью труб (|) и поставить соответствующую позицию строки.

Выходная таблица:

f_name          position            value
test1.txt       1                   (null)
test1.txt       2                   0002434299
test1.txt       3                   354534
test1.txt       4                   535345345
test1.txt       5                   05
test1.txt       6                   (null)
test1.txt       7                   (null)
test1.txt       8                   BCV RESULT # 174
test1.txt       9                   Test 12%
test1.txt       10                  (null)

test2.txt       1                   (null)
test2.txt       2                   543566677
test2.txt       3                   HTTYE
test2.txt       4                   9w5w RRLL
test2.txt       5                   05
test2.txt       6                   (null)
test2.txt       7                   (null)
test2.txt       8                   BBN RESULT # 144
test2.txt       9                   Test 15#%
test2.txt       10                  3

У меня более 500K записей в таблице1.Каждая запись имеет более 200 каналов.

Есть ли способ написать оптимизированный запрос, чтобы он мог обрабатывать 500K записей с более чем 200 каналами без заполнения табличного пространства отмены?

Может ли SQL-запрос быть записан для обработки кусками и продолжать вставлять его в выходную таблицу?

Ответы [ 2 ]

2 голосов
/ 23 мая 2019

Вам не нужны (медленные) регулярные выражения, и вы можете сделать это с помощью простых строковых функций:

Oracle Setup :

CREATE TABLE table1 ( f_name, f_content ) AS
SELECT 'test1.txt', '|0002434299|354534|535345345|05|||BCV RESULT # 174|Test 12%|' FROM DUAL UNION ALL
SELECT 'test2.txt', '|543566677|HTTYE|9w5w RRLL|05|||BBN RESULT # 144|Test 15#%|3' FROM DUAL

CREATE TABLE output_table (
  f_name   VARCHAR2(20),
  position NUMBER(4,0),
  value    VARCHAR2(50)
);

ВставитьОператор :

INSERT INTO output_table ( f_name, position, value )
WITH rsqfc ( f_name, f_content, idx, spos, epos ) AS (
  SELECT f_name, f_content, 1, 1, INSTR( f_content, '|', 1 )
  FROM   table1
UNION ALL
  SELECT f_name, f_content, idx + 1, epos + 1, INSTR( f_content, '|', epos + 1 )
  FROM   rsqfc
  WHERE  epos > 0
)
SELECT f_name,
       idx,
       CASE
         WHEN epos > 0
         THEN SUBSTR( f_content, spos, epos - spos )
         ELSE SUBSTR( f_content, spos )
       END
FROM   rsqfc

Выход :

SELECT *
FROM   output_table
ORDER BY f_name, position
F_NAME    | POSITION | VALUE           
:-------- | -------: | :---------------
test1.txt |        1 | <em>null</em>            
test1.txt |        2 | 0002434299      
test1.txt |        3 | 354534          
test1.txt |        4 | 535345345       
test1.txt |        5 | 05              
test1.txt |        6 | <em>null</em>            
test1.txt |        7 | <em>null</em>            
test1.txt |        8 | BCV RESULT # 174
test1.txt |        9 | Test 12%        
test1.txt |       10 | <em>null</em>            
test2.txt |        1 | <em>null</em>            
test2.txt |        2 | 543566677       
test2.txt |        3 | HTTYE           
test2.txt |        4 | 9w5w RRLL       
test2.txt |        5 | 05              
test2.txt |        6 | <em>null</em>            
test2.txt |        7 | <em>null</em>            
test2.txt |        8 | BBN RESULT # 144
test2.txt |        9 | Test 15#%       
test2.txt |       10 | 3               

дБ <> скрипка здесь

1 голос
/ 22 мая 2019

Вы можете использовать regexp_substr() оконную аналитическую функцию в сочетании с connect by level <= regexp_count(f_content,'\|')

with t(f_name,f_content) as
(
 select 'test1.txt','|0002434299|354534|535345345|05|||BCV RESULT # 174|Test 12%|' 
   from dual
  union all  
 select 'test2.txt','|543566677|HTTYE|9w5w RRLL|05|||BBN RESULT # 144|Test 15#%|3' 
   from dual   
) 
select f_name,
       level as position,          
       replace( regexp_substr(replace(f_content,'|',' |'),
                                      '([^\|])+',
                                       1,
                                       level
                                      ),' ',null) as value                    
  from t
 connect by level <= regexp_count(f_content,'\|') + 1
     and prior f_name = f_name and prior sys_guid() is not null

Демо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...