PreparedStatement issue in postgresql (select query) [duplicate] - java

I have a typical crosstab query with static parameters. It works fine with createStatement. I want to use preparestatement to query instead.
String query = "SELECT * FROM crosstab(
'SELECT rowid, a_name, value
FROM test WHERE a_name = ''att2''
OR a_name = ''att3''
ORDER BY 1,2'
) AS ct(row_name text, category_1 text, category_2 text, category_3 text);";
PreparedStatement stat = conn.prepareStatement(query);
ResultSet rs = stat.getResultSet();
stat.executeQuery(query);
rs = stat.getResultSet();
while (rs.next()) {
//TODO
}
But it does not seem to work.
I get a PSQLException -
Can't use query methods that take a query string on a PreparedStatement.
Any ideas what I am missing?

You have fallen for the confusing type hierarchy of PreparedStatement extends Statement:
PreparedStatement has the same execute*(String) methods like Statement, but they're not supposed to be used, just use the parameterless execute*() methods of PreparedStatement --- you already have given the actual query string to execute using conn.prepareStatement().

Please try:
String query = "...";
PreparedStatement stat = conn.prepareStatement(query);
ResultSet rs = stat.executeQuery();
while (rs.next()) {
// TODO
}

Related

Basic JDBC select working, when I switch to prepared statement it doesn't work

I am using Java 8 and oracle.
I have confirmed that this code is working:
Statement stmt = null;
String query = "select * from custref";
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
String cName = rs.getString("CUSTOMER_NAME");
System.out.println(cName);
}
When I change it to this, it does not give any results:
PreparedStatement prepStmt = null;
String query = "select * from custref where CUSTOMER_NUMBER = ?";
prepStmt = con.prepareStatement(query);
prepStmt.setString(1, "12344321");
ResultSet rs = prepStmt.executeQuery();
while (rs.next()) {
String cName = rs.getString("CUSTOMER_NAME");
System.out.println(cName);
}
I have confirmed that my data type is VARCHAR hence the set string. I know my connections are fine because the basic search works just when I switch to parameterized it doesn't fail or throw exceptions it just doesn't have a result set. I have also tried the :customerNumber convention instead of the ? and this didn't work either. This is quite embarrassing but I am at my end here, nothing I can find seems to address this.

Executing multiple queries with single PS

i have created prepared statement object .
now i want to get the result of multiple queries . is it possible to do using single prepared statement object/ find the piece code below
PreparedStatement ps = null;
String moviedirectorQry = "SELECT movie_director FROM movies WHERE movie_title= ?";
ps = dbConnection.prepareStatement(moviedirectorQry);
ps.setString(1, "Twilight");
ResultSet rs=null;
rs = ps.executeQuery(moviedirectorQry);
while (rs.next()) {
String director_name = rs.getString("movie_director");
System.out.println("director name : " + director_name);
}
now i want to run another query.. how to do
If the idea is to use the same PreparedStatement for different queries of the same type with only parameters' value that change, yes it is possible, simply call clearParameters() first to clear the parameters in case you want to reuse it before setting the new parameters' value.
The code could be something like that:
if (ps == null) {
// The PreparedStatement has not yet been initialized so we create it
String moviedirectorQry = "SELECT movie_director FROM movies WHERE movie_title= ?";
ps = dbConnection.prepareStatement(moviedirectorQry);
} else {
// The PreparedStatement has already been initialized so we clear the parameters' value
ps.clearParameters();
}
ps.setString(1, someValue);
ResultSet rs = ps.executeQuery();
NB: You are supposed to use executeQuery() not ps.executeQuery(moviedirectorQry) otherwise the provided parameters' value will be ignored such that the query will fail.

Return id after sql insert java [duplicate]

Is there a way to retrieve the auto generated key from a DB query when using a java query with prepared statements.
For example, I know AutoGeneratedKeys can work as follows.
stmt = conn.createStatement();
stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
if(returnLastInsertId) {
ResultSet rs = stmt.getGeneratedKeys();
rs.next();
auto_id = rs.getInt(1);
}
However. What if I want to do an insert with a prepared Statement.
String sql = "INSERT INTO table (column1, column2) values(?, ?)";
stmt = conn.prepareStatement(sql);
//this is an error
stmt.executeUpdate(Statement.RETURN_GENERATED_KEYS);
if(returnLastInsertId) {
//this is an error since the above is an error
ResultSet rs = stmt.getGeneratedKeys();
rs.next();
auto_id = rs.getInt(1);
}
Is there a way to do this that I don't know about. It seems from the javadoc that PreparedStatements can't return the Auto Generated ID.
Yes. See here. Section 7.1.9. Change your code to:
String sql = "INSERT INTO table (column1, column2) values(?, ?)";
stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
stmt.executeUpdate();
if(returnLastInsertId) {
ResultSet rs = stmt.getGeneratedKeys();
rs.next();
auto_id = rs.getInt(1);
}
There's a couple of ways, and it seems different jdbc drivers handles things a bit different, or not at all in some cases(some will only give you autogenerated primary keys, not other columns) but the basic forms are
stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
Or use this form:
String autogenColumns[] = {"column1","column2"};
stmt = conn.prepareStatement(sql, autogenColumns)
Yes, There is a way. I just found this hiding in the java doc.
They way is to pass the AutoGeneratedKeys id as follows
String sql = "INSERT INTO table (column1, column2) values(?, ?)";
stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
I'm one of those that surfed through a few threads looking for solution of this issue ... and finally get it to work. FOR THOSE USING jdbc:oracle:thin: with ojdbc6.jar PLEASE TAKE NOTE:
You can use either methods:
(Method 1)
Try{
String yourSQL="insert into Table1(Id,Col2,Col3) values(SEQ.nextval,?,?)";
myPrepStatement = <Connection>.prepareStatement(yourSQL, Statement.RETURN_GENERATED_KEYS);
myPrepStatement.setInt(1, 123);
myPrepStatement.setInt(2, 123);
myPrepStatement.executeUpdate();
ResultSet rs = getGeneratedKeys;
if(rs.next()) {
java.sql.RowId rid=rs.getRowId(1);
//what you get is only a RowId ref, try make use of it anyway U could think of
System.out.println(rid);
}
} catch (SQLException e) {
//
}
(Method 2)
Try{
String yourSQL="insert into Table1(Id,Col2,Col3) values(SEQ.nextval,?,?)";
//IMPORTANT: here's where other threads don tell U, you need to list ALL cols
//mentioned in your query in the array
myPrepStatement = <Connection>.prepareStatement(yourSQL, new String[]{"Id","Col2","Col3"});
myPrepStatement.setInt(1, 123);
myPrepStatement.setInt(2, 123);
myPrepStatement.executeUpdate();
ResultSet rs = getGeneratedKeys;
if(rs.next()) {
//In this exp, the autoKey val is in 1st col
int id=rs.getLong(1);
//now this's a real value of col Id
System.out.println(id);
}
} catch (SQLException e) {
//
}
Basically, try not used Method1 if you just want the value of SEQ.Nextval, b'cse it just return the RowID ref that you may cracked your head finding way to make use of it, which also don fit all data type you tried casting it to! This may works fine (return actual val) in MySQL, DB2 but not in Oracle.
AND, turn off your SQL Developer, Toad or any client which use the same login session to do INSERT when you're debugging. It MAY not affect you every time (debugging call) ... until you find your apps freeze without exception for some time. Yes ... halt without exception!
Connection connection=null;
int generatedkey=0;
PreparedStatement pstmt=connection.prepareStatement("Your insert query");
ResultSet rs=pstmt.getGeneratedKeys();
if (rs.next()) {
generatedkey=rs.getInt(1);
System.out.println("Auto Generated Primary Key " + generatedkey);
}

java : use of executeQuery(string) method not supported error?

I'm doing a simple preparedstatement query execution and its throwing me this error:
java.sql.SQLException: Use of the executeQuery(string) method is not supported on this type of statement at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.notSupported(JtdsPreparedStatement.java:197) at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.executeQuery(JtdsPreparedStatement.java:822) at testconn.itemcheck(testconn.java:58)
Any ideas what i'm doing incorrectly? thanks in advance
here is the code:
private static int itemcheck (String itemid ) {
String query;
int count = 0;
try {
Class.forName("net.sourceforge.jtds.jdbc.Driver");
con = java.sql.DriverManager.getConnection(getConnectionUrl2());
con.setAutoCommit(false);
query = "select count(*) as itemcount from timitem where itemid like ?";
//PreparedStatement pstmt = con.prepareStatement(query);
//pstmt.executeUpdate();
PreparedStatement pstmt = con.prepareStatement(query);
pstmt.setString(1,itemid);
java.sql.ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
count = rs.getInt(1);
System.out.println(count);
} //end while
}catch(Exception e){ e.printStackTrace(); }
return (count);
} //end itemcheck
A couple of things are worth checking:
Use a different alias. Using COUNT as an alias would be asking for trouble.
The query object need not be passed twice, once during preparation of the statement and later during execution. Using it in con.prepareStatement(query); i.e. statement preparation, is enough.
ADDENDUM
It's doubtful that jTDS supports usage of the String arg method for PreparedStatement. The rationale is that PreparedStatement.executeQuery() appears to be implemented, whereas Statement.executeQuery(String) appears to have been overriden in PreparedStatement.executeQuery() to throw the stated exception.
So...
PreparedStatement pstmt = con.prepareStatement(query);
pstmt.setString(1,itemid);
java.sql.ResultSet rs = pstmt.executeQuery(query);
Unlike Statement, with PreparedStatement you pass the query sql when you create it (via the Connection object). You're doing it, but then you're also passing it again, when you call executeQuery(query).
Use the no-arg overload of executeQuery() defined for PreparedStatement.
So...
PreparedStatement pstmt = con.prepareStatement(query);
pstmt.setString(1,itemid);
java.sql.ResultSet rs = pstmt.executeQuery();

Parameterized Oracle SQL query in Java?

I've been trying to figure out why the following code is not generating any data in my ResultSet:
String sql = "SELECT STUDENT FROM SCHOOL WHERE SCHOOL = ? ";
PreparedStatement prepStmt = conn.prepareStatement(sql);
prepStmt.setString(1, "Waterloo");
ResultSet rs = prepStmt.executeQuery();
On the other hand, the following runs properly:
String sql = "SELECT STUDENT FROM SCHOOL WHERE SCHOOL = 'Waterloo' ";
PreparedStatement prepStmt = conn.prepareStatement(sql);
ResultSet rs = prepStmt.executeQuery();
The data type for SCHOOL is CHAR (9 Byte). Instead of setString, I also tried:
String sql = "SELECT STUDENT FROM SCHOOL WHERE SCHOOL = ? ";
PreparedStatement prepStmt = conn.prepareStatement(sql);
String school = "Waterloo";
Reader reader = new CharArrayReader(school.toCharArray());
prepStmt.setCharacterStream(1, reader, 9);
prepStmt.setString(1, "Waterloo");
ResultSet rs = prepStmt.executeQuery();
I'm completely stuck on what to investigate next; the Eclipse debugger says the SQL query doesn't change even after setString or setCharacterStream. I'm not sure if it's because setting parameters isn't working, or if the debugger simply can't pick up changes in the PreparedStatement.
Any help will be greatly appreciated, thanks!
I think the problem is that your datatype is CHAR(9) and "Waterloo" has only 8 chars.
I assume that this would return the expected results (LIKE and %). Or add the missing space.
String sql = "SELECT STUDENT FROM SCHOOL WHERE SCHOOL LIKE ? ";
PreparedStatement prepStmt = conn.prepareStatement(sql);
prepStmt.setString(1, "Waterloo%");
ResultSet rs = prepStmt.executeQuery();
The best way would by to use varchar instead of char if your Strings have a flexible length. Then the PreparedStatement would work as expected.
A workaround would be to use the Oracle specific setFixedCHAR method (but it's better to change the datatype to varchar if possible).
The following is from Oracle's PreparedStatement JavaDoc:
CHAR data in the database is padded to the column width. This leads to a limitation in using the setCHAR() method to bind character data into the WHERE clause of a SELECT statement--the character data in the WHERE clause must also be padded to the column width to produce a match in the SELECT statement. This is especially troublesome if you do not know the column width.
setFixedCHAR() remedies this. This method executes a non-padded comparison.
Notes:
Remember to cast your prepared statement object to OraclePreparedStatement to use the setFixedCHAR() method.
There is no need to use setFixedCHAR() for an INSERT statement. The database always automatically pads the data to the column width as it inserts it.
The following example demonstrates the difference between the setString(), setCHAR() and setFixedCHAR() methods.
// Schema is : create table my_table (col1 char(10));
// insert into my_table values ('JDBC');
PreparedStatement pstmt = conn.prepareStatement
("select count() from my_table where col1 = ?");
ResultSet rs;
pstmt.setString (1, "JDBC"); // Set the Bind Value
rs = pstmt.executeQuery(); // This does not match any row
// ... do something with rs
CHAR ch = new CHAR("JDBC ", null);
((OraclePreparedStatement)pstmt).setCHAR(1, ch); // Pad it to 10 bytes
rs = pstmt.executeQuery(); // This matches one row
// ... do something with rs
((OraclePreparedStatement)pstmt).setFixedCHAR(1, "JDBC");
rs = pstmt.executeQuery(); // This matches one row
// ... do something with rs

Categories

Resources