JPA/Criteria API - NotLike - oracle

I want to use Predicate notLike(Expression x, String pattern) to replace the following query:
select * from mytable
where mytable.myParameter not in ('ABC%','XYZ');
But when I execute my query using the following predicate:
Predicate notLike = builder.notLike(fromMyTable.get(MyTable_.myParameter), "ABC%|BCD");
is not working.
But if I create 2 predicates for the both strings: "ABC%" and "XYZ" is working.
Is my pattern written wrong or where is the problem? I tried to change the pattern in many ways but is still not working.
Thank you!

In SQL A not in (X,Y,Z) predicate is a shortcut for the following condition:
A <> X AND A <> Y AND A <> Z
this condition uses "not equal" operators, which compare operands for exact unequality.
It is not ossible to use IN or NOT IN operators for pattern-matching.
You must rewrite your query using LIKE operator which supports pattern matching:
select * from mytable
where mytable.myParameter not in ('XYZ')
and mytable.myParameter not LIKE 'ABC%';
or
select * from mytable
where mytable.myParameter <> 'XYZ'
and mytable.myParameter not LIKE 'ABC%';

Related

can I use `=` sign operator with sub-query instead of `IN`

I am just wondering if use = sign operator with sub-query instead of IN
Is it correct way ? and meet the oracle standard ?
Example
select column_name from my_table_1 where id = (select max(id) from my_table_2);
The Difference is related to the number of rows returned. If you have only one row returned from nested sql you may prefer both = or in operators. But if multiple rows returned from nested query, use in operator.
So, in your sql example you may prefer using any of the operators. Since, max functions returns only one row.
As you are fetching maximum value from subquery to compare with id, Both(= and IN )will work fine. But If you are trying to fetch more than one row then you have to use IN keyword.
If you have 1 result in sub query you are fine with using = sign, except when data type is wrong, for example , checking with same data type of dummy VARCHAR2(1)
select * from dual where 'X' = (select max(dual.dummy) from dual);
Is similar to using in (also same explain plain)
select * from dual where 'X' in (select max(dual.dummy) from dual);
But checking with different/wrong data type will result with exception ORA-01722 Invalid number
select * from dual where 1 =(select max(dual.dummy) from dual);

Missing Keyword when using Case in Where clause

I am using case in where clause but getting error: missing keyword
SQL:
SELECT *
FROM tmp t
WHERE
CASE :p_flag WHEN 'Y'
THEN t.call_destination NOT IN ('Premium', 'Satellite')
ELSE t.call_destination LIKE call_destination
END;
The predicate of a CASE expression has to be a single value, not another expression. If I read your WHERE clause correctly, you ought to be able to rephrase your query as follows:
SELECT *
FROM tmp t
WHERE
(:p_flag = 'Y' AND t.call_destination NOT IN ('Premium','Satellite')) OR
(:p_flag <> 'Y' AND t.call_destination LIKE call_destination);
-- ^^^ not sure about this
I have highlighted a LIKE comparison you are making which does not seem to make sense because it would always return true.

Oracle 12c Inline View Evaluation

A long time ago in a database far, far away a developer wrote a query in which he/she was reliant on the order in which predicates were written.
For example,
select x
from a, b
where NOT REGEXP_LIKE (a.column, '[^[:digit:]]')
and a.char_column = b.numeric_column;
(explain plan suggests a to_number conversion will be applied to a.char_column)
I think by chance more than design this "just works" (Oracle 11g). However, the order of the predicates isn't adhered to when running in Oracle 12c, so this query breaks with an invalid number exception. I'm aware that I could try to force 12c to evaluate the predicates in order by using the ORDERED_PREDICATES hint as follows
select /*+ ORDERED_PREDICATES +*/ x
from a, b
where NOT REGEXP_LIKE (a.column, '[^[:digit:]]')
and a.char_column = b.numeric_column
.. Or cast one of the values using to_char for the comparison. The downside is that to_char could operate on say a million rows. I think the following inline view is probably a better solution. Am I guaranteed that the inline view will be evaluated first?
select x
from b
inner join (
select only_rows_with_numeric_values as numeric_column
from a
where NOT REGEXP_LIKE (a.column, '[^[:digit:]]')
) c
on c.numeric_column = b.numeric_column;
About predicate order - look at https://jonathanlewis.wordpress.com/2015/06/02/predicate-order-2/
You should rewrite your last query to next using rownum according to doc(https://docs.oracle.com/database/121/SQLRF/queries008.htm#SQLRF52358)
select x
from b
inner join (
select only_rows_with_numeric_values as numeric_column,
rownum
from a
where NOT REGEXP_LIKE (a.column, '[^[:digit:]]')
) c
on c.numeric_column = b.numeric_column;
to suppress query unnesting or simply using hint /*+ no_unnest*/

Regular Expressions Oracle

I want to find regular expression [.-] in field filial_name.
select uc.filial_name from MYTABLE uc
where regexp_like(uc.filial_name , '[.-]');
select uc.filial_name from MYTABLE uc
where uc.filial_name like '%[.-]%';
The first variant is working. But the second is not.
How to fix second variant ?
Second expression isn't regex , it is normal search and should be used be like '%text%' .
Try this
SELECT uc.filial_name FROM MYTABLE uc
where uc.filial_name like '%.-%';

Is there a Hive equivalent of SQL “LIKE ANY ( SUBQUERY )”

While Hive doesn't supports multi-value LIKE queries which are supported in SQL : ex.
SELECT * FROM user_table WHERE first_name LIKE ANY ( 'root~%' , 'user~%' );
We can convert it into equivalent HIVE queries as :
SELECT * FROM user_table WHERE first_name LIKE 'root~%' OR first_name LIKE 'user~%'
Does anyone know an equivalent solution that Hive does support in case sub-query is used with LIKE ? Have a look at below example :
SELECT * FROM user_table WHERE first_name LIKE ANY ( SELECT expr FROM exprTable);
As It doesn't have values in expression, I can't use same approach for generating multiple LIKE expression separated with OR / AND operator. Initially I thought to write HIVE UDF for it ? Can you please help me supporting such expression and finding HIVE equivalent ?
You can use Hive's RLIKE relational operator as shown below,
SELECT * FROM user_table WHERE first_name RLIKE 'root~|user~|admin~';
Hope this helps!
This is a case involving theta joins in Hive. There is a wiki page for this and a jira request. Please go through the details here on this page: https://cwiki.apache.org/confluence/display/Hive/Theta+Join
Your case is similar to the Side-Table Similarity case given on the page.
You need to convert the expr values into a map and then use regular expression to find the like. Alternatively you can also use union all with all the like expressions in separate SQL - the query might become tedious so you can programatically generate it.
What about this using EXISTS
SELECT * FROM user_table WHERE EXISTS ( SELECT * FROM exprTable WHERE first_name LIKE expr );

Resources