Search code examples
sqloracle11goracle-sqldeveloperconnect-by

SQL Query Returning only 5 records instead of 6 rows


I am trying to fetch the data present in a single column which is delimited with double hash (##). As per my query mentioned below, i am able to fetch only 5 records instead of 6 lines.

I could think there is some issue with my connectby expression. Any help is greatly appreciated.

Data

Line1## Line2## Line3 ## Line4 ## Line5  ## Line6  ##

Query Used to fetch the records in a single record which are delimited with double hash ##

Replicate the scenario:

create table temp (errormessage varchar2(300))

insert into  temp errormessage values('Line1## Line2## Line3 ## Line4 ## Line5  ## Line6  ##')



WITH sample_data
     AS ( SELECT errormessage AS Error_Message
          FROM   TEMP )
SELECT Regexp_substr( error_message, ',?([^#]*)', 1, LEVEL, 'i', 1 ) AS Error_Message
FROM   sample_data
WHERE  Length( Regexp_substr( error_message, ',?([^#]*)', 1, LEVEL, 'i', 1 ) ) != 0
CONNECT BY ( Regexp_count(error_message, '#') + 1 >= LEVEL AND
             PRIOR dbms_random.value IS NOT NULL )
ORDER  BY LEVEL 

Error Message is the column which has the info to be delimited. Now it is pretty easy to replicate the issue in any of your databases.


Solution

  • Maybe you're after something like:

    WITH sample_data AS (SELECT 1 stagging_id,
                                'A' status,
                                'Line1## Line2## Line3 ## Line4 ## Line5  ## Line6  ##' error_message
                         FROM   dual UNION ALL
                         SELECT 2 stagging_id,
                                'B' status,
                                'Line1## Line2## Line3 ## Line4 ## Line5  ## Line6  ##Line7  ##' error_message
                         FROM   dual)
    SELECT stagging_id,
           status,
           regexp_substr(error_message, '[^#]+', 1, LEVEL) err_msg
    FROM   sample_data
    CONNECT BY PRIOR stagging_id = stagging_id
               AND PRIOR sys_guid() IS NOT NULL
               AND regexp_substr(error_message, '[^#]+', 1, LEVEL) IS NOT NULL;
    
    STAGGING_ID STATUS ERR_MSG
    ----------- ------ --------------------------------------------------------------
              1 A      Line1
              1 A       Line2
              1 A       Line3
              1 A       Line4
              1 A       Line5
              1 A       Line6
              2 B      Line1
              2 B       Line2
              2 B       Line3
              2 B       Line4
              2 B       Line5
              2 B       Line6
              2 B      Line7
    

    The issue with your existing code is the * in the regexp_substr, plus the fact that you're counting single # whereas your delimiter is ##.

    You could fix your query like so:

    WITH sample_data AS (SELECT 1 stagging_id,
                                'A' status,
                                'Line1## Line2## Line3 ## Line4 ## Line5  ## Line6  ##' error_message
                         FROM   dual UNION ALL
                         SELECT 2 stagging_id,
                                'B' status,
                                'Line1## Line2## Line3 ## Line4 ## Line5  ## Line6  ##Line7  ##' error_message
                         FROM   dual)
    SELECT Regexp_substr( error_message, ',?([^#]+)', 1, LEVEL, 'i', 1 ) AS Error_Message
    FROM   sample_dataCONNECT BY ( Regexp_count(error_message, '##') >= LEVEL AND
                 PRIOR stagging_id = stagging_id AND
                 PRIOR dbms_random.value IS NOT NULL )
    ORDER  BY stagging_id, LEVEL;
    
    ERROR_MESSAGE
    --------------------------------------------------------------
    Line1
     Line2
     Line3
     Line4
     Line5
     Line6
    Line1
     Line2
     Line3
     Line4
     Line5
     Line6
    Line7
    

    Note how I've changed the *s to +s in the regexp_substr's and the '#' to '##' in the regexp_count.