Reverse String Word by Word using SQL

后端 未结 5 1447
半阙折子戏
半阙折子戏 2020-12-15 13:19

I would need to reverse the word positions in a sentence or String.

For example : \"Hello World! I Love StackOverflow\", to be displayed as \"StackOverflow          


        
相关标签:
5条回答
  • 2020-12-15 13:48

    XML-based version to avoid defining your own function; requires 11g for listagg():

    select listagg(word, ' ') within group (order by rn desc) as reversed
    from (
      select word, rownum as rn
      from xmltable('for $i in ora:tokenize($STR, " ") return $i'
        passing 'Hello World! I Love StackOverflow' as str
        columns word varchar2(4000) path '.'
      )
    );
    
    REVERSED                               
    ----------------------------------------
    StackOverflow Love I World! Hello        
    

    The XMLTable() does the tokenising, and assigns a row number:

    select rownum as rn, word
    from xmltable('for $i in ora:tokenize($STR, " ") return $i'
      passing 'Hello World! I Love StackOverflow' as str
      columns word varchar2(4000) path '.'
    );
    
            RN WORD               
    ---------- --------------------
             1 Hello                
             2 World!               
             3 I                    
             4 Love                 
             5 StackOverflow        
    

    The listagg() then pieces it back together in reverse order.

    0 讨论(0)
  • 2020-12-15 13:52

    Create a Function:

    REGEXP_SUBSTR('Your text here','[^ ]+', 1, ?) will extract a word from the text using Space as a delimiter. Tt returns the original String itself on Exception!

    CREATE OR REPLACE FUNCTION reverse_words (v_STRING IN VARCHAR2)
    RETURN VARCHAR2
    IS
       L_TEMP_TEXT  VARCHAR2(4000);
       L_FINAL_TEXT  VARCHAR2(4000);
       V_LOOPCOUNT NUMBER :=0;
       T_WORD VARCHAR2(4000);
    BEGIN
          L_TEMP_TEXT := regexp_replace(V_STRING,'[[:space:]]+',' '); -- Replace multiple spaces as single
          LOOP
            v_LOOPCOUNT := v_LOOPCOUNT+1;
            T_WORD      := REGEXP_SUBSTR(L_TEMP_TEXT,'[^ ]+', 1, V_LOOPCOUNT);
            L_final_TEXT := T_WORD||' '||L_final_TEXT;
          EXIT WHEN T_WORD IS NULL;
          END LOOP;
       RETURN(TRIM(L_final_TEXT));
    EXCEPTION
        WHEN OTHERS THEN
            DBMS_OUTPUT.PUT_LINE(sqlerrm||chr(10)||dbms_utility.format_error_backtrace);
            RETURN V_STRING;
    END reverse_words;
    /
    

    Sample Result:

    You can call reverse_words(yourcolumn) from your_table

    SQL> select reverse_words('Hello World! I Love StackOverflow') "Reversed" from dual;
    
    Reversed
    --------------------------------------------------------------------------------
    StackOverflow Love I World! Hello
    
    0 讨论(0)
  • 2020-12-15 13:56

    Here you go:

    WITH sel_string AS 
          (SELECT 'Hello World! I Love StackOverflow' AS fullstring FROM DUAL)
      SELECT SUBSTR(fullstring, beg + 1, end_p - beg - 1) AS token
        FROM (SELECT beg, LEAD(beg) OVER (ORDER BY beg) AS end_p, fullstring
                FROM (SELECT beg, fullstring
                        FROM (SELECT LEVEL beg, fullstring
                                FROM sel_string
                                CONNECT BY LEVEL <= LENGTH(fullstring))
                        WHERE INSTR(' ', SUBSTR(fullstring, beg, 1)) > 0
                      UNION ALL
                        SELECT 0, fullstring FROM sel_string
                      UNION ALL
                        SELECT LENGTH(fullstring) + 1, fullstring FROM sel_string))
        WHERE end_p IS NOT NULL AND
              end_p > beg + 1
        ORDER BY ROWNUM DESC;
    

    All in one SQL query. I wish I could claim credit for this query but I can't - found it years ago on the net and have used it ever since.

    Share and enjoy.

    0 讨论(0)
  • 2020-12-15 14:01

    One more solution

    WITH str_tab(str1, rn) AS
    (SELECT regexp_substr(str, '[^\[:space:]]+', 1, LEVEL), 
            LEVEL 
       FROM (SELECT 'Hello World! I Love StackOverflow' str
               FROM dual) tab
    CONNECT BY LEVEL <= LENGTH(str) - LENGTH(REPLACE(str, ' ')) + 1)
    SELECT listagg(str1, ' ') WITHIN GROUP (ORDER BY rn DESC) AS new_text
      FROM str_tab;
    
    0 讨论(0)
  • 2020-12-15 14:10
    DECLARE 
    
    in_string VARCHAR2(500);
    pros_string  VARCHAR2(500);
    out_string  VARCHAR2(800);  
    spce_cnt NUMBER;
    
    
    BEGIN
    
    in_string := 'Hello World! I Love StackOverflow';
    pros_string := ' '||in_string||' ' ;   
    spce_cnt := REGEXP_COUNT(pros_string,' ',1);
    FOR i IN reverse  1.. spce_cnt-1  
    LOOP                               
     out_string := out_string||' '|| SubStr (pros_string,InStr(pros_string, ' ',1,i)+1 ,InStr(SubStr (pros_string,InStr(pros_string, ' ',1,i)+1 ),' '  ));    
    Dbms_Output.Put_Line(out_string);    
    END LOOP; 
    END;
    
    0 讨论(0)
提交回复
热议问题