2014-01-07 9 views
5

Ich müsste die Wortpositionen in einem Satz oder String umkehren.Reverse String Word für Word mit SQL

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

Kann es mit einem SQL getan werden? Die Wortlänge ist nicht größer als VARCHAR2(4000). Dies ist die maximale Länge in einer Oracle VARCHAR2 Tabellenspalte.

habe ich Lösungen für einen String (Zeichen in umgekehrter Reihenfolge) nur

Umkehren
+0

Sie eine PL/SQL-Funktion schreiben konnte, und verwenden Sie es direkt in SQL. –

+0

Es ist relativ einfach, nach der nächsten Instanz eines Leerzeichens zu suchen und eine String-Manipulation mit einer Funktion durchzuführen. Was hast du probiert? –

+2

ein interessantes Hausaufgabenproblem, Ihr Lehrer versuchte wahrscheinlich, Sie über die Verwendung von Sammlungen oder Cursors zu unterrichten, oder um zu sehen, wie schlau Sie sind. Ich denke, Kopieren/Einfügen von SO ist auch schlau;) – tbone

Antwort

5

erstellen Funktion: Platzsparender als Trennzeichen

REGEXP_SUBSTR('Your text here','[^ ]+', 1, ?) wird ein Wort aus dem Text extrahieren. Tt gibt den ursprünglichen String selbst bei Exception zurück!

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

Probe Ergebnis:

können Sie rufen reverse_words(yourcolumn) from your_table

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

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

XML-basierte Version der Definition Ihrer eigenen Funktion zu vermeiden; 11g erfordert für 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   

Die XMLTable() die tokenising der Fall ist, und weist eine Zeilennummer:

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   

Die listagg() dann Stücke zusammen zurück in umgekehrter Reihenfolge.

+0

Danke Alex! Ich habe noch nie xmltable gehört und ich verstehe deine Vorgehensweise. Entschuldigung bin ein Neuling! Für jetzt gehe ich mit einer benutzerdefinierten Funktion, wie es mir besser passt! – ahairshi

2

Hier gehen Sie:

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; 

Alle in einer SQL-Abfrage. Ich wünschte, ich könnte für diese Frage Anerkennung in Anspruch nehmen, aber ich kann nicht - vor Jahren im Internet gefunden und habe es seitdem verwendet.

Teilen und genießen.

+1

Ich lernte LEAD und LAG .. Danke! +1 :) –

2

Eine weitere Lösung

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;