I'm having issues dealing with the single quote while using it in a prepared statement in JAVA via Oracle JDBC.
Let's say we have a table Restaurant with a column restaurant_name with 1 value : Jack's Deli
I want to use a simple prepared statement query like this:
String result = "Jack\'\'s Deli"
String sqlStatement = "select * from Restaurant where restauraunt_name like ? escape '\\' ";
PreparedStatement pStmt = conn.prepareStatement(sqlStatement);
pstmt.setString(1, result);
The result shows 0 returned values, however when I directly search the query in the database (ORACLE) it works fine and retrieves the result. (Oracle uses two single quotes as an escape for the first)
I am thinking that the value is not being passed properly to the database. Or there is some other formatting issue.
The point of prepared statements is that you don't need any escaping.
.setString(1, "Jack's Deli") will get it done.
Related
I am developing java code where sql query is already, but it it leads to sql injection, I am using setString method to avoid sql injection. But the setstring is adding single quotes for parameter values, so my query is failing. How can I remove single quotes for setString methods.
I have tried to use replaceAll method, but it does not work for preapred statements.
String X="where IP ?";
String Y=" group by user";
String Z="order by descend";
query="select appname,user,IP from xyz "+X+" "+Y+Z; --> this is existing query.
I am changing query as below
query="select appname,user,IP from xyz ? ? ?";
Object=connectionObj.prepareStatement(query);
Object.setString(1,X);
Object.setString(2,Y);
Object.setString(3,Z);
but here setString method is adding single quoes for the values so my query is failing as syntax error.I tried replceAll("'"," ") method but it only works for strings not for prepared statements.I am stuck with syntax error.Please help me out to solve this issue in JAVA.
What you are trying to do is also SQL injection. Where are the values of X, Y, and Z coming from? Code your program to build up the SQL based on your business needs, adding the fragments of SQL using StringBuilder from within your program. If you have control over the fragments, it is not SQL injection. You should only be using parameters (?) for values compared with the data within your tables. You could also consider a tool like myBatis if you have a need to dynamically create SQL.
This is what I did, I hope it will benefit someone:
List<String> temp = new ArrayList<>();
String placeholder = "";
while(rst.next()){
temp.add(rst.getString("ISSN"));
placeholder += "?,";
}
placeholder = placeholder.replaceAll(",$", "");
ps=con.prepareStatement("select * from BOOKS where ISSN in "+ "("+placeholder+")");
for (int i=1; i<=temp.size(); i++){
ps.setString(i, temp.get(i-1));
}
rs =ps.executeQuery();
I am using JDBC PreparedStatement to query a Teradata database from a web service. My table has a PHONE_NUMBER column, stored as VARCHAR(10). I have always used PreparedStatement setString() to supply the parameter for this column, like below:
String myPhoneNumber = "5551234567";
String sql = "SELECT * FROM MYTABLE " +
"WHERE PHONE_NUMBER = ? ";
PreparedStatement p_stmt = db.getPreparedStatement(sql);
p_stmt.setString(1, myPhoneNumber);
ResultSet rs = db.executeQuery(p_stmt);
It returns correct results, but I noticed the CPU Teradata is using for this query is quite high. According to the EXPLAIN plan, it appears that Teradata is interpreting the myPhoneNumber parameter as a FLOAT, instead of VARCHAR, and so it has to do a data conversion to compare it to the VARCHAR column PHONE_NUMBER. Here is an excerpt of the EXPLAIN plan:
...
MYDATABASE.MYTABLE.PHONE_NUMBER (FLOAT, FORMAT
'-9.99999999999999E-999'))= 5.55123456700000E 009)
So, I came up with the below, which showed a great improvement in CPU usage (99.86% improvement):
String myPhoneNumber = "5551234567";
String sql = "SELECT * FROM MYTABLE " +
"WHERE PHONE_NUMBER = ''||?||'' ";
PreparedStatement p_stmt = db.getPreparedStatement(sql);
p_stmt.setString(1, myPhoneNumber);
ResultSet rs = db.executeQuery(p_stmt);
So my question is why is this necessary? Shouldn't setString tell JDBC to tell Teradata to expect a String/VARCHAR parameter?
Thanks!
Have you tried String myPhoneNumber = "'5551234567'";
Note -- The inclusion of the single quotes to wrap the value.
If you look at the example in the Teradata manuals here, you will see that a Query Band being set the same way as the OP's first example arrives as expected without single quotes wrapping it. It would seem to me this behavior in the first example of the OP is expected.
EDIT
The sample code provided by Teradata for their JDBC driver is using java.sql.PreparedStatment. With this their example program uses setString without any tricks to provide a string value for an INSERT statement. Sample Code If you are not able to replicate that behavior, I would open an incident with the Teradata GSC.
I'm attempting to create a JDBC query with the following statement
String query = "SELECT COLUMN1,DATECOLUMN2 FROM tableName +
"where datediff(d,DATECOLUMN2,getdate()) <= 1";
st = conn1.createStatement();
rs = st.executeQuery(query); //receiving error here
I am receiving the following error message
java.sql.SQLException: "d" is not a recognized table hints option. If it is intended as a parameter to a table-valued function or to the CHANGETABLE function, ensure that your database compatibility mode is set to 90.
I'm sure the query isn't recognizing the datediff function for some reason I am not sure why since i was previously using HQL in the same application and retrieving the values.
In an attempt to use an alternative function I used
{fn TIMESTAMPADD( SQL_TSI_DAY, 1, CURRENT_TIMESTAMP)}
but it also failed I later on found that this is only used for Derby Database's
Can someone assist me in using the proper sql function to compare a date with the current date using JDBC
String query = "SELECT COLUMN1,DATECOLUMN2 FROM tableName "+
"where datediff(day,DATECOLUMN2,getdate()) <= 1";
You have a comma before from. Based on the error messages you are running this against SQL server.
String query = "SELECT COLUMN1,DATECOLUMN2 FROM tableName "
+" where datediff(d,DATECOLUMN2,getdate()) <= 1";
The comma after the "d" should be a dot:
where datediff(d.DATECOLUMN2,getdate())
--------------- ^ dot here
The posted snippet doesn't have a closing double quote between tableName and +, but I figure that is just a typo. However, in your real code, where precisely is the double quote? Is it directly after tablename, like this
String query = "SELECT COLUMN1,DATECOLUMN2 FROM tableName" +
or after the space that follows tablename, like this
String query = "SELECT COLUMN1,DATECOLUMN2 FROM tableName "+
It is very likely the former, because in that case the resulting query would look exactly the way as to cause the error you are getting. Take a look at this:
SELECT COLUMN1,DATECOLUMN2 FROM tableNamewhere datediff(d,DATECOLUMN2,getdate()) <= 1
You can see that where merges with the table name and datediff becomes an alias. What follows is interpreted as table hints. (You can specify table hints without WITH in older versions of SQL Server/older compatibility levels.) Consequently, SQL Server stumbles over d, as that is indeed an incorrect table hint.
I'm using hibernate 3.6 and i'm having problems using criteria.list. I need search words with quotes or accents like "d'eau" or "d´eau". My code is something like this:
Criteria criteria;
criteria.add(Restrictions.ilike("nameParam", "d''eau", MatchMode.ANYWHERE));
I put two single quotes because i'm working with a sql server database. There are 2 single quotes because single quote escapes with another single quote.
The statement has 0 results, but if I execute the sql statement printed in the log in the sql server client, I get 120 results aprox.
Testing with HQL and the same sql statement. I get this:
String hqlQuery = "select distinct(t) from Table t where b.idCon in (select t2.idCon from Table t2 where lower(t2.outTerTb) like '%d''eau%')";
List qwer = getEntityManager().createQuery(hqlQuery).getResultList();
System.out.println("qwer.size() -> " + qwer.size());
String hqlQuery2 = "select distinct(t) from Table t where b.idCon in (select t2.idCon from Table t2 where lower(t2.outTerTb) like :param)";
List qwer2 = getEntityManager().createQuery(hqlQuery2).setParameter("param", "%d''eau%").getResultList();
System.out.println("qwer2.size() -> " + qwer2.size());
This code print:
qwer.size() -> 120
qwer2.size() -> 0
And I don't understand why this happens.
Sorry if my english is bad
You don't need to escape single quotes in your parameters. That's the whole point of using parameters (in Hibernate and, behind the scenes, in the JDBC prepared statements): the JDBC driver escapes everything that needs to be escaped for you.
You take what comes from the UI layer as is and stuff it into parameters, everything isproperly escaped by the driver, and you don't risk any SQL injection attack.
The query code and query:
ps = conn.prepareStatement("select instance_id, ? from eam_measurement where resource_id in (select RESOURCE_ID from eam_res_grp_res_map where resource_group_id = ?) and DSN like '?' order by 2");
ps.setString(1,"SUBSTR(DSN,27,16)");
ps.setInt(2,defaultWasGroup);
ps.setString(3,"%Module=jvmRuntimeModule:freeMemory%");
rs = ps.executeQuery();
while (rs.next()) { bla blah blah blah ...
Returns an empty ResultSet.
Through basic debugging I have found its the third bind that is the problem i.e.
DSN like '?'
I have tried all kinds of variations, the most sensible of which seemed to be using:
DSN like concat('%',?,'%')
but that does not work as I am missing the ' on either side of the concatenated string so I try:
DSN like ' concat('%',Module=P_STAG_JDBC01:poolSize,'%') ' order by 2
but I just cannot seem to find a way to get them in that works.
What am I missing?
First, the PreparedStatement placeholders (those ? things) are for column values only, not for table names, column names, SQL functions/clauses, etcetera. Better use String#format() instead. Second, you should not quote the placeholders like '?', it would only malform the final query. The PreparedStatement setters already do the quoting (and escaping) job for you.
Here's the fixed SQL:
private static final String SQL = "select instance_id, %s from eam_measurement"
+ " where resource_id in (select RESOURCE_ID from eam_res_grp_res_map where"
+ " resource_group_id = ?) and DSN like ? order by 2");
Here is how to use it:
String sql = String.format(SQL, "SUBSTR(DSN,27,16)"); // This replaces the %s.
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, defaultWasGroup);
preparedStatement.setString(2, "%Module=jvmRuntimeModule:freeMemory%");
See also:
Sun JDBC tutorial: Using Prepared Statements
Format string syntax
If you want to use LIKE in prepared statement and also want to use % characters in LIKE;
write prepared statement as normally " .... LIKE ? ...." and while assigning parameter value to question mark use
ps.setString(1, "%" + "your string value" + "%");
This will work :)
There are two problems with your statement. You have to understand how bind variables work. The query is not processed by substituing the characters ? with your parameters. Instead, the statement is compiled with placeholders and then, during execution, the actual values of the parameters are given to the DB.
In other words, you parse the following query:
SELECT instance_id, :p1
FROM eam_measurement
WHERE resource_id IN (SELECT RESOURCE_ID
FROM eam_res_grp_res_map
WHERE resource_group_id = :p2)
AND DSN LIKE '?'
ORDER BY 2
I'm pretty sure the last parameter will be ignored because it is in a delimited character string. Even if it is not ignored, it does not make sense to have ' characters around because Oracle won't bind a parameter in a string (I'm surprised it hasn't raised any error, do you catch exceptions ?).
Now if you replace your DNS LIKE '?' with DSN LIKE ? and bind "%Module=jvmRuntimeModule:freeMemory%" this will make sense and should return the correct rows.
You still have the problem with your first parameter, it won't do what you expect, i-e the query that will be executed will be equivalent to the following query:
SELECT instance_id, 'SUBSTR(DSN,27,16)'
FROM ...
which is not at all the same as
SELECT instance_id, SUBSTR(DSN,27,16)
FROM ...
I would suggest parsing (=prepareStatement) the following query if you expect the SUBSTR to be dynamic:
SELECT instance_id, SUBSTR(DSN,?,?)
FROM eam_measurement
WHERE resource_id IN (SELECT RESOURCE_ID
FROM eam_res_grp_res_map
WHERE resource_group_id = ?)
AND DSN LIKE ?
ORDER BY 2
Omit the ' around the ?. Without the ', ? is a placeholder for a parameter. With it, it's an SQL string (i.e. the same as "?" in Java).
Then you must concatenate the string on the Java side; you can't pass SQL functions as parameters to queries; only basic values (like string, integer, etc) because the JDBC driver will convert the parameter to the SQL type the database expects and it cannot execute SQL functions in this step.
You can try:
String beforeAndAfter = "%" + yourVariable + "%";
PreparedStatement ps = con.prepareStatement(
"select columname from tablename where LOWER(columnname) LIKE LOWER('"+var+"%')");
Here var is the variable in which value that is to be searched is stored...
This should work:
"\'" + "?" + "\'"