使用SQL反向字符串Word

时间:2014-01-07 14:15:01

标签: sql oracle plsql

我需要在句子或字符串中反转单词的位置。

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

可以使用SQL完成吗?字长不大于VARCHAR2(4000),这是Oracle VARCHAR2表格列中的最大长度支持。

我得到了用于反转字符串的解决方案(仅按相反顺序的字符)

5 个答案:

答案 0 :(得分:9)

基于XML的版本,以避免定义自己的功能; listagg()需要11g:

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        

XMLTable()执行令牌化,并指定行号:

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        

listagg()然后以相反的顺序将它拼凑回来。

答案 1 :(得分:6)

创建功能

REGEXP_SUBSTR('Your text here','[^ ]+', 1, ?)将使用Space作为分隔符从文本中提取单词。 Tt在Exception上返回原始String本身!

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;
/

示例结果:

您可以致电reverse_words(yourcolumn) from your_table

SQL> select reverse_words('Hello World! I Love StackOverflow') "Reversed" from dual;

Reversed
--------------------------------------------------------------------------------
StackOverflow Love I World! Hello

答案 2 :(得分:3)

你走了:

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;

一体化SQL查询。我希望我可以为这个查询声称自己,但我不能 - 几年前在网上找到它并且从那时起就使用过它。

分享并享受。

答案 3 :(得分:3)

还有一个解决方案

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;

答案 4 :(得分:0)

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;