<%
String qTotal = "SELECT MsThread.ID, MsThread.ThreadName, Count(MsThread.ThreadName) AS TotalPost, ThreadCategory FROM MsThread LEFT OUTER JOIN MsPosts ON MsThread.ThreadName = MsPosts.ThreadName GROUP BY MsThread.ID, MsThread.ThreadName, MsThread.ThreadCategory;";
ResultSet rs = stmt.executeQuery(qTotal);
int size = 0;
while(rs.next())
{
out.print(size++);%><br/><%
}
rs.first();
out.println(rs.getString("id"));
rs.next();
out.println(rs.getString("id"));
rs.next();
out.println(rs.getString("id"));
if(!rs.next())
{
out.println("no data");
}
else
out.println(rs.getString("id"));
%>
Guys, here's what happened, when i tried to run the query it shows 3 result (http://s29.postimg.org/6qiv9kc9j/ss_forum.png) but when i run the
while(rs.next())size++;
it returns 4, and when i try to show the data, it gives me invalid cursor state, so is there anything wrong with my query?
thanks
The default sensitivity of a ResultSet is TYPE_FORWARD_ONLY, which means that it cannot be scrolled; you cannot call any of these methods that move the cursor -
previous
first
last
beforeFirst
afterLast
relative(int rows)
absolute(int row)
Except next, your ResultSet cannot be scrolled. If your resultset if created with default sensitivity then they can not be scrolled using rs.first(); after moving to last end via rs.next() in while statement.
but when i run the while(rs.next())size++; it returns 4,
When a ResultSet object is first created, the cursor is positioned before the first row, so you are getting 4.
Thanks
Related
I am using the ucanaccess tool to interact with my access database, but I do not know how to display or store the resulting ResultSets as Strings.
Edit: I have tried =System.out.println(resultSetId.getString(1)); but that only returns errors.
ResultSet resultSetId;
String msAccDB = "D://Computer Science//passManager//src//Manager.accdb";
String dbURL = "jdbc:ucanaccess://" + msAccDB;
connection = DriverManager.getConnection(dbURL);
statement = connection.createStatement();
resultSetId = statement.executeQuery("SELECT ID FROM Passwords WHERE ID =
\""+identifier+"\";");
System.out.println(resultSetId.getString(1));
Gives the error Exception in thread "main" net.ucanaccess.jdbc.Ucanaccessenter code hereSQLException: invalid cursor state: identifier cursor not positioned on row in UPDATE, DELETE, SET, or GET statement: ; ResultSet is positioned before first row
Edit: Adding the .next() fixed it, thanks!
ResultSet is positioned before first row
When executeQuery returns the ResultSet it is not pointing at a row of data. You need to call resultSetId.next() in order to retrieve each row. That is often done in the context of a while loop when the ResultSet is expected to return more than one row, e.g.,
while (resultSetId.next()) {
System.out.println(resultSetId.getString(1)); // print value from each row
}
but you can simply call it once if you only expect a single row, e.g.,
if (resultSetId.next()) {
System.out.println(resultSetId.getString(1));
} else {
System.out.println("The ResultSet contained no rows.");
}
I was inserting multiple rows in a ResultSet as shown like below, I need to print out the ResultSet after inserting all rows, so tried moving the cursor back to before first row and it fails there with an error - "Error at this line: Java.lang.IllegalStateException: This method cannot be called when the cursor is on the insert row"
ResultSet rs = ...;
for(int i=0; i<5; i++){
rs.moveToInsertRow();
rs.updateString("NAME", "Jon");
rs.updateString("ADDRESS", "111 New York");
rs.updateString("EMAIL", "test#test.com");
}
rs.beforeFirst(); // Error at this line: Java.lang.IllegalStateException: This method cannot be called when the cursor is on the insert row
//ResultSet print logic goes here
if( rs.getType() == ResultSet.TYPE_FORWARD_ONLY){
ResultSetMetaData rsmd = rs.getMetaData();
int columnsNumber = rsmd.getColumnCount();
while (rs.next()) {
for (int i = 1; i <= columnsNumber; i++) {
String columnValue = rs.getString(i);
sb.append(rsmd.getColumnName(i)).append(" : ").append(columnValue).append(" ");
}
}
}
Any idea, how to move the cursor back to initial position when moveToInsertRow() has been invoked?
You should make your Statement scrollable to do this, something like below
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
After having done an insert, you need to leave the insert row using moveToCurrentRow() to go back to the row you where on, after having done that (and assuming you actually have a scrollable cursor) you can call beforeFirst().
Note that - depending on the driver implementation - it is entirely possible that the rows inserted through the result set are not visible to the current result set.
I have a two database table, on a single button click in my program , I want to delete all the two table's data. But there's always one datum left on the table.. Here is my code:
public void mouseClicked(MouseEvent arg0) {
int confirm = JOptionPane.showConfirmDialog(null, "Are you sure you want to delete the log? ", "Log", JOptionPane.YES_NO_OPTION );
if (confirm == JOptionPane.YES_OPTION){
try{
Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver");
con = DriverManager.getConnection("jdbc:odbc:RIM");
Statement st1 = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
Statement st2 = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
String sql1 = "select * from userLogIn";
ResultSet rs1 = st1.executeQuery(sql1);
String sql2 = "select * from userViewed";
ResultSet rs2 = st2.executeQuery(sql2);
while(rs1.next()){
rs1.deleteRow();
rs1.first();
}
while(rs2.next()){
rs2.deleteRow();
rs2.first();
}
editorPane.setText("");
}catch(Exception e){e.printStackTrace();}
When there is only one element left, your call to first() sets the cursor to that element, but then the next() call in the while condition will return false, causing the exit from the loop and thus the deleteRow won't be executed.
Use rs.beforeFirst()`.
Note that your code has lots of issues, so get this answers as "for educational purposes" only.
Why are you iterating over a select record set at all? It's incredibly inefficient.
If you want to delete all data from those tables, you can simply execute the statements:
delete from userLogin;
delete from userViewed;
(or use truncate).
I have for example the following code line
ResultSet rs = stmt.executeQuery("SELECT * FROM item WHERE itemID='"+ X +"'");
if item table scheme is: ItemID,itemName,Count,location
how does the row from the table "sit" in the ResultSet?
is there a way to take the entire row and push it to the first cell of ArrayList (that is the value i must return and i can not change it, for other queries with multiple line results each line will be in a different cell of the array)?
you can iterate over your resultset using ResultSet.next() and get the row information on every iteration and add it into your array list.
List<YourObj> ref = new ArrayList<>();
ResultSet rs = stmt.executeQuery("SELECT * FROM item WHERE itemID='"+ X +"'");
while(rs.next())
ref.add(new YourObj(rs.getName(), rs.getWhatever()));
}
Here's the reference from Oracle Trails
How to check if resultset has one row or more with JDBC?
ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1");
boolean isMoreThanOneRow = rs.first() && rs.next();
You didn't ask this one, but you may need it:
boolean isEmpty = ! rs.first();
Normally, we don't need the row count because we use a WHILE loop to iterate through the result set instead of a FOR loop:
ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1");
while (rs.next()) {
// retrieve and print the values for the current row
int i = rs.getInt("a");
String s = rs.getString("b");
float f = rs.getFloat("c");
System.out.println("ROW = " + i + " " + s + " " + f);
}
However, in some cases, you might want to window the results, and you need the record count ahead of time to display to the user something like Row 1 to 10 of 100. You can do a separate query with SELECT COUNT(*) first, to get the record count, but note that the count is only approximate, since rows can be added or removed between the time it takes to execute the two queries.
Sample from ResultSet Overview
There are many options, and since you don't provide more context the only thing left is to guess. My answers are sorted by complexity and performance ascending order.
Just run select count(1) FROM ... and get the answer. You'd have to run another query that actually selects and returns the data.
Iterate with rs.next() and count until you're happy. Then if you still need the actual data re-run same query.
If your driver supports backwards iteration, go for rs.next() couple of times and then rewind back with rs.previous().
You don't need JDBC for this. The normal idiom is to collect all results in a collection and make use of the collection methods, such as List#size().
List<Item> items = itemDAO.list();
if (items.isEmpty()) {
// It is empty!
if (items.size() == 1) {
// It has only one row!
} else {
// It has more than one row!
}
where the list() method look like something:
public List<Item> list() throws SQLException {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
List<Item> items = new ArrayList<Item>();
try {
connection = database.getConnection();
statement = connection.createStatement();
resultSet = statement.executeQuery(SQL_LIST);
while (resultSet.next()) {
Item item = new Item();
item.setId(resultSet.getLong("id"));
item.setName(resultSet.getString("name"));
// ...
items.add(item);
}
} finally {
if (resultSet != null) try { resultSet.close(); } catch (SQLException logOrIgnore) {}
if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
}
return items;
}
If you want to make sure that there is exactly one row, you can ensure that the first row is the last:
ResultSet rs = stmt.executeQuery("SELECT a FROM Table1 WHERE b=10");
if (rs.isBeforeFirst() && rs.next() && rs.isFirst() && rs.isLast()) {
// Logic for where there's exactly 1 row
Long valA = rs.getLong("a");
// ...
}
else {
// More that one row or 0 rows returned.
// ..
}
My no-brainer suggestion: Fetch the first result row, and then try to fetch the next. If the attempt is successful, you have more than one row.
If there is more than one row and you want to process that data, you'll need to either cache the stuff from the first row, or use a scrollable result set so you can seek back to the top before going through the results.
You can also ask SQL directly for this information by doing a SELECT COUNT(*) on the rest of your query; the result will be 0, 1 or more depending on how many rows the rest of the query would return. That's pretty easy to implement but involves two queries to the DB, assuming you're going to want to read and process the actual query next.
This implementation allows you to check for whether result of the query is empty or not at the cost of duplicating some lines.
ResultSet result = stmt.executeQuery("SELECT * FROM Table");
if(result.next()) {
// Duplicate the code which should be pasted inside while
System.out.println(result.getInt(1));
System.out.println(result.getString(2));
while(result.next()){
System.out.println(result.getInt(1));
System.out.println(result.getString(2));
}
}else{
System.out.println("Query result is empty");
}
Drawbacks:
In this implementation a portion of the code will be duplicated.
You cannot know how many lines are present in the result.
Get the Row Count using ResultSetMetaData class.
From your code u can create ResultSetMetaData like :
ResultSetMetaData rsmd = resultSet.getMetaData(); //get ResultSetMetaData
rsmd.getColumnCount(); // get row count from resultsetmetadata