简体   繁体   中英

Seperate data into different columns in Oracle Sql developer

Table_1 contains messages that are of these attributes

  • message -> VARCHAR2(2000 BYTE) -> nullable: Yes

  • Message are seperated by new line, "CLRF" always.

Table_1 messages John DoeCRLF555-555-5555CRLFThis is a test message

How can I split them in separate columns

  1. Column_1: Message
  2. Column_2: John Doe
  3. Column_3: 555-555-5555
  4. Column_4: This is a test message.

A couple things:

  1. This sounds like a version of the common question " how do I split a comma-separated string ", but with CRLF instead of commas. The answers on that link are great, so be sure to look at those.
  2. You aren't really clear about whether your separator is the string "CRLF" or an actual carriage return-line feed combination. I'm going to guess it's the second one, which in Oracle can be represented as chr(13)||chr(10)
  3. The simple answer (below) will only really work for a single input row. If you want this to work on multiple rows, you'll have to tell us what primary key you're using for this table (eg id ). Again, see the link above for a great example of a really clear question.

Anyway, here's the usual way of splitting a newline-delimited string into ROWS. This is what most people do. The regexp is the only part I changed here for your situation (CRLF instead of comma).

-- sample data 
with table_1 as (select 'John Doe' || chr(13)||chr(10) || '555-555-5555' || chr(13)||chr(10) || 'This is a test message' as message from dual)
-- query
select regexp_substr(message, '^[^'||chr(13)||']+', 1, level,'m')
from table_1
connect by regexp_substr(message, '^[^'||chr(13)||']+', 1, level,'m') is not null;

If you want to split it into COLUMNS, I don't think there's an easy way of generating a dynamic number of columns, so you'll have to manually set up each column.

-- sample data 
with table_1 as (select 'John Doe' || chr(13)||chr(10) || '555-555-5555' || chr(13)||chr(10) || 'This is a test message' as message from dual)
-- query
select regexp_substr(message, '^[^'||chr(13)||']+', 1, 1,'m') as col1,
    regexp_substr(message, '^[^'||chr(13)||']+', 1, 2,'m') as col2,
    regexp_substr(message, '^[^'||chr(13)||']+', 1, 3,'m') as col3
from table_1
;

I believe you are looking for something like this. Expects 3 columns and allows for NULL elements.

-- table_1 just sets up the test data
WITH table_1(message) AS (
  SELECT 'John Doe'||CHR(13)||CHR(10)||'555-555-5555'||CHR(13)||CHR(10)||'John This is a test message' FROM dual UNION ALL
  SELECT 'Jane Smith'||CHR(13)||CHR(10)||'555-555-1234'||CHR(13)||CHR(10)||'Jane This is a test message' FROM dual UNION ALL
  SELECT 'Lance Link'||CHR(13)||CHR(10)||'555-555-1212'||CHR(13)||CHR(10)||'Lance This is a test message' FROM dual
)
SELECT message,
       REGEXP_SUBSTR(message, '(.*?)('||CHR(13)||CHR(10)||'|$)', 1, LEVEL,   NULL, 1) column_1,
       REGEXP_SUBSTR(message, '(.*?)('||CHR(13)||CHR(10)||'|$)', 1, LEVEL+1, NULL, 1) column_2,
       REGEXP_SUBSTR(message, '(.*?)('||CHR(13)||CHR(10)||'|$)', 1, LEVEL+2, NULL, 1) column_3
FROM table_1
CONNECT BY LEVEL <= REGEXP_COUNT(message, 'CHR(13)')+1
  AND PRIOR message = message
  AND PRIOR SYS_GUID() IS NOT NULL;


 MESSAGE                        COLUMN_1        COLUMN_2        COLUMN_3                      
------------------------------ --------------- --------------- ------------------------------
Jane Smith
555-555-1234
Jane This is a test message   Jane Smith      555-555-1234    Jane This is a test message   
                                                                                             
                                                                                                    
John Doe
555-555-5555
John This is a test message   John Doe        555-555-5555    John This is a test message   
                                                                                             
                                                                                                    
Lance Link
555-555-1212
Lance This is a test message  Lance Link      555-555-1212    Lance This is a test message  
                                                                                             
                                                                                                    

3 rows selected.

You can use SUBSTRING_INDEX method. See stand-alone example below:

SELECT 
SUBSTRING_INDEX("John DoeCRLF555-555-5555CRLFThis is a test message","CRLF",1) as string1,
SUBSTRING_INDEX(SUBSTRING_INDEX("John DoeCRLF555-555-5555CRLFThis is a test message","CRLF",2),"CRLF",-1) as string2,
SUBSTRING_INDEX(SUBSTRING_INDEX("John DoeCRLF555-555-5555CRLFThis is a test message","CRLF",3),"CRLF",-1) as string3;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM