I have filters in a datatable and when user enters some value it should return a list of results matching that filter. I want it to be case-insensitive.
I create the query string for a prepared statement via Java string concatenation, as in the below:
public static List<Logger> getAll(int from, int to, Map<String, Object> filters, String sortField,
SortOrder sortOrder) {
Connection con = null;
PreparedStatement ps = null;
List<Logger> lista = new ArrayList<>();
String upit = "Select * from (select m.*,rownum r from (";
String upitZaFilterISort = "select m.* from eps_stage.MDM_OSB_LOG m";
try {
con = DataConnect.getConnection();
int upper = from + to;
if (filters.size() > 0) {
upitZaFilterISort = upitZaFilterISort.concat(" where 1=1");
Set<String> keys = filters.keySet();
// To get all key: value
for (String key : keys) {
if (key.equalsIgnoreCase("status") || key.equalsIgnoreCase("mbr")
|| key.equalsIgnoreCase("pib") || key.equalsIgnoreCase("jmbg")
|| key.equalsIgnoreCase("poruka_tip") || key.equalsIgnoreCase("aplikacija")
|| key.equalsIgnoreCase("operacija")) {
upitZaFilterISort = upitZaFilterISort.concat(
" AND UPPER(" + key.toString() + ") LIKE '" + filters.get(key).toString().toUpperCase() + "%'");
}
}
}
}
String sort = "";
ps = con.prepareStatement(upit + upitZaFilterISort + ") m ) where r>=? and r<=?");
ps.setInt(1, from);
ps.setInt(2, upper);
System.out.println(upit+ upitZaFilterISort + sort+") m " + ") where r>=? and r<=?");
ResultSet resultSet = ps.executeQuery();
In this line is a problem:
upitZaFilterISort = upitZaFilterISort.concat(
" AND UPPER(" + key.toString() + ") LIKE '" + filters.get(key).toString().toUpperCase() + "%'");
When I use case-sensitive comparison it works:
upitZaFilterISort = upitZaFilterISort.concat(
" AND " + key.toString() + " LIKE '" + filters.get(key).toString() + "%'");
After concatenation query:
Select * from (select m.*,rownum r from (select m.* from eps_stage.MDM_OSB_LOG m where 1=1 AND UPPER(poruka_tip) LIKE 'V%') m ) where r>=1 and r<=20
It returns the expected result when I run it in Oracle SQL Developer, but in my app it returns an empty result set.
Does Java put quotes somewhere I don't expect? I will provide more info if needed.
Try this:
Check if the user has all the required privileges to make the statements
It may happen that the port has only one open connection. Therefore you can only use java or oracle sql developer. Try disconnecting from sql developer and running your java program. If it doesn't work tell me.
I hope it has been helpful
Re: https://docs.oracle.com/cd/B28359_01/appdev.111/b28843/tdddg_globalization.htm#CCHIJBCG, section "Changing NLS Parameter Values for All Sessions"
Please check your session settings for NLC_COMP, which may be set to LINGUISTIC. The link below can get you there in SQL Developer. If set to LINGUISTIC then your SQL Developer sessions are performing case insensitive searches, possibly explaining differences between the sessions.
Also, concur with Filippo's recomended practices.
Related
I have a mysql database here I have columns for oldNominalValue and newNominalValue. I have 12 rounds in which at the each end of the round I update my new and nominal values. At the end of each round I need to set my newnominalvalue to oldnominalvalue how can I do this. Can anyone please tell me how to do this. Thanks for your time.
String CMF= rs.getString("comapanyName");
String ONV = rs.getString("oldNominalValue");
String NNV = rs.getString("newNominalValue");
// String NS = rs.getString("numberOfShares");
// System.out.print(CMF);
nominalvalue = Integer.parseInt(ONV);
//int nv = 1;
T = randNum / 100;
RT = T * nominalvalue;
newnominalvalue = nominalvalue - RT;
st = con.createStatement();
String query08= "update where " + FS + " (comapanyName,newnominalValue,oldNominalValue,PLock) VALUE ('" + gameName + "','Financial','" + CMF + "',', " + newnominalvalue + "," + nominalvalue + "', 0 )";
st.executeUpdate(query08);
Are you familiar with SQL syntax? There are some issues with your update query. Also, try using a prepared statement instead of a regular statement when using parameters and use proper resource management (ensure the statement gets closed again). See the sample below:
String statement = "UPDATE <your-table> SET newnominalValue = ?, oldNominalValue = ? WHERE <your-id-column> = ?";
try(PreparedStatement updateStmt = con.prepareStatement(statement)) {
updateStmt.setString(1, NNV);
updateStmt.setString(2, ONV);
updateStmt.setString(3, FS); // not sure what FS is in your code, or what type it is
updateStmt.executeUpdate();
}
Also, please use sensible and camelCased names in Java, it will help you and others in the long run to maintain the code. Variable names like 'T', 'RT' and 'FS' are most likely to confuse people and makes things a lot harder.
I am trying to change a normal query to Parameterized query using jdbcTemplate.queryForObject for avoiding SQL Injection. But the query returns EmptyResultDataAccessException - Incorrect result size: expected 1, actual 0 where the normal query works fine. Below is the normal query where i get the correct result.
StringBuilder builder = new StringBuilder();
String AcctNameBuilder = adhpDetailUtil.getAccName();
builder.append("select * " +
"from gfc.LSI_ELGBLTY " +
"where INSURANCE_ID = '" + request.getInsuranceId() + "' and " +
"SYS_CD = '" + request.getSystemId() + "' and " +
"ACCT_TYPE in (" + AcctNameBuilder.toString() + ")");
Here is the parameterized query that i have created from the above query.
StringBuilder builder = new StringBuilder();
String AcctNameBuilder = adhpDetailUtil.getAccName();
final String QUERY = "select * " + "from gfc.LSI_ELGBLTY " + "where INSURANCE_ID = ? and " + "SYS_CD = ? and " + "ACCT_TYPE in (?)";
Object[] params = new Object[] {
request.getInsuranceId(),request.getSystemId(),AcctNameBuilder};
String ids = jdbcTemplate.queryForObject(QUERY, params, String.class);
builder.append(ids)
In the first case, builder.append contains the exact query while in the second case jdbcTemplate.queryForObject is returning EmptyResultDataAccessException. What am I doing wrong here.
I don't believe you can just append ids for an "IN" clause like that.
The parameter for the "IN" clause is technically an Array. I ran into this a number of years ago and I don't think that this has ever been truly addressed.
If you think about it this is a fairly difficult problem as the query planner for preparing the statement cannot effectively bound the number of parameters.
I am new to using SQL2O with MySQL, but I am having a weird problem, where different queries return same results. Is SQL2O returning me cached results?
My code looks like this:
String sql = "SELECT * " +
"FROM report_A" +
"ORDER BY :order :sequence "+
"LIMIT :from, :limit";
int limit = 5;
int startIndex = (page-1)*limit;
String sequence = "DESC";
try(Connection con = sql2o.open()) {
if(order.contains("-")){
order = order.replace("-", "");
sequence= " ASC";
}
Query query= con.createQuery(sql)
.addParameter("from", startIndex)
.addParameter("limit", limit)
.addParameter("order", order)
.addParameter("sequence", sequence);
List<ReportA> result = query.executeAndFetch(ReportA.class);
con.close();
The 4 parameters always change, but the output remains the same. I have verified the queries in mysql workbench, the data is different, but SQL2O returns me the same set of data. Am I missing something?
Your query is invalid. It wont compile and throw an Sql2oException on execution.
The problem is, basically, that you can use parameters only for values, not for table names, column names or other keywords like "ASC". Changing those would change the structure of the query.
It's possible to construct queries with variable structure by good old string concatenation, i.e.
String sql = "SELECT * " +
"FROM report_A" +
"ORDER BY " + order " " + SEQUENCE +
"LIMIT :from, :limit";
and then
query(sql)
.addParameter("from", from)
.addParameter("limit", limit)
.executeAndFetch(...)
I have a table in H2 DB
Order
--------
id (key)
MarketId1
MarketId2
MarketId3
ListName1
ListName2
ListName3
From XML I'm getting list of ListOrder
public final class ListOrder
{
public long listId;
public String Name;
}
So I have 3 prepared statements
"UPDATE Order set " + ListName1 + " = ? WHERE " + MarketId1 + " = ?"
"UPDATE Order set " + ListName2 + " = ? WHERE " + MarketId2 + " = ?"
"UPDATE Order set " + ListName3 + " = ? WHERE " + MarketId3 + " = ?"
The in a method I prepare a list of PreparedStament to execute
final PreparedStatement statement1 = connection.prepareStatement(QUERY1);
final PreparedStatement statement2 = connection.prepareStatement(QUERY2);
final PreparedStatement statement3 = connection.prepareStatement(QUERY3);
for (ListOrder listOrder: listOrders)
{
statement1.setString(1, listOrder.Name);
statement1.setLong(2, listOrder.listId);
statement1.addBatch();
statement2.setString(1, listOrder.Name);
statement2.setLong(2, listName.listId);
statement2.addBatch();
statement3.setString(1, listName.Name);
statement3.setLong(2, listOrder.listId);
statement3.addBatch();
}
return new ArrayList<PreparedStatement>(){{add(statement1); add(statement2); add(statement3);}};
I'm a SQL noob. Is there any better way of doing it? I assume that MarketId 1 2 3 could be the same. ListNames could be null (there will be at least one)
UPDATE:
In code I would write something like this (prob change to HashMap)
for (ListOrder listOrder: listOrders)
{
for(Order order : orders)
{
if(order.marketID1 == listOrder.listID)
order.listName1 = listOrder.Name; //break if no dups
if(order.marketID2 == listOrder.listID)
order.listName2 = listOrder.Name;
if(order.marketID3 == listOrder.listID)
order.listName3 = listOrder.Name;
}
}
You can use update comma separated
UPDATE <TABLE>
SET COL1 = <VAL1>,
COL2= <VAL2>
WHERE <CONDITION>
Is it this what you expect as one update query?
Unless you are trying to update the same record, then there is no way to do this easily or efficiently in a single query. Otherwise, assuming this is the desired result, you could use an OR (or an AND if that is desired) statement such as:
UPDATE Order
SET ListName1=?, ListName2=?, ListName3=?
WHERE MarketId1=? OR MarketId2=? OR MarketId3=?
You might also consider updating your table to use a one:many relationship which might make your queries easier. For example:
Order
--------
id (key)
name
etc
Market_List
--------
id (key)
order_id (fk)
market
listname
I try to create a PreparedStatement:
stmt = conn.prepareStatement("SELECT POLBRP, POLTYP, POLNOP, INCPTP, TRMTHP, " +
"CLTKYP , CANDTP, POLSTP, EXPRYP, OINCPP, CANRNP, PAYMDP,
KCNFLP, KCRTSP, KACADP, KSCHMP, EXPRYP FROM "
+ POLHDR + " WHERE POLNOP = " + idNumber +
" AND POLBRP = " + branch + " AND POLTYP = " + product +
" AND OINCPP <= "+date );
And this throws an SQLException: [SQL0206] Column AD not in specified tables.
I have no idea where it's getting column AD from as I never specified it in the select clause (unless I'm being completely blind and stupid)
Can anyone help?
If your variables are strings, e.g. branch
" AND POLBRP = " + branch + " ...
then you forgot to quote the values
" AND POLBRP = '" + branch + "' ...
but the real solution is using placeholders
... AND POLBRP = ? ...
which would prevent such problems once and for all, this is what PreparedStatement is designed for
Try to change your query into this:
SELECT
POLBRP,
POLTYP,
POLNOP,
INCPTP,
TRMTHP,
CLTKYP,
CANDTP,
POLSTP,
EXPRYP,
OINCPP,
CANRNP,
PAYMDP,
KCNFLP,
KCRTSP,
KACADP,
KSCHMP,
EXPRYP
FROM TableName WHERE POLNOP = ? AND POLBRP = ? AND POLTYP = ? AND OINCPP <= ?";
Then use:
stmt.setString(1, "ValueOfPOLNOP");
...
When your query is being executed ? will be replaced with the value you passed into PreparedStatement#setString(int, String) method
Preventing SQL Injection in Java shows the proper use of PreparedStatement:
Prepared Statements Variables passed as arguments to prepared
statements will automatically be escaped by the JDBC driver.
Example: ps.1
String selectStatement = "SELECT * FROM User WHERE userId = ? ";
PreparedStatement prepStmt = con.prepareStatement(selectStatement);
prepStmt.setString(1, userId);
ResultSet rs = prepStmt.executeQuery();
From the same source, following in the same section:
Although Prepared Statements helps in defending against SQL Injection,
there are possibilities of SQL Injection attacks through inappropriate
usage of Prepared Statements. The example below explains such a
scenario where the input variables are passed directly into the
Prepared Statement and thereby paving way for SQL Injection attacks.
Example: ps.2
String strUserName = request.getParameter("Txt_UserName");
PreparedStatement prepStmt = con.prepareStatement("SELECT * FROM user WHERE userId = '+strUserName+'");