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.
Related
I am using Oracle DB with Spring Boot Application. The query is working fine in DBeaver but not in actual application. I have copied the query from the console error message.
Query calling function:
public List<UserFullNameDesignationDto> getUserFullNameDesignation(String[] userNames) {
String queryParam = "";
for (String uName : userNames) {
queryParam += "'" + uName + "',";
}
queryParam = queryParam.substring(0, queryParam.length() - 1);
String sql =
"SELECT\n"
+ "\tu.USERNAME,\n"
+ "\tu.FULL_NAME,\n"
+ "\tcd.NAME \n"
+ "FROM\n"
+ "\tUSER_ENTITY u\n"
+ "LEFT JOIN CORE_DESIGNATIONS cd ON u.DESIGNATION_ID = cd.ID \n"
+ "WHERE\n"
+ "\tu.USERNAME IN ("
+ queryParam
+ ");\n";
var rowMapper = BeanPropertyRowMapper.newInstance(UserFullNameDesignationDto.class);
List<UserFullNameDesignationDto> list = jdbcTemplate.query(sql, rowMapper);
System.out.println(list);
return jdbcTemplate.query(sql, rowMapper);
}
Stack trace:
org.springframework.jdbc.BadSqlGrammarException: StatementCallback; bad SQL grammar [SELECT
u.USERNAME,
u.FULL_NAME,
cd.NAME
FROM
USER_ENTITY u
LEFT JOIN CORE_DESIGNATIONS cd ON u.DESIGNATION_ID = cd.ID
WHERE
u.USERNAME IN ('aro_user','afo_user1','afo_user1','afo_user1','afo_user1','afo_user1');
]; nested exception is java.sql.SQLSyntaxErrorException: ORA-00933: SQL command not properly ended
............
Caused by: java.sql.SQLSyntaxErrorException: ORA-00933: SQL command not properly ended
This line will be
'aro_user','afo_user1','afo_user1','afo_user1','afo_user1','afo_user1'
replaced by variable.
The root cause of the error is that you copied the semicolon in the JDBCTemplate statement (which works in SQL IDE but not in JDBC)
+ ");\n";
remove it
+ ")\n";
and it will work (or you get an other error;)
Anyway you should re-think your way of concatenation input in the SQL statement towards the usage of bind variables. There are lot of examples for binding IN list on this site.
As far as I can tell, you'll have to split values stored in that variable into rows. How? Like this:
SQL> with test(queryParam) as
2 (select q'['aro_user','afo_user1','afo_user1','afo_user1','afo_user1','afo_user1']' from dual)
3 select regexp_substr(queryParam, '[^,]+', 1, level) val
4 from test
5 connect by level <= regexp_count(queryParam, ',') + 1
6 /
VAL
----------------------------------------------------------------------
'aro_user'
'afo_user1'
'afo_user1'
'afo_user1'
'afo_user1'
'afo_user1'
6 rows selected.
SQL>
It means that this:
+ "\tu.USERNAME IN ("
+ queryParam
+ ");\n";
should be modified so that queryParam is replaced by
( SELECT REGEXP_SUBSTR (queryParam,
'[^,]+',
1,
LEVEL) val
FROM test
CONNECT BY LEVEL <= REGEXP_COUNT (queryParam, ',') + 1)
List<String> userIds = Arrays.asList("User1", "User2");
String inSql = String.join(",", Collections.nCopies(userIds.size(), "?"));
List<User> employees = jdbcTemplate.query(String.format("SELECT * FROM Users WHERE id IN (%s)", inSql), userIds.toArray());
Please see, https://www.baeldung.com/spring-jdbctemplate-in-list for
I have a native query in plsql like this;
create or replace package body DBPK_Monitoring is
PROCEDURE monitoring_Search(cur OUT SYS_REFCURSOR,) is
query VARCHAR(30000);
whereClause VARCHAR(10000);
BEGIN
whereClause := whereClause || ' and ( cnt.contract_status!=7)';
query := ' select itemTitle as "itemTitle", numberOfRow as "numberOfRow" ,
orderNumber as "orderNumber",createDate as "createDate",
priorityNumber as "priorityNumber"
from buy_buy_order bbo
inner join buy_buy_order_item bbi
on bbi.buy_order_id = bbo.id
left outer join core_User_Role shoUserRole
on shoUserRole.id = bbi.buy_Expert_Id
' || whereClause || ' order by ' || orderBy ||
') e WHERE e.rowNO> ' || lower_Bound || ' and e.rowNO<=' ||
upper_Bound;
OPEN cur FOR query
end monitoring_Search;
end DBPK_Monitoring;
I use of this query in repository with hql like this :
Session session = getSession();
Query query = session.getNamedQuery("monitoring_Search").setResultTransformer(Transformers.aliasToBean(MonitoringDto.class));
int firstResultIndex = searchOption.getPageNumber() * searchOption.getPageSize();
query.setInteger("lower_Bound", firstResultIndex);
query.setParameter("upper_Bound", firstResultIndex + searchOption.getPageSize());
query.setString("orderBy", searchOption.getOrder());
query.setParameter("buyOrderNumber", buyOrderNumber);
List<MonitoringDto> list = query.list();
int count = (list.size() > 0L) ? list.get(0).getNumberOfRow() : 0;
return new QueryResult<MonitoringDto>(searchOption.getPageNumber(), count, searchOption.getPageSize(), list);
When I run program, I get this error:
java.lang.illegalargumentexception no query defined for that name
[monitoring_Search]
How can I fix this?
you have to define monitoring_search as a Hibernate named query , you can see the detail about this in this link : https://www.baeldung.com/hibernate-named-query
have a nice day and kiss people around you ;)
#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 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 (?,?,?,?,?,?)...