Search from oracle database in Java using LIKE keyword - java

query="select * from books where BookName LIKE \"%" +txt1.getText()+"%\"";
this is for mysql server database code.
what will be change for oracle?

DO NOT build SQL queries using string concatenation - you should be using bind parameters.
Your query string should be:
query="select * from books where BookName LIKE ?";
and then you can do something like:
Class.forName( "oracle.jdbc.OracleDriver" ); // If you are using the Oracle driver.
Connection con = DriverManager.getConnection(
"jdbc:oracle:thin:#localhost:1521:XE",
"username",
"password"
);
final String query="select * from books where BookName LIKE ?";
PreparedStatement ps = conn.prepareStatement(query);
ps.setString( 1, "%" + txt1.getText() + "%" );
ResultSet rs = ps.executeQuery();
// Loop through the result set.
// Close statement/connections
(you will need to handle exceptions, etc.)
and:
You should not need to change the query to swap between MySQL and Oracle (just change the driver and connection string).
You do not need to escape any single or double quotation marks in the input string.
You are protected from SQL injection attacks.
Oracle can cache the query with the bind parameter and does not have to re-parse / re-compile it when the bind parameter changes.
If you are going to write the query as a string then string literals are surrounded by single quotes (not double quotes) in SQL:
query="select * from books where BookName LIKE '%your_string%'";
and you need to make sure that any single quotes in your string are properly escaped (but just use a bind parameter instead).

problem solved with this..
query="select * from books where BookName LIKE '%" +txt1.getText()+"%'";
thanks everyone :)

Related

Java PreparedStatement SQL syntax error [duplicate]

This question already has answers here:
Java PreparedStatement complaining about SQL syntax on execute()
(6 answers)
Closed 6 years ago.
This is a really weird error that only started appearing today. When I use a prepared statement with ? for parameters, I get an error, but when I use it without parameters, it works just fine.
Here is the error-causing code:
String table = "files";
Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
PreparedStatement prep = conn.prepareStatement("SELECT * FROM ?");
prep.setString(1, table);
ResultSet rs = prep.executeQuery();
while(rs.next()) {
System.out.println(rs.getString("file_name"));
}
This produces the following error:
Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''files'' at line 1
Also, changing it to the following works just fine:
String table = "files";
Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
PreparedStatement prep = conn.prepareStatement("SELECT * FROM " + table);
ResultSet rs = prep.executeQuery();
while(rs.next()) {
System.out.println(rs.getString("file_name"));
}
This doesn't seem to be making a whole lot of sense. Any ideas?
Tried it on another table and got more weired results.
This works and logs the admin in correctly:
String sql = "SELECT * FROM " + ADMIN_AUTH_TABLE + " WHERE " + column + " = '" + hashedPassword + "'";
PreparedStatement prepared = connection.prepareStatement(sql);
The following doesn't cause errors, but returns a message saying that the password entered is incorrect (it's correct - I double triple checked).
String sql = "SELECT * FROM " + ADMIN_AUTH_TABLE + " WHERE ? = ?";
PreparedStatement prepared = connection.prepareStatement(sql);
prepared.setString(1, column);
prepared.setString(2, hashedPassword);
Got it: use ? for values.
Also, the answer here helped.
Bind parameters cannot be used for identifiers in the SQL statement. Only values can supplied through bind placeholders.
This will work:
SELECT foo FROM bar WHERE id = ?
This will not work, because the table name is an identifier
SELECT foo FROM ? WHERE id = 2
You can't supply a column name, because column names are also identifiers.
A statement like this will run, but it may not do what you think it does.
SELECT ? AS foo FROM bar WHERE ? = 0
If we supply values of 'foo' for both placeholders, the query will actually be equivalent to a query containing two string literals:
SELECT 'foo' AS foo FROM bar WHERE 'foo' = 0
MySQL will run that statement, because it's a valid statement (if the table bar exists and we have privileges on it.) That query will return every row in bar (because the predicate in the WHERE clause evaluates to TRUE, independent of the contents of the table.. And we get returned the constant string foo.
It doesn't matter one whit that the string foo happens to match the name of column in our table.
This restriction has to do with how the SQL optimizer operates. We don't need to delve into all the details of the steps (briefly: parsing tokens, performing syntax check, performing semantics check, determining query plan, and then the actual execution of the query plan.)
So here's the short story: The values for bind parameters are supplied too late in that process. They are not supplied until that final step, the execution of the query plan.
The optimizer needs to know which tables and columns are being referenced at earlier stages... for the semantics check, and for developing a query plan. The tables and columns have to be identified to the optimizer. Bind placeholders are "unknowns" at the time the table names and column names are needed.
(That short story isn't entirely accurate; don't take all of that as gospel. But it does explain the reason that bind parameters can't be used for identifiers, like table names and column names.)
tl;dr
Given the particular statement you're running, the only value that can be passed in as a bind parameter would be the "hashedPassword" value. Everything else in that statement has to be in the SQL string.
For example, something like this would work:
String sqltext = "SELECT * FROM mytable WHERE mycolumn = ?";
PreparedStatement prepared = connection.prepareStatement(sqltext);
prepared.setString(1, hashedPassword);
To make other parts of the SQL statement "dynamic" (like the table name and column name) you'd have to handle that in the Java code (using string concatenation.) The contents of that string would need to end up like the contents of the sqltext string (in my example) when it's passed to the prepareStatement method.
The parameters of PreparedStatement should be applied only in parameters that can be used in conditional clauses. The table name is not the case here.
If you have a select where the table name can be applied in the conditional clause you can do it, otherwise you can not.

Prevent this statement from SQL injection

I am trying to write a very simply query using the PreparedStatement class. I read here:Fail to convert to internal representation JDBC that you cannot parameterize column names, only values. Since my query is very simple, the only 'value' I can parameterize is count (*).
This is the query:
SELECT COUNT (*) FROM EZ_DAY
If I try to parameterize it like this:
SELECT ? FROM EZ_DAY
I get an error:
Fail to convert to internal representation
when using the method getInt() on the ResultSet.
How can I use PreparedStatement and parameterize something in this query to prevent SQL injection? Also I know you can't parameterize column names, does that include table names? For example, can I do something like:
SELECT COUNT (*) FROM ?
?
That query cannot fall into SQL injection. The queries that fall in this category are those queries that you build by plain String concatenation. For example:
String query = "SELECT COUNT(*) FROM EZ_DAY WHERE colX = " + stringParameter;
Statement stmt = con.createStatement(query);
ResultSet rs = stmt.executeQuery();
In your case, there's no parameter to inject, so there's no way to have a SQL injection attack for your specific case.
If you need to prevent from SQL injection attacks, use PreparedStatement and do not concatenate the query. Instead, pass the parameters through the interface, which will escape any invalid character for you:
String query = "SELECT COUNT(*) FROM EZ_DAY WHERE colX = ?";
PreparedStatement pstmt = con.prepareStatement(query);
pstmt.setString(1, stringParameter);
ResultSet rs = pstmt.executeQuery();
In case you need to build a dynamic query, then you may fall back into concatenating strings, regardless if you use plain String concatenation or a StringBuilder:
//Common solution, still suffers from SQL injection
String query = "SELECT COUNT(*) FROM EZ_DAY WHERE 1 = 1 ";
if (stringParameter != null) {
query = query + = "AND colX = " + stringParameter;
}
Instead, it is better to use a COALESCE or IFNULL function to the parameter to avoid such situations:
//Better solution
String query = "SELECT COUNT(*) FROM EZ_DAY WHERE colx = COALESCE(?, colx)";
In the case above:
If the parameter has a different value than null, the query would be like this:
String query = "SELECT COUNT(*) FROM EZ_DAY WHERE colx = ?";
If the parameter has null value, then the query would be like this:
String query = "SELECT COUNT(*) FROM EZ_DAY WHERE colx = colx";
In the last example, you're still able to use PreparedStatement and avoid SQL injection attacks.
Related:
Difference between Statement and PreparedStatement
As explained in this post, SQL injection can lead to very serious issues like:
call a sleep function so that all your database connections will be busy, therefore making your application unavailable
extracting sensitive data from the DB
bypassing the user authentication
And it's not just SQL that can be affected. Even JPQL can be compromised if you are not using bind parameters.
Bottom line, you should never use string concatenation when building SQL statements. Use a dedicated API for that purpose:
JPA Criteria API
jOOQ

Trouble with SQL querys

I'm having trouble with an SQL query. The problem is that I'm querying an external database of enterprise names and some names are like "Martha's" (include apostrophes). And because I'm querying from an android app, the query string looks like:
String query = "Select * from Advertiser where AdvName= '" + name + "';";
So is there anyway I could ignore or change the apostrophes in the query?
Thanks in advance!
That's one of the reasons why you should always use prepared statements when executing parameterized queries:
String sql = "select * from Advertiser where AdvName = ?";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, name);
ResultSet rs = stmt.executeQuery();
The JDBC driver will escape the quotes for you, and this will also prevent SQL injection attacks.
Prepared statements also have performance advantages when you must execute the same query several times but with different parameters.
Read more about prepared statements in the JDBC tutorial.
Side note: you shouldn't have a ; at the end of your query.
In PLSQL you should use double '' in the input-field, meaning, Martha's => Martha''s:
String query = "Select * from Advertiser where AdvName= 'Martha''s';";
Important Remark:
For security purposes (to avoid sql injection) you should avoid creating queries the way you do, better use prepared-statement and set the parameters like this:
String query = "Select * from Advertiser where AdvName= ? ";
PreparedStatement st = conn.prepareStatement(query);
st.setString(1,name);

Java SQL "ERROR: Relation "Table_Name" does not exist"

I'm trying to connect netbeans to my postgresql database. The connection seems to have worked as I don't get any errors or exceptions when just connecting, methods such as getCatalog() also return the correct answers.
But when I try to run a simple SQL statement I get the error "ERROR: relation "TABLE_NAME" does not exist", where TABLE_NAME is any one of my tables which DO exist in the database. Here's my code:
Statement stmt = con.createStatement();
ResultSet rs;
String query = "SELECT * FROM clients";
rs = stmt.executeQuery(query);
I was thinking that netbeans might not be finding the tables because it's not looking in the default schema (public), is there a way of setting the schema in java?
EDIT: My connection code. The database name is Cinemax, when I leave out the statement code, I get no errors.
String url = "jdbc:postgresql://localhost:5432/Cinemax";
try{
try {
Class.forName("org.postgresql.Driver");
} catch (ClassNotFoundException cnfe) {
System.err.println("Couldn't find driver class:");
cnfe.printStackTrace();
}
Connection con = DriverManager.getConnection( url,"postgres","desertrose147");
I suspect you created the table using double quotes using e.g. "Clients" or some other combination of upper/lowercase characters and therefor the table name is case sensitive now.
What does the statement
SELECT table_schema, table_name
FROM information_schema.tables
WHERE lower(table_name) = 'clients'
return?
If the table name that is returned is not lowercase you have to use double quotes when referring to it, something like this:
String query = "SELECT * FROM \"Clients\"";
You could check these possibilities:
String query = "SELECT * FROM clients";
String query = "SELECT * FROM CLIENTS";
String query = "SELECT * FROM \"clients\"";
String query = "SELECT * FROM \"CLIENTS\"";
String query = "SELECT * FROM Clients";
Maybe one of those would work.
Besides CoolBeans' suggestion, you may also be connecting to the db as a different user who does not have permission on the relevant db or schema. Can you show the connection string?
Funny thing is i was experiencing the same thing as i had just started on netbeans and postgressql db, and the error was fixed after noting that the issue was that my tables in postgressql had capital letters in my naming convention which me and my jdbc query statement for INSERT was failing to find the table. But after renaming my tables in the db and fixing the column names as well am good to go. Hope it helps.

Cannot use a LIKE query in a JDBC PreparedStatement?

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:
"\'" + "?" + "\'"

Categories