Wednesday, February 19, 2014

Script to Get the Nth Position String within a String

CREATE OR REPLACE PACKAGE xx_delimited_string
AS

-- p_str - the string to get the i'th word from
-- p_str can be xyz,yxz,zyx,zxy and you want to get the zxy as return ---- Value
-- p_n - the word to get from the string -- an index into the string
-- p_enclosed_by - what the words might be wrapped in.  In the above -- -- example, chr(34) is a double quote
-- p_terminated_by - what separates the words.  In the above example, ---- chr(44) is a comma.
  

  
   FUNCTION nth_word(
      p_str                      IN             VARCHAR2
    , p_n                        IN             VARCHAR2
    , p_enclosed_by              IN             VARCHAR2 DEFAULT ''''
    , p_separated_by             IN             VARCHAR2 DEFAULT ','
   )
      RETURN VARCHAR2;

   PRAGMA RESTRICT_REFERENCES(nth_word, WNDS, RNDS);
END xx_delimited_string;
/

CREATE OR REPLACE PACKAGE BODY xx_delimited_string
AS
   TYPE vcarray IS TABLE OF VARCHAR2(2000)
      INDEX BY BINARY_INTEGER;

   g_words                                           vcarray;
   g_empty                                           vcarray;
   g_last_string                                     VARCHAR2(4096);

   FUNCTION de_quote(
      p_str                      IN             VARCHAR2
    , p_enc_by                   IN             VARCHAR2
   )
      RETURN VARCHAR2
   IS
   BEGIN
      RETURN REPLACE(LTRIM(RTRIM(p_str
                               , p_enc_by
                                )
                         , p_enc_by
                          )
                   , p_enc_by || p_enc_by
                   , p_enc_by
                    );
   END de_quote;

   PROCEDURE parse_string(
      p_str                      IN             VARCHAR2
    , p_delim                    IN             VARCHAR2
    , p_sep                      IN             VARCHAR2
   )
   IS
      l_n                                               NUMBER DEFAULT 1;
      l_in_quote                                        BOOLEAN DEFAULT FALSE;
      l_ch                                              CHAR(1);
      l_len                                             NUMBER DEFAULT NVL(LENGTH(p_str)
                                                                         , 0
                                                                          );
   BEGIN
      IF (l_len = 0)
      THEN
         RETURN;
      END IF;

      g_words                                        := g_empty;
      g_words(1)                                     := NULL;

      FOR i IN 1 .. l_len
      LOOP
         l_ch                                           := SUBSTR(p_str
                                                                , i
                                                                , 1
                                                                 );

         IF (l_ch = p_delim)
         THEN
            l_in_quote                                     := NOT l_in_quote;
         END IF;

         IF (    l_ch = p_sep
             AND NOT l_in_quote)
         THEN
            l_n                                            := l_n + 1;
            g_words(l_n)                                   := NULL;
         ELSE
            g_words(l_n)                                   := g_words(l_n) || l_ch;
         END IF;
      END LOOP;

      FOR i IN 1 .. l_n
      LOOP
         g_words(i)                                     := de_quote(g_words(i)
                                                                  , p_delim
                                                                   );
      END LOOP;
   END parse_string;

   FUNCTION nth_word(
      p_str                      IN             VARCHAR2
    , p_n                        IN             VARCHAR2
    , p_enclosed_by              IN             VARCHAR2 DEFAULT ''''
    , p_separated_by             IN             VARCHAR2 DEFAULT ','
   )
      RETURN VARCHAR2
   IS
   BEGIN
      IF (   g_last_string IS NULL
          OR p_str <> g_last_string)
      THEN
         g_last_string                                  := p_str;
         parse_string(p_str
                    , p_enclosed_by
                    , p_separated_by
                     );
      END IF;

      RETURN g_words(p_n);
   EXCEPTION
      WHEN NO_DATA_FOUND
      THEN
         RETURN NULL;
   END nth_word;
END xx_delimited_string;
/


How to Test 

SELECT xx_delimited_string.nth_word(:p_str
                         , 4
                         , CHR(34)
                         , CHR(44)
                          )

  FROM DUAL

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.