Jason Bennett's Developer Corner

 






Click to see the XML version of this web page.

>


View David Jason Bennett's profile on LinkedIn

 

 

A Little About Jason Bennett ...

I've had an interest in publishing technical articles and HELPFUL code for a few years.  I am (by trade and hobby) a developer who specializes in Oracle technologies and web based architectures.  I have been an employee of both TUSC and Oracle Corporation.  My intent here is to share my ideas and coding experiences with the developer community as a whole.  As with all developers some of my ideas are great and some of them are ....  well you know.  Anyway, I hope you find something here that will aid in your endeavor, or spark a new idea. 

I am more than happy to assist with technical issues and will even write a little code if need be. If you find something on the site that is really useful and you'd like to make a contribution (absolutely up to you and absolutely not required), just click the "Make a Donation" button on the left!

Good luck and good coding !




  Tuesday, November 16, 2004


PL/SQL List Parsing Utility

I have had need of a utility such as the one being provided in this entry on almost every major Oracle development project I've been involved in over the last ten years.  The utility, a PL/SQL package called ListUtils, performs three key functions on a delimited string or list:

(1) It provides the means to retrieve any element at a given position in the list in a single request.

(2) It will count and return the number of elements in a list.

(3) It will compare two lists (or strings) for absolute equality.

Another key feature of this utility is it ability to reduce a list by removing all of the null entries before retrieving a desired element.  Examples are given in the PL/SQL package spec below.  Please feel free to use or improve this code:

 

/*=======================================================*/
/*  Jason Bennett                                        */
/*  PL/SQL Package Containing Three Utilities for        */
/*  manipulating a list or string of delimited elements  */
/*  such as A,B,C,D or A B C D                           */
/*  11/15/2004                                           */
/*=======================================================*/
CREATE OR REPLACE PACKAGE ListUtils AUTHID DEFINER AS

/**
/* The getListElement Function returns the desired element in
/* a delimited list based upon the elements position in the list.
/*
/* Example:
/*    ListUtils.getListElement('A,B,C,D,E',4,',')
/*    would return D.
/*
/* This function can also reduce or clean a list of all null elements
/* using the p_clean_parse parameter. 
/*
/* Example:
/*    ListUtils.getListElement(',,,,,,A,,B,,,C,,,,,D,,,E',4,',','Y')  
/*    would still return D.
/*
/* Note: A delimiter can be any character or series of characters ','
/* and 'xyzsdd' are both acceptable delimiters.
**/

FUNCTION  getListElement( p_string_in       IN VARCHAR2,                                            
                                                p_desired_element IN NUMBER,                                              
                                                p_delimiter       IN VARCHAR2 := ',',                                     
                                                p_clean_parse     IN VARCHAR2 := 'N')

RETURN VARCHAR2;

 

PRAGMA RESTRICT_REFERENCES(getListElement,WNDS,WNPS);

/**
/* The listElementCount function returns the number of elements
/* in a delimited list.
/*
/* Example:
/*    ListUtils.listElementCount('A,B,C,D,E',',') 
/*    would return 5
/*
/* This function can also return a count of all none null elements
/* using the p_clean_count parameter.
/*
/* Example:
/*    ListUtils.listElementCount(',,,,,,A,,B,,,C,,,,,D,,,E',',','Y')  
/*    would still return 5.
/*
**/

FUNCTION listElementCount(p_string_in     IN VARCHAR2,
                                                  p_delimiter     IN VARCHAR2 := ',',
                                                  p_clean_count   IN VARCHAR2 := 'N' )

RETURN NUMBER;

 

PRAGMA RESTRICT_REFERENCES(listElementCount,WNDS,WNPS);


/**
/* The listComp Function compares two delimited lists to
/* determine if they are exact matches. White space and
/* case count.
/*
/* Example:
/*    ListUtils.listComp('a,b,c','a,b,c')
/*    returns TRUE
/*
/*    ListUtils.listComp('a,b,c','a,b, c')
/*    returns FALSE
**/

FUNCTION listComp(p_list_1 VARCHAR2,p_list_2 VARCHAR2) RETURN BOOLEAN;
PRAGMA RESTRICT_REFERENCES(listComp,WNDS,WNPS);

END;
/
sho err;

 

/**********************************************************************/

CREATE OR REPLACE PACKAGE BODY ListUtils AS

 

FUNCTION removeRepeatChars(p_string VARCHAR2 := NULL,

                                                       p_repeat_char VARCHAR2 := NULL)

RETURN VARCHAR2 IS

 

   ret_val VARCHAR2(32000) := NULL;

 

BEGIN

  
   IF INSTR(p_string,p_repeat_char||p_repeat_char) = 0 THEN

     ret_val := p_string;
     
   ELSE

     ret_val := REPLACE(p_string,p_repeat_char||p_repeat_char,p_repeat_char);

     ret_val := removeRepeatChars(ret_val,p_repeat_char);
  
   END IF;

   RETURN ret_val;

END;

/**********************************************************************/

FUNCTION countString(p_string VARCHAR2 := NULL,

                                         p_target VARCHAR2 := NULL,

                                         p_pos NUMBER :=0)

 RETURN NUMBER IS

 

   ret_val NUMBER(12) := 0;

 

BEGIN

 

   IF INSTR(p_string,p_target,1,p_pos+1) < p_pos THEN

 

     ret_val := 0;
     
   ELSE

     ret_val := countString(p_string,p_target,p_pos+1) + 1;
  
   END IF;

 

   RETURN ret_val;

 

END;

 

/**********************************************************************/

FUNCTION  getListElement( p_string_in       IN VARCHAR2,                                            
                                                 p_desired_element IN NUMBER,                                              
                                                 p_delimiter       IN VARCHAR2 := ',',                                     
                                                 p_clean_parse     IN VARCHAR2 := 'N')                                    
RETURN VARCHAR2                                                                               
IS                                                                                            
       v_edit_string            VARCHAR2(32000);  

       v_delimiter_count    NUMBER(4) := 0;                                                       
       v_element_count      NUMBER(4) := 0;                                                                                              
       v_start_position        NUMBER(4);                                                            
       v_end_position         NUMBER(4);                                                            
       e_end_process          EXCEPTION;
                                                                
BEGIN  
                  
    IF (INSTR(p_string_in,p_delimiter)=0) THEN
       IF (p_desired_element != 1) THEN
          RETURN NULL;
       ELSE
          RETURN p_string_in;
       END IF;
    END IF;
 
                                                                    
    /* HANDLE NULL STRING */                                                                    
                                                             
    IF p_string_in IS NULL THEN                                                                
      RAISE e_end_process;                                                                    
    ELSE
      v_edit_string := p_string_in;
    END IF;  

                                                                                                                                                 
                      
    /* REMOVE EXTRA DELIMITERS */
                                          
    IF UPPER(p_clean_parse) = 'Y' THEN

        -- Remove Leading and trailing delimiters                                                       
       v_edit_string := RTRIM(LTRIM(v_edit_string,p_delimiter),p_delimiter);

       -- Reduce consecutive repeating delimiters to one delimiter between elements                                                     
       v_edit_string := removeRepeatChars(v_edit_string,p_delimiter);

       -- Get Count of delimiters
       v_delimiter_count := countString(v_edit_string,p_delimiter);

       -- There always be one more element in a list than there are delimiters.
       v_element_count   := v_delimiter_count+1;
                                                                           
       /*****************/                                                                       
       /* SPECIAL CASES */                                                                       
       /*****************/ 
                                                                     
       /* IF DELIMITER COUNT IS 0 THEN RETURN THE ENTIRE STRING. */ 
                            
       IF (v_delimiter_count = 0) AND (p_desired_element = 1) THEN                                   
           RAISE e_end_process;                                                                    
       END IF;      

                                                                             

       /* DISQUALIFY BOGUS REQUESTS FOR ELEMENTS */
                                             
       IF (p_desired_element > v_element_count) OR (p_desired_element < 1) THEN                        
          v_edit_string := NULL;                                                                   
          RAISE e_end_process;                                                                     
       END IF;

    ELSE

       -- There always be one more element in a list than there are delimiters.
       v_element_count   := listElementCount(v_edit_string,p_delimiter);  
                                                                                
    END IF; /* CLEAN PARSING */  
                                                               
    /********************************/                                                           
    /* ISOLATE THE DESIRED ELEMENT. */                                                           
    /********************************/ 
                                                         
    /* FIND STARTING POSITION OF DESIRED ELEMENT */
                                             
    IF (p_desired_element = 1) THEN                                                                
       v_start_position := 1;                                                                      
    ELSE                                                                                         
       v_start_position := (INSTR(v_edit_string,p_delimiter,1,p_desired_element-1)+length(p_delimiter));
    END IF;
                                                                                     
    /* FIND ENDING POSITION OF DESIRED ELEMENT */
                                               
    IF (p_desired_element = v_element_count) THEN 
       v_end_position := LENGTH(v_edit_string);                                                      
    ELSE                                                                                         
       v_end_position := (INSTR(v_edit_string,p_delimiter,v_start_position,1) - v_start_position);                                                       
    END IF; 
                                                                                    
    /* GET REQUESTED ELEMENT */                                                                  

    v_edit_string := SUBSTR(v_edit_string,v_start_position,v_end_position);
                              
    RETURN v_edit_string;
                                                                          
EXCEPTION                                                                                      
    WHEN e_end_process THEN                                                                     
       RETURN v_edit_string;
                                                               
END;

/*****************************************************************/

FUNCTION listElementCount(p_string_in     IN VARCHAR2,
                          p_delimiter     IN VARCHAR2 := ',',
                          p_clean_count   IN VARCHAR2 := 'N') RETURN NUMBER
IS                                                                                                                                 
                                                          
    e_end_process   EXCEPTION;
    v_count_string  VARCHAR2(32000) := p_string_in;
    v_element_count NUMBER(12)      := 0;
                                                                 
BEGIN        
                                                                                 
   /* HANDLE NULL STRING */ 
                                                                                                                             
   IF v_count_string IS NULL THEN                                                                
      RAISE e_end_process;                                                                    
   END IF;

   IF p_clean_count = 'Y' THEN

      -- Remove Leading and trailing delimiters                                                       
      v_count_string := RTRIM(LTRIM(v_count_string,p_delimiter),p_delimiter);

      -- Reduce consecutive repeating delimiters to one delimiter between elements                                                     
      v_count_string := removeRepeatChars(v_count_string,p_delimiter);

      -- Get Count of elements
   END IF;

   v_element_count := countString(v_count_string,p_delimiter) + 1;      
                                                                               
  RETURN v_element_count;
                                                                       
EXCEPTION                                                                                      
   WHEN e_end_process THEN                                                                     
     RETURN 0;     
                                                          
END;  


/**************************************************************/

FUNCTION listcomp(p_list_1 VARCHAR2,

                                    p_list_2 VARCHAR2) RETURN BOOLEAN
IS

 

  v_return BOOLEAN := TRUE;

 

BEGIN

 

 Lists of unequal length are not equal.
  IF LENGTH(p_list_1) != LENGTH(p_list_2) THEN
    v_return := FALSE;
  ELSE

    -- Perform a character by character comparison.
    FOR step IN 1 .. LENGTH(p_list_1) LOOP

 

     IF SUBSTR(p_list_1,step,1) != SUBSTR(p_list_2,step,1) THEN


       v_return := FALSE;


       EXIT;


     END IF;

   END LOOP;

 

  END IF;

 

  RETURN v_return;

 

END;
                                                      
END;  
/
SHO ERR

 

 

 


9:47:10 PM    

Click here to visit the Radio UserLand website. © Copyright 2008Jason Bennett.
Last update: 8/28/2008; 9:44:17 PM.

November 2004
Sun Mon Tue Wed Thu Fri Sat
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30        
Oct   Feb