3

I am trying to reverse a string without using REVERSE function. I came across one example which is something like:

select listagg(letter) within group(order by lvl)
from 
 (SELECT LEVEL lvl, SUBSTR ('hello', LEVEL*-1, 1) letter 
 FROM   dual 
 CONNECT BY LEVEL <= length('hello'));

Apart from this approach,is there any other better approach to do this?

2
  • 1
    How are you defining "better"? And why don't you want to use reverse; because it isn't documented? Commented Feb 10, 2016 at 12:10
  • @AlexPoole -- note: reverse only works on VARCHAR (ascii) strings, not NVARCHAR (unicode) input. When I use it on nvarchar, I get what looks like Chinese characters, as output. I have to REVERSE(CAST(columnname AS VARCHAR(x))) if the input is nvarchar. Commented May 2 at 21:37

5 Answers 5

3

If you're trying to avoid the undocumented reverse() function you could use the utl_raw.reverse() function instead, with appropriate conversion too and from RAW:

select utl_i18n.raw_to_char(
  utl_raw.reverse(
    utl_i18n.string_to_raw('Some string', 'AL32UTF8')), 'AL32UTF8')
from dual;

UTL_I18N.RAW_TO_CHAR(UTL_RAW.REVERSE(UTL_I18N.STRING_TO_RAW('SOMESTRING','AL32UT
--------------------------------------------------------------------------------
gnirts emoS                                                                     

So that is taking an original value; doing utl_i18n.string_to_raw() on that; then passing that to utl_raw.reverse(); then passing the result of that back through utl_i18n.raw_to_char().

Not entirely sure how that will cope with multibyte characters, or what you'd want to happen to those anyway...

Or a variation from the discussion @RahulTripathi linked to, without the character set handling:

select utl_raw.cast_to_varchar2(utl_raw.reverse(utl_raw.cast_to_raw('Some string')))
from dual;

UTL_RAW.CAST_TO_VARCHAR2(UTL_RAW.REVERSE(UTL_RAW.CAST_TO_RAW('SOMESTRING')))   
--------------------------------------------------------------------------------
gnirts emoS                                                                     

But that thread also notes it only works for single-byte characters.

Sign up to request clarification or add additional context in comments.

Comments

2

You could do it like this:

with strings as (select 'hello' str from dual union all
                 select 'fred' str from dual union all
                 select 'this is a sentance.' from dual)
select str,
       replace(sys_connect_by_path(substr (str, level*-1, 1), '~|'), '~|') rev_str 
from   strings
where  connect_by_isleaf = 1
connect by prior str = str                  --added because of running against several strings at once
           and prior sys_guid() is not null --added because of running against several strings at once 
           and level <= length(str);

STR                 REV_STR             
------------------- --------------------
fred                derf                
hello               olleh               
this is a sentance. .ecnatnes a si siht 

N.B. I used a delimiter of ~| simply because that's something unlikely to be part of your string. You need to supply a non-null delimiter to the sys_connect_by_path, hence why I didn't just leave it blank!

Comments

1
SELECT LISTAGG(STR) WITHIN GROUP (ORDER BY RN DESC)
FROM 
(
     SELECT ROWNUM RN, SUBSTR('ORACLE',ROWNUM,1) STR FROM DUAL 
     CONNECT BY LEVEL <= LENGTH('ORACLE')
);

Comments

0

You can try using this function:

SQL> ed
Wrote file afiedt.buf

  1  with t as (select 'Reverse' as txt from dual)
  2  select replace(sys_connect_by_path(ch,'|'),'|') as reversed_string
  3  from (
  4        select length(txt)-rownum as rn, substr(txt,rownum,1) ch
  5        from t
  6        connect by rownum <= length(txt)
  7       )
  8  where connect_by_isleaf = 1
  9  connect by rn = prior rn + 1
 10* start with rn = 0
SQL> /

Source

Comments

0
select listagg(rev)within group(order by rownum)
from
(select substr('Oracle',level*-1,1)rev from dual
connect by level<=length('Oracle'));

1 Comment

Your answer could be improved with additional supporting information. Please edit your answer to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.