regexp no space - sql

The regexp [[:blank:]] and \s arent they the same.
The below shows 2 different results.
select regexp_replace('Greg94/Eric99Chandler/Faulkner','/','')
from dual
where regexp_like(trim('Greg94/Eric99Chandler/Faulkner'),'[^[[:blank:]]]');
The above query returns no rows whereas when i replace blank with [^/s] it returns the row.

the problem is that you are using [[:blank:]] instead of [:blank:].
Regular Expression [^ [[:blank:]]] evaluate:
^[[:blank:]] : no character within the list "[, [:blank:]"
] last character to be evaluated.
or you remove the last character ']' which is the one that is not returning records or correct the expression:
[^ [:blank:]]
[^\s] is correct.

That would be
SQL> SELECT regexp_replace('Greg94/Eric99Chandler/Faulkner','/','') as result
2 FROM dual
3 WHERE REGEXP_LIKE(TRIM('Greg94/Eric99Chandler/Faulkner'), '[^[:blank:]]');
RESULT
--------------------------------------------------
Greg94Eric99ChandlerFaulkner
SQL>
SQL> SELECT regexp_replace('Greg94/Eric99Chandler/Faulkner','/','') as result
2 FROM dual
3 WHERE NOT REGEXP_LIKE(TRIM('Greg94/Eric99Chandler/Faulkner'), '[[:blank:]]');
RESULT
--------------------------------------------------
Greg94Eric99ChandlerFaulkner
SQL>
SQL> SELECT regexp_replace('Greg94/Eric99Chandler/Faulkner','/','') as result
2 FROM dual
3 WHERE REGEXP_LIKE(TRIM('Greg94/Eric99Chandler/Faulkner'), '[^\s]');
RESULT
--------------------------------------------------
Greg94Eric99ChandlerFaulkner
SQL>
Pick the one you like the most. Besides, if you found what works OK, why don't you simply use it (and forget about the one that doesn't work)? (I guess I know - because of but WHY???).

Perhaps a clearer test would be to generate some strings containing various whitespace characters and then use case expressions to see whether they match different regexes.
with demo (str) as
( select ':' from dual union all
select 'a' from dual union all
select 'b' from dual union all
select 'c' from dual union all
select 'contains'||chr(9)||'tabs' from dual union all
select 'contains'||chr(10)||chr(13)||'linebreaks' from dual union all
select 'contains some spaces' from dual
)
select str
, case when regexp_like(str,'[:blank:]') then 'Y' end as "[:blank:]"
, case when regexp_like(str,'[[:blank:]]') then 'Y' end as "[[:blank:]]"
, case when regexp_like(str,'[[:space:]]') then 'Y' end as "[[:space:]]"
, case when regexp_like(str,'\s') then 'Y' end as "\s"
from demo
order by 1;
STR [:blank:] [[:blank:]] [[:space:]] \s
-------------------- --------- ----------- ----------- --
: Y
a Y
b Y
c
contains tabs Y Y Y
contains Y Y Y
linebreaks
contains some spaces Y Y Y Y
(I manually edited the result for the row with tabs to align the results, otherwise the tab messes it up and makes it harder to read.)
[:blank:] matches any of :, b, l, a, n, k, because a character class is only valid within a [] bracket expression.
[[:blank:]] only matches spaces.
[[:space:]] matches tab, newline, carriage return and space.
\s is the same as [[:space:]]
As for your example, it is not behaving as you expected in two different ways.
Firstly, [^[[:blank:]]] should be [^[:blank:]] - that is, the character class [:blank:] within a bracketed expression.
Secondly, the corrected syntax still returns a match when there are no blanks because it looks for any character that is not a space, for example the first character G is not a space so it matches the expression:
regexp_like('Greg94/Eric99Chandler/Faulkner','[^ ]');
To identify strings that do not contain any whitespace character, you should use:
not regexp_like(str,'\s')
or
not regexp_like(str, '[[:space:]]')

Related

How to get first string after character Oracle SQL

I'm trying to get first string after a character.
Example is like
ABCDEF||GHJ||WERT
I need only
GHJ
I tried to use REGEXP but i couldnt do it.
Can anyone help me with please?
Thank you
Somewhat simpler:
SQL> select regexp_substr('ABCDEF||GHJ||WERT', '\w+', 1, 2) result from dual;
^
RES |
--- give me the 2nd "word"
GHJ
SQL>
which reads as: give me the 2nd word out of that string. Won't work properly if GHJ consists of several words (but that's not what your example suggests).
Something like I interpret with a separator in place, In this case it is || or | example is with oracle database
-- pattern -- > [^] represents non-matching character and + for says one or more character followed by ||
-- 3rd parameter --> starting position
-- 4th parameter --> nth occurrence
WITH tbl(str) AS
(SELECT 'ABCDEF||GHJ||WERT' str FROM dual)
SELECT regexp_substr(str
,'[^||]+'
,1
,2) output
FROM tbl;
I think the most general solution is:
WITH tbl(str) AS (
SELECT 'ABCDEF||GHJ||WERT' str FROM dual UNION ALL
SELECT 'ABC|DEF||GHJ||WERT' str FROM dual UNION ALL
SELECT 'ABClDEF||GHJ||WERT' str FROM dual
)
SELECT regexp_replace(str, '^.*\|\|(.*)\|\|.*', '\1')
FROM tbl;
Note that this works even if the individual elements contain punctuation or a single vertical bar -- which the other solutions do not. Here is a comparison.
Presumably, the double vertical bar is being used for maximum flexibility.
You should use regexp_substr function
select regexp_substr('ABCDEF||GHJ||WERT ', '\|{2}([^|]+)', 1, 1, 'i', 1) str
from dual;
STR
---
GHJ

ORACLE SQL - REGEXP_LIKE Contains First Character As a Number and Second Character as an Alphabet

I am trying to generate a query in Oracle where i can get records that has first character in String as 3 or 4 AND second character is an alphabet. The rest can be anything else.
Something like this
SELECT COL1 FROM TABLE
WHERE REGEXP_LIKE (COL1, '3[A-Za-Z]')
OR REGEXP_LIKE (COL1, '4[A-Za-z]')
I Do get the output but for few records the data doesn't start with 3 or 4.
Meaning it selects those records who have 3 and An alphabet together anywhere in the column.
ex: 10573T2 (10573T2). I have to query records that should start with either 3 or 4 and the next character should be a letter.
Any help would be great
SQL> with test (col) as
2 (select '10573T2' from dual union all
3 select '3A1234F' from dual union all
4 select '23XXX02' from dual union all
5 select '4GABC23' from dual union all
6 select '31234FX' from dual
7 )
8 select col
9 from test
10 where regexp_like(col, '(^3|^4)[[:alpha:]]');
COL
-------
3A1234F
4GABC23
SQL>
begins ^ with 3 or | 4
and is followed by a letter [[:alpha:]]
As of your ^ doubts: that character has two roles:
[^ ... ] - Non-Matching Character List: matches any character not in list ...
^ - Beginning of Line Anchor: match the subsequent expression only when it occurs at the beginning of a line.
You need to anchor the pattern at the beginning of the string:
REGEXP_LIKE(COL1, '^[34][A-Za-z]')
Here is a db<>fiddle

retrieve a specific data from a table after a symbol in oracle

Table DATA
----------------------------
Name
ABC:000
DEF:0
ABD:000
FFF:00
GGG:000
I need only those names which contains only 3 characters post the semicolon.
In the event that the field is stored as a char() and varying, then use trim():
where trim(name) like '%:___'
with
table_name ( name ) as (
select 'ABC:000' from dual union all
select 'DEF:0' from dual union all
select 'ABD:000' from dual union all
select 'FFF:00' from dual union all
select 'GGG:000' from dual
)
-- End of SIMULATED inputs (not part of the SQL query).
-- Solution begins BELOW THIS LINE. Use your actual table and column names.
select name
from table_name
where name like '%:___'
;
NAME
-------
ABC:000
ABD:000
GGG:000
Explanation: like is a comparison operator for strings. % stands for any sequence of characters, of any length (including of length zero). : stands for itself. Underscore stands for exactly one character - ANY character. The comparison string is one % sign, one : semicolon, and three underscores.

PL SQL replace conditionally suggestion

I need to replace the entire word with 0 if the word has any non-digit character. For example, if digital_word='22B4' then replace with 0, else if digital_word='224' then do not replace.
SELECT replace_funtion(digital_word,'has non numeric character pattern',0,digital_word)
FROM dual;
I tried decode, regexp_instr, regexp_replace but could not come up with the right solution.
Please advise.
Thank you.
the idea is simple - you need check if the value is numeric or not
script:
with nums as
(
select '123' as num from dual union all
select '456' as num from dual union all
select '7A9' as num from dual union all
select '098' as num from dual
)
select n.*
,nvl2(LENGTH(TRIM(TRANSLATE(num, ' +-.0123456789', ' '))),'0',num)
from nums n
result
1 123 123
2 456 456
3 7A9 0
4 098 098
see more articles below to see which way is better to you
How can I determine if a string is numeric in SQL?
https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:15321803936685
How to tell if a value is not numeric in Oracle?
You might try the following:
SELECT CASE WHEN REGEXP_LIKE(digital_word, '\D') THEN '0' ELSE digital_word END
FROM dual;
The regular expression class \D matches any non-digit character. You could also use [^0-9] to the same effect:
SELECT CASE WHEN REGEXP_LIKE(digital_word, '\D') THEN '0' ELSE digital_word END
FROM dual;
Alternately you could see if the value of digital_word is made up of nothing but digits:
SELECT CASE WHEN REGEXP_LIKE(digital_word, '^\d+$') THEN digital_word ELSE '0' END
FROM dual;
Hope this helps.
The fastest way is to replace all digits with null (to simply delete them) and see if anything is left. You don't need regular expressions (slow!) for this, you just need the standard string function TRANSLATE().
Unfortunately, Oracle has to work around their own inconsistent treatment of NULL - sometimes as empty string, sometimes not. In the case of the TRANSLATE() function, you can't simply translate every digit to nothing; you must also translate a non-digit character to itself, so that the third argument is not an empty string (which is treated as a real NULL, as in relational theory). See the Oracle documentation for the TRANSLATE() function. https://docs.oracle.com/cd/E11882_01/server.112/e41084/functions216.htm#SQLRF06145
Then, the result can be obtained with a CASE expression (or various forms of NULL handling functions; I prefer CASE, which is SQL Standard):
with
nums ( num ) as (
select '123' from dual union all
select '-56' from dual union all
select '7A9' from dual union all
select '0.9' from dual
)
-- End of simulated inputs (for testing only, not part of the solution).
-- SQL query begins BELOW THIS LINE. Use your own table and column names.
select num,
case when translate(num, 'z0123456789', 'z') is null
then num
else '0'
end as result
from nums
;
NUM RESULT
--- ------
123 123
-56 0
7A9 0
0.9 0
Note: everything here is in varchar2 data type (or some other kind of string data type). If the results should be converted to number, wrap the entire case expression within TO_NUMBER(). Note also that the strings '-56' and '0.9' are not all-digits (they contain non-digits), so the result is '0' for both. If this is not what you needed, you must correct the problem statement in the original post.
Something like the following update query will help you:
update [table] set [col] = '0'
where REGEXP_LIKE([col], '.*\D.*', 'i')

Insert character between string Oracle SQL

I need to insert character string after each character in Oracle SQL.
Example:
ABC will A,B,C
DEFG will be D,E,F,G
This question gives only one character in string
Oracle insert character into a string
Edit: As some fellows have mentioned, Oracle does not admit this regex. So my approach would be to do a regex to match all characters, add them a comma after the character and then removing the last comma.
WITH regex AS (SELECT REGEXP_REPLACE('ABC', '(.)', '\1,') as reg FROM dual) SELECT SUBSTR(reg, 1, length(reg)-1) FROM regex;
Note that with the solution of rtrim there could be errors if the string you want to parse has a final ending comma and you don't want to remove it.
Previous solution: (Not working on Oracle)
Check if this does the trick:
SELECT REGEXP_REPLACE('ABC', '(.)(?!$)', '\1,') FROM dual;
It does a regexp_replace of every character, but the last one for the same character followed by a ,
To see how regexp_replace works I recommend you: https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions130.htm
SELECT rtrim(REGEXP_REPLACE('ABC', '(.)', '\1,'),',') "REGEXP_REPLACE" FROM dual;
You could do it using:
REGEXP_REPLACE
RTRIM
For example,
SQL> WITH sample_data AS(
2 SELECT 'ABC' str FROM dual UNION ALL
3 SELECT 'DEFG' str FROM dual UNION ALL
4 SELECT 'XYZ' str FROM dual
5 )
6 -- end of sample_data mimicking a real table
7 SELECT str,
8 rtrim(regexp_replace(str, '(\w?)', '\1,'),',') new_str
9 FROM sample_data;
STR NEW_STR
---- ----------
ABC A,B,C
DEFG D,E,F,G
XYZ X,Y,Z
Since there is no way to negate the end of string in an Oracle regex (that does not support lookarounds), you may use
SELECT REGEXP_REPLACE(
REGEXP_REPLACE('ABC', '([^,])([^,])','\1,\2'),
'([^,])([^,])',
'\1,\2')
AS Result from dual
See the DB Fiddle. The point here is to use REGEXP_REPLACE with ([^,])([^,]) pattern twice to cater for consecutive matches.
The ([^,])([^,]) pattern matches any non-comma char into Group 1 (\1) and then any non-comma char into Group 2 (\2), and inserts a comma in between them.