psql query to return values that contain space at the start/end of the value specified - whitespace

I have a DB with more than 1,000,000 entries in it, some of them contain space char at the start/end of the value.
I have tried the following queries and it works but i would have to go through 1,000,000 records because all id's are unique
select * from tablename where id like '%1234%';
select * from tablename where id='1234 ';
select * from tablename where id=' 1234';
select * from tablename where id=' 1234 ';
is there a query that can be run that returns all values with space/empty char at the start/end of the value?
Appreciate your help
B

You can use a regular expression that says "one or more spaces at the start of the string OR one of more spaces at the end of the string".
select * from tablename where id ~ '^\s+|\s+$';
Each special character:
^ match start of the string
\s match a white space character
| the or operator
+ one or more times
$ match the end of the string.

I found the way to do this
select * from tablename where id like '% %';

Related

Finding fields with non alfa numeric values

I am looking a way to find the values in a column that has non alfa numeric values...
I tried
select 'kjh$' not RLIKE '([0-9][a-z]|[A-Z])*')
but does not work
Thanks for your help
You can use REGEXP '^[A-Za-z0-9]+$' or RLIKE '^[A-Za-z0-9]+$'.
Sample SQL -
select * from my table where mycol not RLIKE '^[A-Za-z0-9]+$'
^ - determines start of the string
$ - end of the string
+ - match the preceding character one or more times
[A-Za-z0-9] - to check alphanumeric or not
I ran a simple select statement to check if a string has alphanumeric or not using regex and here is the output.
select 'Aa90$$bc' ,'Aa90$$bc' rlike '^[A-Za-z0-9]+$'

apex_string.split new line as delimiter

I am using this query to split a string of a text area field inside my SQL query:
select * from "MyTable" a
where NAME in (select * from
TABLE(apex_string.split(:P23_TEXTAREA, ',')))
It works but I would like to split the string with a new line delimiter instead of a comma. I tried already "\n", "\r\n", "" but without success. If I remove the delimiter and use the default, the string gets split only once with a new line. How can I split my string with multiple new line separated entries?
You can try the CHR function:
SELECT *
FROM TABLE(apex_string.split(:P23_TEXTAREA, CHR(10)))
or a string literal containing a newline:
SELECT *
FROM TABLE(apex_string.split(:P23_TEXTAREA, '
'))
Your :P23_TEXTAREA value is: 'TRI_1000'||CHR(13)||CHR(10)||'TRI_10' which, if you split it on CHR(10) (LF) will give you the values 'TRI_1000'||CHR(13) and 'TRI_10' and the second will probably match but the first will not due to the trailing carriage return (CR) character.
It appears you need to either trim the result or split on CR/LF (or an optional CR) rather than just LF:
SELECT *
FROM "MyTable"
WHERE name IN (SELECT *
FROM TABLE(apex_string.split(:P23_TEXTAREA, '\r?\n'))
)
or:
SELECT *
FROM "MyTable"
WHERE name IN (SELECT RTRIM(COLUMN_VALUE, CHR(13))
FROM TABLE(apex_string.split(:P23_TEXTAREA, CHR(10)))
)
The default delimiter for apex_string.split is LF (line feed) so one way to do this is to replace the CR+LF combos with a single LF before passing it to split:
select * from "MyTable" a
where NAME in (select * from
TABLE(apex_string.split(
replace(:P23_TEXTAREA, chr(13)||chr(10), chr(10))
))
)

ORACLE SUBQUERY NOT WORKING IN (IN CONDITION)

I need help
i have records 123,456,789 in rows when i am execute like
this one is working
select * from table1 where num1 in('123','456')
but when i am execute
select * from table1 where num1 in(select value from table2)
no resultset found - why?
Check the DataType varchare2 or Number
try
select * from table1 where num1 in(select to_char(value) from table2)
Storing comma separated values could be the cause of problem.
You can try using regexp_substr to split comma.
First and foremost, an important thing to remember: Do not store numbers in character datatypes. Use NUMBER or INTEGER. Secondly, always prefer VARCHAR2 datatype over CHAR if you wish to store characters > 1.
You said in one of your comments that num1 column is of type char(4). The problem with CHAR datatype is that If your string is 3 characters wide, it stores the record by adding extra 1 space character to make it 4 characters. VARCHAR2 only stores as many characters as you pass while inserting/updating and are not blank padded.
To verify that you may run select length(any_char_col) from t;
Coming to your problem, the IN condition is never satisfied because what's actually being compared is
WHERE 'abc ' = 'abc' - Note the extra space in left side operator.
To fix this, one good option is to pad the right side expression with as many spaces as required to do the right comparison.The function RPAD( string1, padded_length [, pad_string] ) could be used for this purpose.So, your query should look something like this.
select * from table1 where num1 IN (select rpad(value,4) from table2);
This will likely utilise an index on the column num1 if it exists.
The other one is to use RTRIM on LHS, which is only useful if there's a function based index on RTRIM(num1)
select * from table1 where RTRIM(num1) in(select value from table2);
So, the takeaway from all these examples is always use NUMBER types to store numbers and prefer VARCHAR2 over CHAR for strings.
See Demo to fully understand what's happening.
EDIT : It seems You are storing comma separated numbers.You could do something like this.
SELECT *
FROM table1 t1
WHERE EXISTS (
SELECT 1
FROM table2 t2
WHERE ',' ||t2.value|| ',' LIKE '%,' || rtrim(t1.num1) || ',%'
);
See Demo2
Storing comma separated values are bound to cause problems, better change it.
Let me tell you first,
You have stored values in table2 which is comma seperated.
So, how could you match your data with table1 and table2.
Its not Possible.
That's why you did not get any values in result set.
I found the Solution using string array
SELECT T.* FROM TABLE1 T,
(SELECT TRIM(VALUE)AS VAL FROM TABLE2)TABLE2
WHERE
TRIM(NUM1) IN (SELECT COLUMN_VALUE FROM TABLE(FUNC_GETSTRING_ARRAY(TABLE2.VAL)))
thanks

splitting a comma separated field and use in 'IN' clause oracle sql [duplicate]

I have (and don't own, so I can't change) a table with a layout similar to this.
ID | CATEGORIES
---------------
1 | c1
2 | c2,c3
3 | c3,c2
4 | c3
5 | c4,c8,c5,c100
I need to return the rows that contain a specific category id. I starting by writing the queries with LIKE statements, because the values can be anywhere in the string
SELECT id FROM table WHERE categories LIKE '%c2%';
Would return rows 2 and 3
SELECT id FROM table WHERE categories LIKE '%c3%' and categories LIKE '%c2%'; Would again get me rows 2 and 3, but not row 4
SELECT id FROM table WHERE categories LIKE '%c3%' or categories LIKE '%c2%'; Would again get me rows 2, 3, and 4
I don't like all the LIKE statements. I've found FIND_IN_SET() in the Oracle documentation but it doesn't seem to work in 10g. I get the following error:
ORA-00904: "FIND_IN_SET": invalid identifier
00904. 00000 - "%s: invalid identifier"
when running this query: SELECT id FROM table WHERE FIND_IN_SET('c2', categories); (example from the docs) or this query: SELECT id FROM table WHERE FIND_IN_SET('c2', categories) <> 0; (example from Google)
I would expect it to return rows 2 and 3.
Is there a better way to write these queries instead of using a ton of LIKE statements?
You can, using LIKE. You don't want to match for partial values, so you'll have to include the commas in your search. That also means that you'll have to provide an extra comma to search for values at the beginning or end of your text:
select
*
from
YourTable
where
',' || CommaSeparatedValueColumn || ',' LIKE '%,SearchValue,%'
But this query will be slow, as will all queries using LIKE, especially with a leading wildcard.
And there's always a risk. If there are spaces around the values, or values can contain commas themselves in which case they are surrounded by quotes (like in csv files), this query won't work and you'll have to add even more logic, slowing down your query even more.
A better solution would be to add a child table for these categories. Or rather even a separate table for the catagories, and a table that cross links them to YourTable.
You can write a PIPELINED table function which return a 1 column table. Each row is a value from the comma separated string. Use something like this to pop a string from the list and put it as a row into the table:
PIPE ROW(ltrim(rtrim(substr(l_list, 1, l_idx - 1),' '),' '));
Usage:
SELECT * FROM MyTable
WHERE 'c2' IN TABLE(Util_Pkg.split_string(categories));
See more here: Oracle docs
Yes and No...
"Yes":
Normalize the data (strongly recommended) - i.e. split the categorie column so that you have each categorie in a separate... then you can just query it in a normal faschion...
"No":
As long as you keep this "pseudo-structure" there will be several issues (performance and others) and you will have to do something similar to:
SELECT * FROM MyTable WHERE categories LIKE 'c2,%' OR categories = 'c2' OR categories LIKE '%,c2,%' OR categories LIKE '%,c2'
IF you absolutely must you could define a function which is named FIND_IN_SET like the following:
CREATE OR REPLACE Function FIND_IN_SET
( vSET IN varchar2, vToFind IN VARCHAR2 )
RETURN number
IS
rRESULT number;
BEGIN
rRESULT := -1;
SELECT COUNT(*) INTO rRESULT FROM DUAL WHERE vSET LIKE ( vToFine || ',%' ) OR vSET = vToFind OR vSET LIKE ('%,' || vToFind || ',%') OR vSET LIKE ('%,' || vToFind);
RETURN rRESULT;
END;
You can then use that function like:
SELECT * FROM MyTable WHERE FIND_IN_SET (categories, 'c2' ) > 0;
For the sake of future searchers, don't forget the regular expression way:
with tbl as (
select 1 ID, 'c1' CATEGORIES from dual
union
select 2 ID, 'c2,c3' CATEGORIES from dual
union
select 3 ID, 'c3,c2' CATEGORIES from dual
union
select 4 ID, 'c3' CATEGORIES from dual
union
select 5 ID, 'c4,c8,c5,c100' CATEGORIES from dual
)
select *
from tbl
where regexp_like(CATEGORIES, '(^|\W)c3(\W|$)');
ID CATEGORIES
---------- -------------
2 c2,c3
3 c3,c2
4 c3
This matches on a word boundary, so even if the comma was followed by a space it would still work. If you want to be more strict and match only where a comma separates values, replace the '\W' with a comma. At any rate, read the regular expression as:
match a group of either the beginning of the line or a word boundary, followed by the target search value, followed by a group of either a word boundary or the end of the line.
As long as the comma-delimited list is 512 characters or less, you can also use a regular expression in this instance (Oracle's regular expression functions, e.g., REGEXP_LIKE(), are limited to 512 characters):
SELECT id, categories
FROM mytable
WHERE REGEXP_LIKE('c2', '^(' || REPLACE(categories, ',', '|') || ')$', 'i');
In the above I'm replacing the commas with the regular expression alternation operator |. If your list of delimited values is already |-delimited, so much the better.

Oracle substring select questions

Got stuck
select *
from table a
where ID like 'delr' || trim(substr(busns_asct_id,5)) || '%';
based on the above query, I get records like "delr112591-8218-1" but in that I need to eliminate ID like "delr60201-T,delr99999-A" and "delr1 -5"
How to eliminate this?
This how to deal with LIKE in Oracle:
An underscore _ in the pattern matches exactly one character
A percent sign % in the pattern can match zero or more characters
ESCAPE '\' to escape the _ or % with any character you want, here I used \
To match delr112591-8218-1 you can use that
like 'delr' || trim(substr(busns_asct_id,5)) || '-____-_';
any other string obtained by replacing _ by any other character will match, so "delr60201-T","delr99999-A" and "delr1 -5" will not match, if you want something more accurate, you have to use REGEX.
LIKE condition in Oracle
REGEX in Oracle
select *
from table a
where ID like 'delr' || trim(substr(busns_asct_id,5)) || '-_' or ID like 'delr_-_;

Resources