Java SQL quotes in query strings - java

I have the following code to executing a sql query:
query = String.format("select * from users where user_name = '%s';", results.getString(1));
results2 = mStmt.executeQuery(query);
One user_name in the dataset has value "O'brien". This ruins my query due to the single parenthesis in "O'brien. The query would become:
select * from users where user_name = 'O'brien'
What is the strategy to overcome this and not modify the data?
EDIT: The prepared statement does fix the single quote problem however that was only part of the problem. One of the string values I have contains the word "UNDER". which is a SQL keyword. For example I have a preparedStatement called insertAll with the query:
insert into names (id, val1, val2, val3, val4, tTime, val5) values (?, ?, ?, ?, ?, ?, ?)
Thanks for all the help!

Set your parameters with prepareStatement. Your code is a SQL injection exploitable code from the book.
http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html

Why not use PreparedStatement instead, avoid the tedious and error-prone issue of escaping quotes in sql queries altogether?
The could would look something like this (sorry, I didn't actually run this, but you should get the idea):
query = "select * from users where user_name = ?";
PreparedStatement p = new PreparedStatement(con, query);
p.setString(1, results.getString(1));
results2 = p.executeQuery();

Related

Insert with Select give sql-error (SQLCODE=-803, SQLSTATE=23505)(db2 z/os)

I try to insert values from my java application and values from table1 into table2. I get the following error(db2 z/os):
Exception in thread "main" com.ibm.db2.jcc.am.SqlIntegrityConstraintViolationException: DB2 SQL Error: SQLCODE=-803, SQLSTATE=23505, SQLERRMC=1;DB2T.TSOZ360_WV_AUSGANG, DRIVER=3.66.46
PreparedStatement _prep = con.prepareStatement("INSERT INTO DB2T.TABLE2 (column1, column2, column3 , column4, column5, column6) SELECT ?, ?, ?, ?, column5, column6 FROM DB2T.TABLE1 WHERE column1 = ? column2 = ? AND column3 = ?");
_prep.setString(1,"HELLO");
_prep.setString(2,"H");
_prep.setString(3,"1234567890");
_prep.setString(4,"Hsdfdsffdssdfsdfd");
_prep.setLong(5,9876543210l);
_prep.setInt(6,1);
_prep.setInt(7,12345678);
Table1:
column1, column2, column3 , column4, column5, column6
Table2
column1, column2, column3 , column4, column5, column6
So I want to insert values I generated in the java application into TABLE2 and two values from TABLE1. Without import this two values into the application. What I'm doing wrong?
The sql exception you got suggests that you're trying to insert 2 identical values into a column that accepts unique values (did you use this insert with the same parameter values more than once?).
However, your design is still bad so I would suggest that you split your query/statement into a select and an insert (2 queries/statements instead of just 1). This would make the code more readable as well as easier to debug.
Second, you shouldn't use column names as parameters (?) in a PreparedStatement (a PreparedStatement is meant to be reusable, however, if column names are parameterized, the database can't reuse the statement).
This means that it's wrong to do something like
String sql = "SELECT ?, ?, ?, ?, column5, column6 FROM DB2T.TABLE1 WHERE column1 = ? column2 = ?
_prep.setString(1, colName1);
_prep.setString(2, colName2);
....
You will have to specify the column names in your query (select a,b,c from T where x=?). If they need to be obtained dynamically you can use string concatenation (this is potentially prone to sql injection if you don't sanitize user input etc )
String dynamicColNames = getColumnNames();//just some method to get the names as one string
String sql = "SELECT "+dynamicColNames + " FROM ....";//
//dynamicColNames may contain col1, col2, col3 etc

Using select inside insert query with preparedStatement

I want to write an insert query using preparedStatement. Inside it I want to put a selection query. I did the following but I get: You have an error in your SQL syntax
protected final String createStudentQuery = " INSERT INTO student (student_id, ed_level) VALUES (SELECT MAX(user_id) FROM user WHERE usertype ='Student' , ?)";
and then
stmt5 = conn.prepareStatement(createStudentQuery);
stmt5.setString(1, ed_level);
stmt5.executeUpdate();
All the declarations(connection, statement) have been made.
There are 2 values that needs to be inserted, student_id and ed_level . But in your select statement there is only one value, MAX(user_id). You have to also add the value for ed_level in the select query.
Also, your query should be:
INSERT INTO <TABLE_1> (COLUMN_1, COLUMN_2,...) SELECT COLUMN_1, COLUMN_2,... FROM <TABLE_2> WHERE <CONDITION>
I have modified the query to something like this:
INSERT INTO student (student_id, ed_level) VALUES ((SELECT MAX(user_id) FROM user WHERE usertype ='Student') , ?)
Hope this helps.

Using Select and where statement in Criteria

I am in the process of replacing jdbc with hibernate in my Web Application. I have learned that i don't have to write any SQL queries in this. Instead of this,criteria queries can help me.
These are my SQL queries which i want to convert to hibernate using criteria not HQL.
String getOrgIdQuery = "SELECT * FROM USER_DETAILS WHERE USER_ID= ?";
rsDeptName = stmt.executeQuery("SELECT DEPARTMENT_NAME FROM DEPARTMENT WHERE DEPARTMENT_ID ="+ DeptID + ";");
String insertCreateCdcValuesFirst = ("UPDATE User_Details SET User_Name=?, Organization_ID=?, Department_ID=?, Access_Ctrl = ?, User_Role=? WHERE User_ID = ?;");
First off all you must map your table with POJOS.
String getOrgIdQuery = "SELECT * FROM USER_DETAILS WHERE USER_ID= ?";
Preceding code in Hibernate look like following.
Criteria criteria = session.createCriteria(USER_DETAILS.class);
criteria.add(Restrictions.eq("user_id",yourUserId));
List<USER_DETAILS> list = criteria.list();
Your second select query is also same as preceding.
String insertCreateCdcValuesFirst = ("UPDATE User_Details SET User_Name=?, Organization_ID=?, Department_ID=?, Access_Ctrl = ?, User_Role=? WHERE User_ID = ?;");
With Hibernate Criteria update looks like following:
USER_DETAILS user_details = (USER_DETAILES) session.get(USER_DETAILS.class,yourUserId);
user_details.setUser_Name(NewUserName);
user_details.setOrganization_Id(newOrganizationId);
// some other fields update goes here
session.update(user_details);
tx.commit();
I hope this help you.

JDBC query RETURNING value

I have a problem trying to figure out how to get the id of the last inserted row using PostgreSQL and JDBC.
CREATE TABLE vet_care (
id serial PRIMARY KEY,
deworming int,
castration int
);
My query is
String insertVetCare = "INSERT INTO vet_care(castration,deworming) VALUES("+castrated+","+dewormed+") RETURNING id";
I want the id value (which is serial) for later use. I tried to execute the query like so:
int id = statement.executeUpdate(insertVetCare);
But this says after compilation, that "A result was returned when none was expected." and it does not insert the other values into table.
How can I get this to work?
If "id" means "generated identity key", then you've got it wrong.
The executeUpdate() method returns the number of affected rows, according to the javadocs.
You want it to return auto generated keys, like this.
More advice: Use PreparedStatement and bind values. Building up a SQL query that way is asking for a SQL injection attack.
// Why make the gc work? This query never changes.
private static final String INSERT_VET_CARE = "INSERT INTO vet_care(castration,deworming) VALUES(?, ?)";
PreparedStatement ps = connection.prepareStatement(INSERT_VET_CARE, Statement.RETURN_GENERATED_KEYS);
ps.setInt(1, castration);
ps.setInt(2, deworming);

PreparedStatement not executing correctly

query = "SELECT * FROM POST_COMMENT WHERE Post_date_time= ? AND Post_User= !;";
query = query.replace("?", "'"+post.getDatetime()+"'");
query = query.replace("!", Integer.toString(post.getPublisher().getID()));
PreparedStatement pstm = con.prepareStatement(query);
ResultSet rs = pstm.executeQuery();
The resulting query looks like this
SELECT * FROM POST_COMMENT WHERE Post_date_time= '2013-04-12 07:20:34.0' AND Post_User= 378;
Which works right in the MySQL prompt line but, when launched from prepared statement throws this 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 '07:20:34.0 AND Post_User=378' at line 1
But
pstm.setString(1, post.getDatetime());
pstm.setString(2, Integer.toString(post.getPublisher().getID()));
isn't working either.
Table definition
CREATE TABLE Post_Comment (
Comment_ID INTEGER(7) NOT NULL,
Post_date_time DATETIME NOT NULL,
Post_User INTEGER(7) NOT NULL,
PRIMARY KEY(Comment_ID, Post_date_time, Post_User),
CONSTRAINT Post_Comment_Post
FOREIGN KEY (Post_User, Post_date_time)
REFERENCES Post (User, date_time)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT Post_Comment_Comment
FOREIGN KEY (Comment_ID)
REFERENCES Commentary (ID)
ON DELETE CASCADE
ON UPDATE CASCADE
)
;
Please help.
Take a look at the Java tutorials. You're not supposed to replace() the fields using the String functions.
You're supposed to call the "set" methods of the PreparedStatement.
EDIT:
No, take a look at the available methods. And what types the database columns expect. If you want a date, use setDate(), if you want an Integer, then use setInt(). Example:
query = "SELECT * FROM POST_COMMENT WHERE Post_date_time = ? AND Post_User = ?;";
PreparedStatement pstm = con.prepareStatement(query);
pstm.setDate(1, post.getDatetime());
pstm.setInt(2, post.getPublisher().getID());
ResultSet rs = pstm.executeQuery();
Also note that the query uses ? for both placeholders, not !.
query = "SELECT * FROM POST_COMMENT WHERE Post_date_time= ? AND Post_User= ?;";
PreparedStatement pstm = con.prepareStatement(query);
pstm.setObject(1, post.getDatetime());
pstm.setObject(2, post.getPublisher().getID());
ResultSet rs = pstm.executeQuery();

Categories