Using regexp_like in Oracle to match on multiple string conditions - sql

I have a column called Keywords in my Oracle database, Basically Keywords column contains all the data of other columns in particular row separated by _.
Example Table:
NAME PHONE_NUMBER COMPANY ADDRESS ZIPCODE KEYWORD
ABCD 9849523459 MICRO RAJAHMU 532819 ABCD_9849523459_MICRO_RAJAHMU_532819
ABCD 8628738646 INFOS KAKINAD 532775 ABCD_8628738646_INFOS_KAKINAD_532775
ABCD 8473874381 ICUBE RAVULAP 537238 ABCD_8473874381_ICUBE_RAVULAP_537238
Now, How can i get exact string match by using REGEXP_LIKE. When i'm using the below query
SELECT * FROM USER_DATA WHERE 1=1 AND REGEXP_LIKE ('KEYWORD', 'ABCD_MICRO_RAVULAP', 'i'));
It's returning 0 records
My expected output should be
NAME PHONE_NUMBER COMPANY ADDRESS ZIPCODE KEYWORD
ABCD 9849523459 MICRO RAJAHMU 532819 ABCD_9849523459_MICRO_RAJAHMU_532819
ABCD 8473874381 ICUBE RAVULAP 537238 ABCD_8473874381_ICUBE_RAVULAP_537238
I would be very grateful if anyone help me out.
Thanks Inadvance

Something like this?
SQL> with user_data (name, keyword) as
2 (select 'ABCD', 'ABCD_9849523459_MICRO_RAJAHMU_532819' from dual union all
3 select 'DEFG', 'ABCD_8628738646_INFOS_KAKINAD_532775' from dual union all
4 select 'HIJK', 'ABCD_8473874381_ICUBE_RAVULAP_537238' from dual
5 )
6 select *
7 from user_data
8 where regexp_like(keyword, 'ABCD.+MICRO', 'i');
NAME KEYWORD
---- ------------------------------------
ABCD ABCD_9849523459_MICRO_RAJAHMU_532819
SQL>
If you want to search the string for two words in any order, use | operator:
SQL> with user_data (name, keyword) as
2 (select 'ABCD', 'ABCD_9849523459_MICRO_RAJAHMU_532819' from dual union all
3 select 'DEFG', 'ABCD_8628738646_INFOS_KAKINAD_532775' from dual union all
4 select 'HIJK', 'ABCD_8473874381_ICUBE_RAVULAP_537238' from dual union all
5 select 'LMNO', 'MICRO_241241242_ABCD_WHATEVER_241424' from dual
6 )
7 select *
8 from user_data
9 where regexp_like(keyword, '(ABCD).+(MICRO)|(MICRO).+(ABCD)', 'i');
NAME KEYWORD
---- ------------------------------------
ABCD ABCD_9849523459_MICRO_RAJAHMU_532819
LMNO MICRO_241241242_ABCD_WHATEVER_241424
SQL>
However, it isn't practical. Perhaps you should consider Oracle Text feature, then.
SQL> create table
2 user_data (name, keyword) as
3 (select 'ABCD', 'ABCD_9849523459_MICRO_RAJAHMU_532819' from dual union all
4 select 'DEFG', 'ABCD_8628738646_INFOS_KAKINAD_532775' from dual union all
5 select 'HIJK', 'ABCD_8473874381_ICUBE_RAVULAP_537238' from dual union all
6 select 'LMNO', 'MICRO_241241242_ABCD_WHATEVER_241424' from dual
7 );
Table created.
SQL> create index i1_ud on user_data(keyword) indextype is ctxsys.context;
Index created.
SQL> select *
2 from user_data
3 where contains (keyword, '$micro and abcd', 1) > 0;
NAME KEYWORD
---- ------------------------------------
ABCD ABCD_9849523459_MICRO_RAJAHMU_532819
LMNO MICRO_241241242_ABCD_WHATEVER_241424
SQL>

Use IN on the underlying columns rather than trying to parse the composite column:
SELECT *
FROM USER_DATA
WHERE (name, company, address) IN (
('ABCD', 'MICRO', 'RAVULAP'),
('MICRO', 'ABCD', 'RAVULAP')
);
If you want to compare case-insensitively then use UPPER:
SELECT *
FROM USER_DATA
WHERE (UPPER(name), UPPER(company), UPPER(address)) IN (
('ABCD', 'MICRO', 'RAVULAP'),
('MICRO', 'ABCD', 'RAVULAP')
);
If you want to match a single triplet of values to the terms in any order then you can reverse the IN clause:
SELECT *
FROM USER_DATA
WHERE ('ABCD', 'MICRO', 'RAVULAP') IN (
(UPPER(name), UPPER(company), UPPER(address)),
(UPPER(name), UPPER(address), UPPER(company)),
(UPPER(company), UPPER(name), UPPER(address)),
(UPPER(company), UPPER(address), UPPER(name)),
(UPPER(address), UPPER(name), UPPER(company)),
(UPPER(address), UPPER(company), UPPER(name))
);

Related

How to select values ​from a column with a specific word followed by a random number

I need to get all values from a table where in a column appears the text 'demo' followed a number.
My DB is Oracle.
ID NAME
------------
1 demo20
2 demo26
3 demo
4 any
I just need the values ​​with the demo word with a number. At the moment I have this:
select * from table where NAME like 'demo';
You can achieve this using REGEXP_LIKE
select * from t where REGEXP_LIKE(name, '^demo\d');
test here: https://sqlize.online/sql/oracle19/4284f904af9157489dc4a0c9d9515c7c/
+====+========+
| ID | NAME |
+====+========+
| 1 | demo20 |
| 2 | demo26 |
+----+--------+
When you need filter strings not contains additional chars after digits you can use next:
select * from t where REGEXP_LIKE(name, '^demo\d+$');
You can find the names that start with the sub-string demo and have at least one following character using:
SELECT *
FROM table_name
WHERE name LIKE 'demo_%'
If you want to find demo followed by only trailing numbers then, from Oracle 12, you can use:
SELECT *
FROM table_name
WHERE name LIKE 'demo_%'
AND VALIDATE_CONVERSION(SUBSTR(name, 5) AS NUMBER) = 1;
or, in most versions:
SELECT *
FROM table_name
WHERE REGEXP_LIKE(name, '^demo\d+$');
Which, for the sample data:
CREATE TABLE table_name (name) AS
SELECT 'demo20' FROM DUAL UNION ALL
SELECT 'demo26' FROM DUAL UNION ALL
SELECT 'demo2a' FROM DUAL UNION ALL
SELECT 'demo' FROM DUAL UNION ALL
SELECT 'any' FROM DUAL;
Both output:
NAME
demo20
demo26
fiddle

How to check if the length of a string is more than one word and keep only the first word else keep the entire string in SQL?

I have the following table in sql.
I want to keep only the first word in the Name column. I have written the code below however when I run it it extracts the first word for strings longer that one word but returns empty cell for strings which consist of one word only. Could you please advise me how should I modify it to achieve the desired result of keeping only the first word of all strings.
SELECT ID,substr(Name, 1, instr ( Name, ' ' ) -1 ) AS Name FROM names_list
DBMS Toad for Oracle
How about regexp_substr()?
select regexp_substr(name, '^[^ ]+')
from names_list;
This is more flexible than instr(), because you have more control over the separators. For instance, if a comma is sometimes used as well:
select regexp_substr(name, '^[^ ,]+')
from names_list;
This would select the first word out of the name column:
SQL> with names_list (id, name) as
2 (select 1, 'John Smith' from dual union all
3 select 2, 'One' from dual union all
4 select 3, 'Nikola O''Neil' from dual union all
5 select 4, 'Rose Ann Lee' from dual union all
6 select 5, 'Neil' from dual union all
7 select 6, 'William Hugh Forest' from dual union all
8 select 7, 'Andrew' from dual
9 )
10 select id,
11 regexp_substr(name, '^\w+') name
12 from names_list;
ID NAME
---------- --------------------
1 John
2 One
3 Nikola
4 Rose
5 Neil
6 William
7 Andrew
7 rows selected.
SQL>

Oracle db query for regex is not giving correct result

I am using Oracle database and table
-----------------------------
ID : NAME
------------------------------
Now I need to know know how many name follow folling condition
Can contain A to Z
Can contain a to z
Can contain _
I have written query
SELECT *
FROM REGEX_TEST
WHERE REGEXP_LIKE (name,'[A-Za-z0-9_]')
But this is not giving me correct result
Sample result which I want
ID Text Expected result
1 PLAN_20001 PASS
2 A937AH PASS
3 556679815 PASS
4 A93_7AH PASS
5 PLANavd20001 PASS
6 A93*7AH FAIL
7 A93%7AH FAIL
8 A93^7AH FAIL
9 A93$7AH FAIL
10 A93#7AH FAIL
11 A93!7AH FAIL
12 A93~7AH FAIL
13 A93+7AH FAIL
//------------ RESULT -----------
1 PLAN20001
2 A937AH
3 556679815
4 A93 7AH
5 PLANavd20001
6 A93*7AH
7 A93%7AH
8 A93^7AH
9 A93$7AH
10 A93#7AH
11 A93!7AH
12 A93~7AH
13 A93+7AH
At the moment your pattern is matching any character in the name; it will only exclude values that do not contain any of those ranges at all, rather than what you seem to want which is to exclude values that contain anything else. So you need to anchor the pattern with ^ and $, and add a quantifier to allow the pattern to be repeated, with either * or ?. So the pattern becomes '^[A-Za-z0-9_]*$'.
Demo with a CTE to represent your sample data:
WITH REGEX_TEST (id, name) AS (
select 1, 'PLAN20001' from dual
union all select 2,'A937AH' from dual
union all select 3, '556679815' from dual
union all select 4, 'A93 7AH' from dual
union all select 5, 'PLANavd20001' from dual
union all select 6, 'A93*7AH' from dual
union all select 7, 'A93%7AH' from dual
union all select 8, 'A93^7AH' from dual
union all select 9, 'A93$7AH' from dual
union all select 10, 'A93#7AH' from dual
union all select 11, 'A93!7AH' from dual
union all select 12, 'A93~7AH' from dual
union all select 13, 'A93+7AH' from dual
)
SELECT *
FROM REGEX_TEST
WHERE REGEXP_LIKE (name, '^[A-Za-z0-9_]*$');
ID NAME
---------- ------------
1 PLAN20001
2 A937AH
3 556679815
5 PLANavd20001
I've left the numeric range 0-9 in despite you saying twice that you only want letters and underscores, as your reply to David Aldridge then said you did want numbers too.
You could also use the alphanumeric class instead of your ranges, which handles other languages more safely (depending on what you want to match, of course):
WHERE REGEXP_LIKE (name, '^[[:alnum:]_]*$');
Or the Perl-influenced \w operator:
WHERE REGEXP_LIKE (name, '^\w*$');
Or the not-word operator, which doesn't need to be anchored:
WHERE NOT REGEXP_LIKE (name, '\W');

How to divide a record and show specific part of it [duplicate]

This question already has answers here:
Last word in a sentence: In SQL (regular expressions possible?)
(6 answers)
Closed 8 years ago.
I have table with 4 columns.
user_id, user_name, password, full_name
706 , 29682 , 29682 , Nikolay Valeriev Rusanov
707 , 30211 , 30211 , Valentin Ognyanov Karamanchev
When i make the selection i need to show only the last name from the column full_name.
Query should return
user_id, user_name, password, full_name
706 , 29682 , 29682 , Rusanov
707 , 30211 , 30211 , Karamanchev
They are separated with "space".
I can't use substr, because every record in the column have different length and i have more than 10 000 rows.
Can u guys give me some sql query how to do it??
1.
Using simple SUBSTR and INSTR :
SQL> WITH DATA AS(
2 SELECT 'Nikolay Valeriev Rusanov' full_name FROM dual UNION ALL
3 SELECT 'Valentin Ognyanov Karamanchev' FROM dual UNION ALL
4 SELECT 'no reason' FROM dual)
5 SELECT SUBSTR(full_name,instr(full_name,' ',-1)+1) last_name
6 FROM DATA
7 /
LAST_NAME
-----------------------------
Rusanov
Karamanchev
reason
SQL>
2.
Using REGULAR EXPRESSION :
SQL> WITH DATA AS(
2 SELECT 'Nikolay Valeriev Rusanov' full_name FROM dual UNION ALL
3 SELECT 'Valentin Ognyanov Karamanchev' FROM dual UNION ALL
4 SELECT 'no reason' FROM dual)
5 SELECT regexp_substr (full_name, '\w*$') last_name
6 FROM DATA
7 /
LAST_NAME
-----------------------------
Rusanov
Karamanchev
reason
SQL>

delete rows using sql 'like' command using data from another table

I am trying to delete rows from a table ("lovalarm") where a field ("pointid") is like any one of a number of strings.
Currently I am entering them all manually however I need to be able to have a list of over 100,000 options.
My thoughts are to have a table ("lovdata") containing all possible strings and running a query to delete rows where the field is 'like' any of the strings in the other table.
Can anyone point me in the right direction as to if/how I can use like in this way?
Many thanks,
Cap
sure you can join with the LIKE operator:
DELETE FROM lovalarm a
WHERE EXISTS (SELECT NULL
FROM lovdata d
WHERE a.pointid LIKE d.pointid)
The lovdata.pointid column may contain wildcards, consider:
SQL> CREATE TABLE lovalarm AS
2 SELECT 'AA' pointid FROM dual
3 UNION ALL SELECT 'AB' FROM dual
4 UNION ALL SELECT 'AC' FROM dual
5 UNION ALL SELECT 'BA' FROM dual
6 UNION ALL SELECT 'BB' FROM dual
7 UNION ALL SELECT 'BC' FROM dual;
Table created
SQL> --# suppose that you want to remove all entries that start
2 --# with A or end with C
3 CREATE TABLE lovdata AS
4 SELECT 'A%' pointid FROM dual
5 UNION ALL SELECT '%C' FROM dual;
Table created
SQL> DELETE FROM lovalarm a
2 WHERE EXISTS (SELECT NULL
3 FROM lovdata d
4 WHERE a.pointid LIKE d.pointid);
4 rows deleted
SQL> select * from lovalarm;
POINTID
-------
BA
BB
Just use a sub query, like this:
DELETE
FROM lovalarm
WHERE pointid IN (SELECT mystring FROM lovdata)
EDIT: Just noticed that LIKE is required, so IN isn't going to work as this will be exact matches. I'll leave this here for reference as Vincent has already added the correct query.
here is an example with the % concatenations
CREATE TABLE LOVALARM(POINTID VARCHAR2(50) ,TXT VARCHAR2(50));
create table deleteThese(deleteStringList varchar2(50));
/
INSERT INTO LOVALARM(POINTID, TXT) VALUES('abc def','1');
INSERT INTO LOVALARM(POINTID, TXT) VALUES('def','2');
INSERT INTO LOVALARM(POINTID, TXT) VALUES('abc','3');
INSERT INTO LOVALARM(POINTID, TXT) VALUES('efd','4');
INSERT INTO LOVALARM(POINTID, TXT) VALUES('abb','5');
INSERT INTO LOVALARM(POINTID, TXT) VALUES('efd bbb','6');
INSERT INTO LOVALARM(POINTID, TXT) VALUES('abb ccc','7');
INSERT INTO LOVALARM(POINTID, TXT) VALUES('abbbccc','8');
INSERT INTO DELETETHESE(DELETESTRINGLIST) VALUES('abc');
INSERT INTO DELETETHESE(DELETESTRINGLIST) VALUES('bbb');
COMMIT;
/
DELETE LOVALARM
where exists(
SELECT NULL
FROM DELETETHESE
where LOVALARM.pointid like '%' || dELETETHESE.DELETESTRINGLIST || '%'
);
select * from LOVALARM;
POINTID TXT
-------------------------------------------------- -----
def 2
efd 4
ABB 5
abb ccc 7