Can you use ascii codes in SELECT statements? Specifically the SOH character - oracle

I have the following simple select statement :
select 'hello' || '|' || 'world' as MYVALUE from dual;
This gives me 2 words, delimited by a pipe.
I want to swap out the pipe delimeter for something else, such as the Ascii SOH character.
How can I use an ascii code in a select statement, such as \u01 ?

The CHR function returns the character for any ASCII code e.g. to get the character with ASCII code 1:
SELECT CHR(1) FROM DUAL;

Related

Oracle regex_replace not working as expected

I have following SQL query (Oracle 18c):
SELECT
--FIRST
translate(
' sOmE tEsT
eNdOfLiNe',
chr(10)||chr(11)||chr(13), 'replText'
) "Result1",
--SECOND
regexp_replace(
' sOmE tEsT
eNdOfLiNe',
'[\x0A|\x0B|`\x0D]', 'replText'
) "Result2",
--THIRD
regexp_replace(
' sOmE tEsT
eNdOfLiNe',
'[\r\n\t]', 'replText', 1, 0
) "Result3"
FROM dual
What I would like to do is replace all tabs, return carriages and new line indicators with new string but it seems like regexp replace is not working (returns initial text). I am really sorry about formatting but I need to handle text in exact format as above with \r \n \t mixed chars.
Here is fiddle: https://dbfiddle.uk/?rdbms=oracle_18&fiddle=63834f9bcab93136635366f18c375b13
I am learning Oracle right now and don't understand why second and third solution returns initial text. The first solution seems to work but I would like to achieve the same effect in SECOND and THIRD solution. What I missed?
I'm pretty sure Oracle does not allow escape sequences in a character class. I believe this is what you have to do. In response to your comment on another answer here and as you are learning, regex is most definitely not regex. Especially Oracle's implementation.
EDIT to explain the regex: The regex pattern is building a string of a regex character class containing 3 characters, hence the concatenation. You can't just have escape characters in the regex as then regex would take those characters as part of the character class pattern itself.
SELECT REGEXP_REPLACE(
' sOmE tEsT
eNdOfLiNe', '['||CHR(9)||CHR(10)||CHR(13)||']', 'X') Result3
FROM dual;
RESULT3
------------------------------
sOmE tEsTXXXXXXXX eNdOfLiNe
1 row selected.
You can try the below using similar format as translate
select regexp_replace(
' sOmE tEsT
eNdOfLiNe',
chr(10)||'|'||chr(11)||'|'||chr(13), 'replText') "Result3"
FROM dual

Replacing multiple CHR() from PLSQL string

I have a PLSQL string which contains chr() special characters like chr(10), chr(13). I want to replace these special characters from the string. I tried the following ways
select regexp_replace('Hello chr(10)Goodchr(13)Morning','CHR(10)|chr(13)','') from dual;
This do not works since regexp_replace do not replace chr() function. Then I tried
select translate('Hello chr(10)Goodchr(13)Morning', 'chr(10)'||'chr(13)', ' ') from dual;
It works partially, ie; I am forced to replace chr() with white space(third parameter). No option if I do not want to replace chr() with white spaces . If I pass third character as null then above query returns null result.
Anybody have any other methods?
The problem with your replacement isn't the logic, it's the syntax. Parentheses are regex metacharacters, and as such, if you want to replace a literal parenthesis, you need to escape it. So your pattern should be this:
chr\(13\)|chr\(10\)
Here is a working query:
select
regexp_replace('Hello chr(10)Goodchr(13)Morning','chr\(13\)|chr\(10\)','', 1, 0, 'i')
from dual
The fifth parameters in the above call to regexp_replace is 'i' and indicates that we want to do a case insensitive replacement.
Demo
The above logic removes the literal text chr(13) and chr(10) from your text. If instead you want to remove the actual control characters chr(13) and chr(10), then you may add those control characters to the alternation, e.g.
select
regexp_replace('Hello chr(10)Goodchr(13)Morning','chr\(13\)|chr\(10\)|chr(10)|chr(13)','', 1, 0, 'i')
from dual
Since regular expression functions are relatively expensive in Oracle I think it's worth showing the alternate method which just uses REPLACE for the same effect.
This replaces occurrences of the each control characters with a space;
SELECT REPLACE(REPLACE('ABC'||CHR(10)||'DEF'||CHR(13)||'GHI'||CHR(10)||'JKL',CHR(13),' '),CHR(10),' ') from dual
And this replaces occurrences of the strings 'CHR(13)' and 'CHR(10)';
select REPLACE(REPLACE('ABCCHR(10)DEFCHR(13)GHICHR(10)JKL','CHR(13)',' '),'CHR(10)',' ') from dual

Oracle: Find control characters except line feed

I'm trying to all rows where a column contains any control charters with the exception of the line feed character (hex value of A). I've tried the following, but this only returns results that have a control character and don't have a line feed. I really want the set of characters that are control characters, LESS the line feed character. Is there a 'minus' operation for character sets, where you can exclude particular ones from it?
SELECT *
FROM MyTable
WHERE REGEXP_LIKE(MyColumn, '[:cntrl: &&[^' || UTL_RAW.CAST_TO_VARCHAR2(HEXTORAW('A')) || ']]{1,}');
Any thoughts?
Thanks!
Well here's a first try that will work but I'm sure this can be made more elegant and efficient:
SELECT *
FROM MyTable
WHERE regexp_like(MyColumn, '[[:cntrl:]]')
AND MyColumn NOT like '%' || chr(10) || '%';

what will translate function do if I want to change some chars to nothing?

I have a sql statement:
select translate('abcdefg', 'abc', '') from dual;
Why the result is nothing?
I think it should be 'defg'.
From the documentation:
You cannot use an empty string for to_string to remove all characters in from_string from the return value. Oracle Database interprets the empty string as null, and if this function has a null argument, then it returns null. To remove all characters in from_string, concatenate another character to the beginning of from_string and specify this character as the to_string. For example, TRANSLATE(expr, 'x0123456789', 'x') removes all digits from expr.
So you can do something like:
select translate('abcdefg', '#abc', '#') from dual;
TRANSLATE('ABCDEFG','#ABC','#')
-------------------------------
defg
... using any character that isn't going to be in your from_string.
select translate('abcdefg', 'abc', '') from dual;
To add to Alex's answer, you could use any character(allowed in SQL) for that matter to concatenate to remove all the characters. So, you could even use a space instead of empty string. An empty string in Oracle is considered as NULL value.
So, you could also do -
SQL> SELECT TRANSLATE('abcdefg', ' abc', ' ') FROM dual;
TRAN
----
defg
SQL>
Which is the same as -
SQL> SELECT TRANSLATE('abcdefg', chr(32)||'abc', chr(32)) FROM dual;
TRAN
----
defg
SQL>
Since the ascii value of space is 32.
It was just a demo, it is better to use any other character than space for better understanding and code readability.

Oracle Regexp to replace \n,\r and \t with space

I am trying to select a column from a table that contains newline (NL) characters (and possibly others \n, \r, \t). I would like to use the REGEXP to select the data and replace (only these three) characters with a space, " ".
No need for regex. This can be done easily with the ASCII codes and boring old TRANSLATE()
select translate(your_column, chr(10)||chr(11)||chr(13), ' ')
from your_table;
This replaces newline, tab and carriage return with space.
TRANSLATE() is much more efficient than its regex equivalent. However, if your heart is set on that approach, you should know that we can reference ASCII codes in regex. So this statement is the regex version of the above.
select regexp_replace(your_column, '([\x0A|\x0B|`\x0D])', ' ')
from your_table;
The tweak is to reference the ASCII code in hexadecimal rather than base 10.
select translate(your_column, chr(10)||chr(11)||chr(13), ' ') from your_table;
to clean it is essential to serve non-null value as params ...
(oracle function basically will return null once 1 param is null, there are few excpetions like replace-functions)
select translate(your_column, ' '||chr(10)||chr(11)||chr(13), ' ') from your_table;
this examples uses ' '->' ' translation as dummy-value to prevent Null-Value in parameter 3

Resources