I have a query that will need to run 28 000 times in a row, so I thought using a preparedStatement probably is a clever idea.
Here is my query :
String requestWithFirstName = "SELECT SE.ELEMENT_ID, SE.LASTNAME||' '||SE.FIRSTNAME AS ELEMENT, (SCORE(1)+SCORE(2))/2 AS SCORE "
+ "FROM BL_SUSPICIOUS_ELEMENT SE "
+ "WHERE CONTAINS(SE.LASTNAME, 'fuzzy({' || ? || '},' || ? || ',' || ? || ', weight)' , 1)>0 "
+ "AND CONTAINS(SE.FIRSTNAME, 'fuzzy({' || ? || '},' || ? || ',' || ? || ', weight)' , 2)>0 "
+ (type > 0 ? "AND SE.ELEMENT_TYPE_ID = ?" : "")
+ " ORDER BY SCORE DESC";
Everthings worked fine until we realized that the fuzzy methods doesn't perform well for splitted words like 'pikachu is my hero' and it is advised to created, in this case, 4 fuzzy search for 'pikachu' 'is' 'my' 'hero'. Not sure if this is true, but as I will run the query 28 000 times it's a good opportunity to see it in action.
So I tried to modify the query in this manner :
"SELECT A.ELEMENT_ID, A.LASTNAME||' '||A.FIRSTNAME AS AKA, SCORE(1) AS SCORE "
+ "FROM BL_AKA A, BL_SUSPICIOUS_ELEMENT SE "
+ "WHERE CONTAINS(A.LASTNAME, ?, 1)>0 "
+ "AND SE.ELEMENT_ID = A.ELEMENT_ID "
+ (type > 0 ? "AND SE.ELEMENT_TYPE_ID = ?": "")
+ " ORDER BY SCORE DESC";
In this case, ? will be set to :
'fuzzy({Burnham},70,4,weight),fuzzy({Investors},70,4,weight),fuzzy({Trust},70,4,weight)'
The query seems fine, running on sql dev. However, with Java, I get the following error :
ORA-20000: Oracle Text error:
DRG-50900: text query parser error on line 1, column 30
DRG-50920: part of phrase not itself a phrase or equivalence
DRG-50900: text query parser error on line 1, column 30
DRG-50920: part of phrase not itself a phrase or equivalence
Any advice ?
I wonder if this is the same situation as the in statement (impossible to create a select * from pokemon where monster in (?))
Thanks !
When you use a prepared statement in java, it will set the parameter according to the method you use. So
String s = "'fuzzy({Burnham},70,4,weight),fuzzy({Investors},70,4,weight),fuzzy({Trust},70,4,weight)'";
statement.setString(s);
will be escaped again and results in:
'''fuzzy({Burnham},70,4,weight),fuzzy({Investors},70,4,weight),fuzzy({Trust},70,4,weight)'''
Try to set the parameter without the quotes.
You can create an IN (?) statement. But you will have to add a questionmark for every parameter: WHERE monster IN (?,?,?,?,?,?)...
Related
I am trying to write a query that performs a search according to several criteria.
My current JPA request:
#Query("SELECT c FROM Client c " +
"INNER JOIN c.entite e " +
"WHERE e.numeroLicence in (:numerosLicence) " +
"AND (UPPER(c.nom) LIKE CONCAT('%',UPPER(:nom),'%') " +
"AND (c.prenom IS NOT NULL AND UPPER(c.prenom) LIKE CONCAT('%',UPPER(:prenom),'%')) " +
"AND (c.dateCreation IS NOT NULL AND c.dateCreation > :dateCreation) " +
"AND (c.dateCreation IS NOT NULL AND c.dateModification > :dateModification) " +
"AND (c.dateCreation IS NOT NULL AND c.dateSuppression > :dateSuppression)) ")
Page<Client> recherche(#Param("numerosLicence") ArrayList numerosLicence,
#Param("nom") String nom,
#Param("prenom") String prenom,
#Param("dateCreation") ZonedDateTime dateCreation,
#Param("dateModification") ZonedDateTime dateModification,
#Param("dateSuppression") ZonedDateTime dateSuppression,
Pageable pageable);
The problem is that it automatically excludes rows where a column contains NULL.
I'll need the selection to be done on columns with data only, it will not try to execute the clause if the field value is NULL
For example, if I have a row whose firstname column is NULL, then this line is automatically excluded from the result whereas I would like it not to test this column if it is NULL
Do you have an idea?
I'm looking for a solution to avoid creating as many queries as possible combination
Sounds like you should use OR instead of AND:
c.dateCreation IS NULL
OR c.dateCreation > :dateCreation
I have an issue when executing the following SQL statement using JAVA on a ORACLE database, it works with DBeaver/SQLdeveloper but during the java process I get the following error. Any ideas ?
SQL Statement :
SELECT MIN(SUBSTR(t1.MONTH,1,4)) || 'A' || 'B' || 'CDE FGR' || ' ' || 'AT'
FROM table1 t1, table2 t2
WHERE t1.toto=t2.toto
AND t1.tata=t2.tata
AND t1.titi=t2.titi
AND t2.tutu = 'IMPACT_EUROPE_FLAG'
SQL error during java process :
org.springframework.jdbc.BadSqlGrammarException: Attempt to process next row failed; bad SQL grammar
nested exception is java.sql.SQLException: Invalid column name
Tables :
TABLE1 TABLE2
--------------
MONTH TOTO
TOTO TATA
TATA TITI
TITI TUTU
TUTU
My java process, only the reader and stepbuilder :
private Step insertBaseToFile() {
return stepBuilderFactory.get("insertBaseToFile").<GenericRecord, GenericRecord>chunk(100).reader(baseReader())
.writer(fileWriter()).build();
}
private JdbcCursorItemReader<GenericRecord> baseReader() {
JdbcCursorItemReader<GenericRecord> databaseReader = new JdbcCursorItemReader<>();
String sql = null;
sql = " SELECT MIN(SUBSTR(t1.MONTH,1,4)) || 'A' || 'B' || 'CDE FGR' || ' ' || 'AT' " +
"FROM table1 t1, table2 t2 " +
"WHERE t1.toto=t2.toto " +
"AND t1.tata=t2.tata " +
"AND t1.titi=t2.titi " +
"AND t2.tutu = 'IMPACT_EUROPE_FLAG'"
databaseReader.setDataSource(dataSource); //dataSource object from my class using JSON conf to get logs in to DB
databaseReader.setSql(sql);
return databaseReader;
}
My guess is that this is happening because the name of the column in your result is going to be:MIN(SUBSTR(T1.MONTH,1,4))||'A'||'B'||'CDEFGR'||''||'AT'
Try:
SELECT MIN( ... ) AS mycolumn
My bad.
Everything works well it was an error from me using wrong variables names.
#Query("SELECT c FROM message c"
+" WHERE (CASE WHEN a='' THEN 1=1 ELSE a= :a"
+ " WHEN b='' THEN 1=1 ELSE b= :b"
+ " WHEN c='' THEN 1=1 ELSE c= :c"
+ " WHEN d='' THEN 1=1 ELSE d= :d)")
I am trying to write an HQL query that has optional inputs of values a, b, c, and d.
My goal is to have the query recognize if an input =' 'and then just move along with 1=1 essentially doing nothing.
I keep getting error
antlr.NoViableAltException: unexpected token: =
First the error token was "CASE" and now it is "=".
Is the "1=1 approach" viable?
Can I use CASE statements like this in HQL?
Thank you
UPDATED ATTEMPT:
#Query("SELECT c "
+ "FROM message c"
+ " WHERE"
+ " CASE (WHEN a != '' THEN a = :a"
+ " WHEN b != '' THEN b = :b"
+ " WHEN c != '' THEN c = :c"
+ " WHEN d != '' THEN d = :d)"
antlr.NoViableAltException: unexpected token: WHEN
antlr.NoViableAltException: unexpected token: a
antlr.NoViableAltException: unexpected token: THEN
Are you sure that You want to use JPQL to do this operation?
I would suggest you to use Query By Example OR QueryDSL
If you want to continue using JPQL, then Read ahead :P
You can use sPEL inside #Query if you want to use conditional operator. Here is a sample query based on your requirement.
#Query("SELECT C FROM Message C " +
"WHERE 1=1 " +
"AND ((1=:#{ #param1 == null ? 1 : 0 }) OR (C.param1 = :#{#param1})) " +
"AND ((1=:#{ #param2 == null ? 1 : 0 }) OR (C.param2 = :#{#param2})) " +
"AND ((1=:#{ #param3 == null ? 1 : 0 }) OR (C.param3 = :#{#param3})) " +
"AND ((1=:#{ #param4 == null ? 1 : 0 }) OR (C.param4 = :#{#param4})) "
)
List<Message> find(#Param("param1") Long param1, #Param("param2") Long param2,#Param("param3") Long param3, #Param("param4") Long param4);
A Little Explanation
First Condition 1=1: Hehe, obsessed with conditions on next line to WHERE clause, you can remove it.
((1=:#{ #param1 == null ? 1 : 0 }) OR (C.param1 = :#{#param1})): Crazzy !!
First part will decide whether to check second part or not. Suppose param1 is null then (1=:#{ #param1 == null ? 1 : 0 }) will return 1=1 and (C.param1 = :#{#param1}) will be skipped.
Same will apply to further conditions.
Feel free to comment, if you have any doubts.
BTW, you should use fields with respect to the object inside JPQL. For example C.param1 instead of just param1.
I would like to rewrite an oracle stored procedure to java code, to select data with concatenated values in a query string to compare the following way:
Query qString =
"SELECT Obj " +
"FROM MyTable Obj2 WHERE ( Obj2.value1 || Obj2.value2 ) in " +
"(SELECT Obj2.value1 || MAX(Obj2.value2) FROM MyTable Obj2 WHERE Obj2.value2 >= :param GROUP BY Obj2.value1) " +
"ORDER BY Obj.value2, Obj.value1";
query = entityManager.createQuery(qString);
query.setParameter("param ", param );
When I run the query as a webservice on weblogic server I got error with the '|' character.
What can I use instead of the || operator to get the same result?
The Java Persistence Query Language provides the CONCAT() function, so you should be able to write Obj2.value1 || Obj2.value2 as CONCAT(Obj2.value1, Obj2.value2)
i am developing an chatbot app using sqlite, chatbot is a program which simulate human vs human Chatting!
in my app, user type something as input and i use it as variable in my JAVA and SQLite query,
for example consider this table:
id - user - chatbot
1 - how - is it important to know how
2 - how are you - i am fine
i use this code to get proper answer from DB:
(which is from this topic: How use “LIKE” and “%” to check similarity to variable in android(Java code)
cursor = db.rawQuery("SELECT chatbot FROM sentence"+
" WHERE ? LIKE '%' || " + USER + " || '%'"
,new String[] { newMessage });
this code work fine in most cases but in cases like this,it doesn't work: when user type in input how are you it select "i am fine" which is correct asnwer but unfortunately select "is it important to know how" too,
I used this code to only choose records with maximum length of user column:
cursor = db .rawQuery( "SELECT shompet FROM sentence" +
"WHERE LENGTH(user) = SELECT MAX(LENGTH(user)) from sentence "
+ " WHERE ? LIKE '%' || " + USER + " || '%'", new String[] {
newMessage });
but when i run it on simulator, it close and show this " app has stopped",
i think it has syntax error,
please help me to correct this syntax or give me another way to handle this problem, waiting for your advice!
You need to make use of an inner query like this.
SELECT chatbot, user
FROM sentence
WHERE LENGTH(user) = (
SELECT MAX(LENGTH(user))
FROM sentence
WHERE 'not exactly' LIKE '%' || user || '%'
) AND 'not exactly' LIKE '%' || user || '%'
SQL Fiddle Output:
+------------+-------------+
| CHATBOT | USER |
+------------+-------------+
| why not | not exactly |
+------------+-------------+
So, you need to create your cursor as
cursor = db.rawQuery("SELECT chatbot FROM sentence " +
"WHERE LENGTH(user) = ( " +
" SELECT MAX(LENGTH(user)) FROM sentence " +
" WHERE ? LIKE '%' || " + USER + " || '%' " +
") AND ? LIKE '%' || " + USER + " || '%' ",
new String[] { newMessage, newMessage });
if your application gets more big then a simple SQL may get confused due to
missing userinput
multiple matches
so i would suggest this
table: indices(id,values-unique)
table: quest(qid,indices)
table: ans(qid,aid,text)
indices
-------------
id values
1 how
2 are
3 you
quest
-------------
qid ids
1 1,2,3
2 1
ans
-------------
aid qid text
1 1 it is...
2 2 i am...
input: user text
break up into parts
get indices(id from indices table)
lookup quest table
lookup ans table