Java and mysql query check if result is empty - java

ResultSet zoeken = stat.executeQuery("SELECT * FROM leden WHERE naam = '" + text + "'");
if (zoeken.getRow() == 0){
System.out.println("hi");
}
while( zoeken.next() ){
System.out.println(zoeken.getString(1) + zoeken.getString(2) + zoeken.getString(3));
}
I am using this to check if the result zoeken is empty, but it throws an exception saying its illegal to do that regardless if it works or not.
What is a better solution to check if result is empty or not

// I am using this to check if the result"zoeken" is empty, but it
throws an exception saying its illegal to do that. regardless if it
works or not
Don't invoke ResultSet.getRow() before you invoke ResultSet.next().
From API:
A ResultSet object maintains a cursor pointing to its current row of
data. Initially the cursor is positioned before the first row. The
next method moves the cursor to the next row, and because it returns
false when there are no more rows in the ResultSet object, it can be
used in a while loop to iterate through the result set.
ResultSet zoeken = stat.executeQuery("SELECT * FROM leden WHERE naam = '" + text + "'");
boolean val = zoeken.next(); //next() returns false if there are no-rows retrieved
if(val==false){
System.out.println("zoken is empty"); //prints this message if your resultset is empty
}
while(val){// only runs when there are rows in the resultset
System.out.println(zoeken.getString(1) + zoeken.getString(2) + zoeken.getString(3));
val=zoeken.next(); //updating val again to check if there are rows in result set
}
If your result set is empty zoeken.next() will return false in which case your while loop will not execute.
An Advice
use PreparedStatement Instead of simple Statement. simple statement would lead to SQL Injection and also would ease the pain for writing complex queries.Below is the sample code which use PreparedStatement.
String yourquery ="Select whatever From table where col1= ? and col2 =?"
PreparedStatement stmnt = Conn.preparedStatement(yourquery);
stmnt.setString(1, "val1");
stmnt.setString(2, "val2");

Use next() method
boolean hasNext = zoeken.next();

Following code will work for you
if(!zoeken.first() && !zoeken.next())//if fist and next records are empty
{
System.out.println("Result set is empty");
}
else
{
System.out.println("Result set is not empty");
}

According to next() you must first use next and then getRow()
ResultSet zoeken = stat.executeQuery("SELECT * FROM leden WHERE naam = '" + text + "'");
while( zoeken.next() ){
int rowNum = zoeken.getRow();
System.out.println(zoeken.getString(1) + zoeken.getString(2) + zoeken.getString(3));
}

without using Result Set next() you cant check the size or resultSet period.
A ResultSet cursor is initially positioned before the first row.

I know the OP probably doesn't need the info any more but if someone stumbles across this, I would agree with everything #PermGenError has said although, I feel a more elegant solution for the given code but using prepared statements would be:
PreparedStatement ps = conn.prepareStatement("SELECT * FROM leden WHERE naam = ?");
ps.setString(title);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
do {
System.out.println(zoeken.getString(1) + zoeken.getString(2) + zoeken.getString(3));
} while (rs.next());
} else {
System.out.println("hi");
}
I have written this freehand so excuse any mistakes or if it doesn't compile. I just feel this is clearer and cuts down on the usage of local variables. If there is at least one row, go print the row and keep doing this until there are no more rows otherwise say "hi". But I assume you would want to say something more useful than "hi" maybe a "No results found" message or something.

Related

Result set always returns empty, should I not use executeQuery() on my prepared statement?

I've got users trying to register to a site. before they can register their username of choice is searched for in an SQL database to make sure it doesn't already exist.
the problem is the names are never searched because the ResultSet always returns empty. I think it's the prepared statement.
I think my prepared statement isn't executing. I'm using executeQuery() to execute my statement because that's how I've been inserting the usernames without any problem. I got the search ResultsSet part if (rs.next())... from the method that inserts the usernames. Same with the String SQL and the prepared statement stuff.
String SQL = "SELECT * FROM users WHERE username='" + getUsername() + "'";
System.out.println(SQL);
// prints out SELECT * FROM users WHERE username='whatever I searched'
// so this String is valid
if (db.getConn() != null){
System.out.println("connected to database");
// always prints
}
PreparedStatement preparedStatement = db.getConn().prepareStatement(SQL);
// preparedStatement.setString(1, getUsername());
ResultSet rs = preparedStatement.executeQuery();
// userNameCounter = rs.getString("username");
// putting this here returns an sqlexception. empty set
if (preparedStatement != null){
System.out.println("ps != null");
// prints this
}
if (rs != null){
System.out.println("rs != null");
// prints this
}
if (!rs.next()){
System.out.println("!rs.next");
// prints this
}
if (rs.next()) {
userNameCounter = rs.getString("username");
System.out.println("rs.next()");
// doesn't print
// so the resultset is empty
if (!userNameCounter.equals(getUsername())) {
System.out.println("that username is unique");
return true;
}
}
preparedStatement.close();
incorrectLabels.setText("That username is already taken");
incorrectLabels.setVisible(true);
System.out.println("that username is already there");
// this always prints. it shouldn't
return false;
So executeUpdate() requires an int but I'm not sure what I would put there. And doing just execute() throws an error Requires ResultSet found boolean. I don't think there are any syntax errors since the table is called users. Everything I try just leads me back to an error resulting from an empty set. let me know if you need more code but this is where the error is happening.
Thanks!
You are issuing a query to the database when using the SELECT statement therefore you use the executeQuery() method.
What looks confusing is the userNameCounter variable you're using. Where is it declared and what is it declared as? It looks like it may be a Integer variable which would bring me to ask....what do you think the rs.getString("username") method returns?
As a matter of fact...what's with all the rs.next() conditions for all those if statements?
The whole thing is rather confusing. If you want to see if a User Name already exists within a database table then you might do it something like this:
if (db.getConn() == null){
throw new RuntimeException("Method Error! You Are NOT Connected To Database!");
}
String suppliedUserName = getUsername();
String dbUserName = "";
String SQL = "SELECT username FROM users WHERE username=?";
PreparedStatement preparedStatement = db.getConn().prepareStatement(SQL);
preparedStatement.setString(1, suppliedUserName);
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
dbUserName = rs.getString("username");
}
rs.close()
preparedStatement.close()
/* Below we use the equalsIgnoreCase() method. You
don't want a supplied User Name to be that close
or that similar to another User Name already in
Database. If you do then just use equals() method. */
if (dbUserName.equalsIgnoreCase(suppliedUserName)) {
System.out.println("The User name (" + suppliedUserName +
") is already in use. Try another User Name.");
return false;
}
else {
System.out.println("The User name (" + suppliedUserName + ") is Unique.");
return true;
}
Of course this code isn't tested and I assume you have your try/catch in place to handle any SQLException. I merely provide this code to give you an idea of how it can be accomplished.

Retrieve an aggregated SQL value from a ResultSet in Java

I've been stuck with this problem for several hours: there are 3 tables, one of them connects the others through a place number and the tray ID. To find out how many samples are on a specific tray I aggregated the places by the tray ID, which works perfectly in pure SQL Code.
My Java code:
ps = connection.prepareStatement("SELECT TRAYID, COUNT(PlaceNo) AS OCCUPIED " +
"FROM PLACE " +
"GROUP BY TRAYID " +
"HAVING TRAYID = ?");
ps.setInt(1, trayId);
rs = ps.executeQuery();
if (!rs.isBeforeFirst()) { throw new CoolingSystemException(); }
else {
spaceOccupied = rs.getInt("OCCUPIED");
And with the last line the program crashes. I have also tried getInt(1) instead of the name but nothing works. And if the result set would be empty it would crash at
if (!rs.isBeforeFirst()) { throw new CoolingSystemException(); }
What I know for sure is that there is a value
Image: DBeaver using the same TrayID
I am sure that it is this spot because I logged it at each imaginable point before and after each line.
Does anyone has an idea how to solve it? I also tried every datatype in the get...() function :(
Your problem is that after you check whether there is any data in the result set, you're not moving the cursor forward with rs.next() before calling rs.getInt(). Now as it seems that you're only ever expecting the result set to contain up to one row, you can do the following instead:
ps = connection.prepareStatement("SELECT TRAYID, COUNT(PlaceNo) AS OCCUPIED " +
"FROM PLACE " +
"GROUP BY TRAYID " +
"HAVING TRAYID = ?");
ps.setInt(1, trayId);
rs = ps.executeQuery();
if (rs.next()) {
spaceOccupied = rs.getInt("OCCUPIED");
} else {
throw new CoolingSystemException();
}
The first invocation of rs.next() will return a falsey if the query didn't return any data.

MySQL - Object not null?

I am trying to check if a player is already is in the database with this code:
Statement sql = mySql.getConnection().createStatement();
ResultSet check = sql.executeQuery("SELECT * FROM `playerinfo` WHERE Username='" + player.getName() + "';");
System.out.println(check.toString());
if(check != null) {
System.out.println("2");
Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "Player already in database");
check.close();
sql.close();
return;
}
I checked but nothing is in the database and it says that the player already contains in the database
Sorry for bad english
Some considerations:
When checking whether the database contains a certain value, it's good practise to do this using a query that returns a single value (and not SELECT * which returns all columns of all rows that match the WHERE condition). You can do this e.g. by selecting a single check flag (SELECT 1) with a row-limiting clause (LIMIT 1):
SELECT 1 FROM playerinfo WHERE Username = ? LIMIT 1
This query is guaranteed to return only one row (with a single column, '1') if a player with the given name exists, or no rows if there are no players with the given name.
As others have pointed out, when you're inputting parameters into the query, you should use a PreparedStatement instead of a simple statement with concatenated inputs. This way, you can avoid SQL injection and the database is also able to reuse/cache the query (or cursor) internally.
Finally, you should close the resources you use, even if an Exception gets thrown during the execution. This is best done in the finally clause, or if you're on Java 7 or later, using the try-with-resources statement.
With these things in mind, a re-write of your code could look like this:
PreparedStatement ps = null;
try {
ps = mySQL.getConnection()
.prepareStatement("SELECT 1 FROM playerinfo WHERE Username = ? LIMIT 1");
ps.setString(1, player.getName());
ResultSet rs = ps.executeQuery();
// the first invocation of rs.next() returns true if
// there are rows in the result set, or false if no rows were found
if (rs.next()) {
System.out.println("2");
Bukkit.getConsoleSender().sendMessage(ChatColor.RED
+ "Player already in database");
}
rs.close();
} finally {
if (ps != null) {
ps.close();
}
}
I think instead of checking if the ResultSet is null or not, you should check if the ResultSet contains any row or not.
Apart from that, use PreparedStatements.

Newbie pointer rs.next

I would like to see only that products user is looking for them, but when second if is executed it will push(pointer or whatever is there) to next ID(id I have as unique so it will push to nowhere) and result is null. I hope you understand my problem :).
if (stmt.execute(
"SELECT * FROM products where ID=" + removeName)) {
rs = stmt.getResultSet();
if (!rs.next()) {
m = "ID not found.";
return m;
}
In your case, you can go for PreparedStatement for avoiding SQL-Injection problem.
PreparedStatement prodsQuery= con.prepareStatement("SELECT * FROM products where ID=?");
prodsQuery.setInt(1,removeName);
ResultSet rs = prodsQuery.executeQuery();
if(!rs.next())
{
m = "ID not found.";
return m;
}
The problem is that you're reading the first result in order to know if there's at least one result, then trying to consume the next results and missing the first one (adapted from your question description). I gave an explanation of how this works here.
A possible solution for this problem would be assuming the query executed with no problems and you have your results, then retrieve the data (or List of data) and as a last step verify if the data is not null or the List of data is not empty.
Code adapted from Naveen's answer to show the proposed solution
PreparedStatement prodsQuery =
con.prepareStatement("SELECT * FROM products where ID=?");
prodsQuery.setInt(1,removeName);
ResultSet rs = prodsQuery.executeQuery();
Assuming there's only one result to get:
//also assuming you will set the results in a Data class (yes, this can be replaced)
Data data = null;
if (rs.next()) {
//logic to retrieve data...
data = new Data();
data.setSomething(rs.get(1));
//more and more code to fill the data...
//because it looks that you need it as String (wonder why you return a String as well)
return data.toString();
}
//note: I use an else statement to check if indeed there were no results at all
//else statement added using a line separator for code explanation purposes
else {
m = "ID not found.";
return m;
}
Assuming there is a list of results to get:
//also assuming you will set the results in a Data class (yes, this can be replaced)
List<Data> dataList = new ArrayList<Data>();
while (rs.next()) {
//logic to retrieve data...
Data data = new Data();
data.setSomething(rs.get(1));
//more and more code to fill the data...
//because it looks that you need it as String (wonder why you return a String as well)
dataList.add(data);
}
//in this case, there's no validation in order to know if there's any result
//the validation must be in the client of this class and method checking if
//the result list is empty using if(!List#isEmpty) { some logic... }
return dataList;
First thing, your approach is vulnerable to SQL Injection. Please go for PreparedStatement.
Look at this simple example for using PreparedStatement
And you should do like this :
ResultSet rs = stmt.executeQuery("SELECT * FROM products where ID=" + removeName);
if (!rs.next()) {
m = "ID not found.";
return m;
}

How do I get the size of a java.sql.ResultSet?

Shouldn't this be a pretty straightforward operation? However, I see there's neither a size() nor length() method.
Do a SELECT COUNT(*) FROM ... query instead.
OR
int size =0;
if (rs != null)
{
rs.last(); // moves cursor to the last row
size = rs.getRow(); // get row id
}
In either of the case, you won't have to loop over the entire data.
ResultSet rs = ps.executeQuery();
int rowcount = 0;
if (rs.last()) {
rowcount = rs.getRow();
rs.beforeFirst(); // not rs.first() because the rs.next() below will move on, missing the first element
}
while (rs.next()) {
// do your standard per row stuff
}
Well, if you have a ResultSet of type ResultSet.TYPE_FORWARD_ONLY you want to keep it that way (and not to switch to a ResultSet.TYPE_SCROLL_INSENSITIVE or ResultSet.TYPE_SCROLL_INSENSITIVE in order to be able to use .last()).
I suggest a very nice and efficient hack, where you add a first bogus/phony row at the top containing the number of rows.
Example
Let's say your query is the following
select MYBOOL,MYINT,MYCHAR,MYSMALLINT,MYVARCHAR
from MYTABLE
where ...blahblah...
and your output looks like
true 65537 "Hey" -32768 "The quick brown fox"
false 123456 "Sup" 300 "The lazy dog"
false -123123 "Yo" 0 "Go ahead and jump"
false 3 "EVH" 456 "Might as well jump"
...
[1000 total rows]
Simply refactor your code to something like this:
Statement s=myConnection.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY);
String from_where="FROM myTable WHERE ...blahblah... ";
//h4x
ResultSet rs=s.executeQuery("select count(*)as RECORDCOUNT,"
+ "cast(null as boolean)as MYBOOL,"
+ "cast(null as int)as MYINT,"
+ "cast(null as char(1))as MYCHAR,"
+ "cast(null as smallint)as MYSMALLINT,"
+ "cast(null as varchar(1))as MYVARCHAR "
+from_where
+"UNION ALL "//the "ALL" part prevents internal re-sorting to prevent duplicates (and we do not want that)
+"select cast(null as int)as RECORDCOUNT,"
+ "MYBOOL,MYINT,MYCHAR,MYSMALLINT,MYVARCHAR "
+from_where);
Your query output will now be something like
1000 null null null null null
null true 65537 "Hey" -32768 "The quick brown fox"
null false 123456 "Sup" 300 "The lazy dog"
null false -123123 "Yo" 0 "Go ahead and jump"
null false 3 "EVH" 456 "Might as well jump"
...
[1001 total rows]
So you just have to
if(rs.next())
System.out.println("Recordcount: "+rs.getInt("RECORDCOUNT"));//hack: first record contains the record count
while(rs.next())
//do your stuff
int i = 0;
while(rs.next()) {
i++;
}
I got an exception when using rs.last()
if(rs.last()){
rowCount = rs.getRow();
rs.beforeFirst();
}
:
java.sql.SQLException: Invalid operation for forward only resultset
it's due to by default it is ResultSet.TYPE_FORWARD_ONLY, which means you can only use rs.next()
the solution is:
stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
[Speed consideration]
Lot of ppl here suggests ResultSet.last() but for that you would need to open connection as a ResultSet.TYPE_SCROLL_INSENSITIVE which for Derby embedded database is up to 10 times SLOWER than ResultSet.TYPE_FORWARD_ONLY.
According to my micro-tests for embedded Derby and H2 databases it is significantly faster to call SELECT COUNT(*) before your SELECT.
Here is in more detail my code and my benchmarks
The way of getting size of ResultSet, No need of using ArrayList etc
int size =0;
if (rs != null)
{
rs.beforeFirst();
rs.last();
size = rs.getRow();
}
Now You will get size, And if you want print the ResultSet, before printing use following line of code too,
rs.beforeFirst();
It is a simple way to do rows-count.
ResultSet rs = job.getSearchedResult(stmt);
int rsCount = 0;
//but notice that you'll only get correct ResultSet size after end of the while loop
while(rs.next())
{
//do your other per row stuff
rsCount = rsCount + 1;
}//end while
String sql = "select count(*) from message";
ps = cn.prepareStatement(sql);
rs = ps.executeQuery();
int rowCount = 0;
while(rs.next()) {
rowCount = Integer.parseInt(rs.getString("count(*)"));
System.out.println(Integer.parseInt(rs.getString("count(*)")));
}
System.out.println("Count : " + rowCount);
theStatement=theConnection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet theResult=theStatement.executeQuery(query);
//Get the size of the data returned
theResult.last();
int size = theResult.getRow() * theResult.getMetaData().getColumnCount();
theResult.beforeFirst();
I checked the runtime value of the ResultSet interface and found out it was pretty much a ResultSetImpl all the time. ResultSetImpl has a method called getUpdateCount() which returns the value you are looking for.
This code sample should suffice:
ResultSet resultSet = executeQuery(sqlQuery);
double rowCount = ((ResultSetImpl)resultSet).getUpdateCount()
I realize that downcasting is generally an unsafe procedure but this method hasn't yet failed me.
Today, I used this logic why I don't know getting the count of RS.
int chkSize = 0;
if (rs.next()) {
do { ..... blah blah
enter code here for each rs.
chkSize++;
} while (rs.next());
} else {
enter code here for rs size = 0
}
// good luck to u.
I was having the same problem. Using ResultSet.first() in this way just after the execution solved it:
if(rs.first()){
// Do your job
} else {
// No rows take some actions
}
Documentation (link):
boolean first()
throws SQLException
Moves the cursor to the first row in this ResultSet object.
Returns:
true if the cursor is on a valid
row; false if there are no rows in the result set
Throws:
SQLException - if a database access error occurs; this method is called on a closed result set or the result set type is TYPE_FORWARD_ONLY
SQLFeatureNotSupportedException - if the JDBC driver does not support
this method
Since:
1.2
Easiest approach, Run Count(*) query, do resultSet.next() to point to the first row and then just do resultSet.getString(1) to get the count. Code :
ResultSet rs = statement.executeQuery("Select Count(*) from your_db");
if(rs.next()) {
int count = rs.getString(1).toInt()
}
Give column a name..
String query = "SELECT COUNT(*) as count FROM
Reference that column from the ResultSet object into an int and do your logic from there..
PreparedStatement statement = connection.prepareStatement(query);
statement.setString(1, item.getProductId());
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {
int count = resultSet.getInt("count");
if (count >= 1) {
System.out.println("Product ID already exists.");
} else {
System.out.println("New Product ID.");
}
}

Categories

Resources