SQLite select from LIKE statement not working? - java

When I view the database and run this query I get results as expected.
SELECT * FROM users WHERE options LIKE '%[-15,-3]%';
However when I use a prepared statement as seen below, the uuid is null.
String opt = "[-15,-3]"; //example
PreparedStatement ps = SQLite.connection.prepareStatement(
"SELECT * FROM users WHERE options LIKE '%" + opt + "%'"
);
ResultSet rs = ps.executeQuery();
String uuid = null;
while (rs.next()){
uuid = rs.getString("member");
}
rs.close();
ps.close();
if(uuid != null){
System.out.println("not null: " + uuid);
return Database.getUser(UUID.fromString(uuid);
}
For the code above, nothing is returned in the result set. Which is very strange because I used the same query with an SQLite viewer and it returned the proper rows. How can I solve this? I don't see an issue.
UPDATE
When I directly use "SELECT * FROM factions WHERE claims LIKE '%[-15,-3]%'" in the prepared statement instead of the variable, it works fine. Why can't I use a string variable? I've checked the variable and it prints to console fine.

I solved it after a lot of trial and error, turns out I should've been using a ? and set the string.
PreparedStatement ps = SQLite.connection.prepareStatement(
"SELECT * FROM users WHERE options LIKE ?"
);
ps.setString(1, "%" + opt + "%");

Related

Error when updating MySQL database using UPDATE - SET - WHERE method in Eclipse

I am making a program using Eclipse that allows the user to update the volume of chemicals everytime they’re restocked/used, which requires them to enter the ID of the chemical and the amount they would like to add/subtract. A query is then performed to search for the chemical's ID in the database, and its volume is updated accordingly.
However, I’m having difficulties getting the volume to update. I tried adapting MySQL’s UPDATE statement from this website to SET volume = volume + amount added, WHERE chemical ID = ID entered by the user; however, there appears to be some syntax errors in my code, more specifically at the UPDATE - SET - WHERE line:
public void IDEnter() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:8889/StockControlSystem","root","root");
Statement stmt = con.createStatement();
String sql = "Select * from Chemicals where `Chemical ID` ='" + txtChemical_ID.getText()+"'";
ResultSet rs = stmt.executeQuery(sql);
if(rs.next()) {
stmt.executeUpdate("UPDATE Chemicals" + "SET `Volume` = rs.getInt(Volume) + Integer.parseInt(AmountAdded.getText()) WHERE `Chemical ID` in (txtChemical_ID.getText())");
}
else {
JOptionPane.showMessageDialog(null, "Invalid chemical ID");
txtChemical_ID.setText(null);
}
} catch(Exception exc) {
exc.printStackTrace();
}
}
Since I'm still new to MySQL, can someone help me correct this? Thank you so much for your help!
Your whole query is badly formatted. Change your code to this:
stmt.executeUpdate("UPDATE Chemicals SET Volume = " +
rs.getInt(Volume) + Integer.parseInt(AmountAdded.getText())
+ " WHERE Chemical_ID in (" + txtChemical_ID.getText() + ")");
You cannot use ' single quotes when defining Column names in queries. Single quotes are used for string values!
Still, this would not be the best way to do this. use PreparedStatement!
This way:
String updateString = "UPDATE Chemicals SET Volume = ? WHERE Chemical_ID in (?)"; // Creation of the prepared statement, the ? are used as placeholders for the values
PreparedStatement preparedStatement = con.prepareStatement(updateString);
preparedStatement.setInt(1, rs.getInt(Volume) + Integer.parseInt(AmountAdded.getText())); // Setting the first value
preparedStatement.setString(2, txtChemical_ID.getText()); // Setting the second. I am supposing that this txtChemical_ID textField has values seperated by commas, else this will not work!
preparedStatement.executeUpdate();
If you need to read more for PreparedStatement there are a lot of great resources out there. They also protect against SQL injections.
I think your problem might be with the "rs.getInt(Volume)"
Yours:
"UPDATE Chemicals" + "SET `Volume` = rs.getInt(Volume)
+ Integer.parseInt(AmountAdded.getText())
WHERE `Chemical ID` in (txtChemical_ID.getText())"
Can you try this:
"UPDATE Chemicals" + "SET `Volume` = " +
Integer.parseInt(AmountAdded.getText()) + "
WHERE `Chemical ID` in (" + (txtChemical_ID.getText()) +")"

Working on this Java project where I need to be able to delete data from the database on user's request

The query inside MySQL is working:
DELETE FROM f9.yoo
WHERE account_tags = '#8GGGJPUR9'
I can delete data inside MySQL, but the problem is whenever I try to remove the account_tags from my Java application, it throws an error:
java.sql.SQLSyntaxErrorException: 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 'DELETE FROM f9.yoo
WHERE account_tags = '#8GGGJPUR9'' at line 2
Here's my Java SQL query:
Statement statement = dbConnection.createStatement();
String sql = "SELECT * FROM "+databaseName+"."+tableName+";\n" +
"DELETE FROM "+databaseName+"."+tableName+"\n" +
"WHERE account_tags = '"+AccountTag+"';";
statement.executeQuery(sql);
The error isn't giving me much to work with, so I really have no idea what is wrong with the program.
Did you add the allowMultiQueries=true
If not then you can add that while you sending the connecting request to your database. So you need to append the allowMultiQueries=true in your to database URL.
Like this:
String dbUrl = "jdbc:mysql:///test?allowMultiQueries=true";
String sql = "DELETE FROM "+databaseName+"."+tableName+"\n" +
"WHERE account_tags = ?";
try (PreparedStatement statement = dbConnection.prepareStatement(sq)) {
statement.setString(1, AccountTag);
int updateCount = statement.executeUpdate();
System.out.printf("%s: %d records deleted.%n", tableName, updateCount);
}
The only thing used is the DELETE, for which one should use executeUpdate.
One definitely should use a PreparedStatement as many code checkers will give alarms otherwise. It escapes things like ', handles types of the arguments, and possible conversions, and especially is a security feature against SQL injection.
The System.out usage is bad style, better would be using a logger.
try-with-resources automatically closes the PreparedStatement even with a raised exception or break/return.
When doing both database operations, it seems better to use two (prepared) statements, as the first returns a ResultSet.
So:
String sql = SELECT * FROM "+databaseName+"."+tableName + "\n" +
"WHERE account_tags = ?";
try (PreparedStatement statement = dbConnection.prepareStatement(sq)) {
statement.setString(1, AccountTag);
try (ResultSet rs = statement.executeQuery()) {
...
}
}
Better to separate statements with an If condition :
String sql1="SELECT * FROM "+databaseName+"."+tableName;
String sql2="DELETE FROM "+databaseName+"."+tableName+" "+
"WHERE account_tags = '"+AccountTag+"';
statement.executeQuery(sql1);
statement.executeUpdate(sql2);

Can't find an Error in SQL update statement

I'm working in one quiz game. There is question maker window. Which works good for saving question. But when want update one of text Field and press save, than error is happening. something is wrong with syntax?!
void insertCell(String tableNamer, String column, String value, int id) throws ClassNotFoundException, SQLException{
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:file:C:/Users/Juris Puneiko/IdeaProjects/for_my_testings/src/sample/DB/Questions/For_Private/Easy", "Juris", "1");
PreparedStatement ps = conn.prepareStatement("UPDATE ? SET ? = ? where ID = ?");
ps.setString(1, tableNamer);
ps.setString(2, column);
ps.setString(3, value);
ps.setInt(4, id);
ps.executeUpdate();
ps.close();
conn.close();
}
org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "UPDATE ?[*] SET ? = ? WHERE ID = ? "; expected "identifier"; SQL statement:
UPDATE ? SET ? = ? where ID = ? [42001-196]
What is this >>> [*]?
What does it mean?
String sql = "UPDATE " + tableNamer + " SET " + column + " = ? where ID = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, value);
ps.setInt(2, id);
ps.executeUpdate();
ps.close();
conn.close();
The placeholders can only be used for values in most SQL databases, not for identifiers like table or column names:
"UPDATE myTable SET myCol = ? where ID = ?" -- OK
"UPDATE ? SET ? = ? where ID = ?" -- not OK
The reason is that those parameters are also used for prepared statements, where you send the query to the database once, the database "prepares" the statement, and then you can use this prepared statement many times with different value parameters. this can improve DB performance because DB can compile and optimize the query and then use this processed form repeatedly - but to be able to do this, it needs to know names of the tables and columns involved.
To fix this, you only leave the ?s in for the values, and you concatenate the tableNamer and column manually:
"UPDATE " + tableNamer + " SET " + column + " = ? where ID = ?"
Keep in mind though that by doing this, tableNamer and column are now potentially vulnerable to SQL injection. Make sure that you don't allow user to provide or affect them, or else sanitize the user input.

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.

How to insert and select from mysql simultaneously

I have a requirement where I need to insert mobile number in mysql if and only if the number is is not present.So for this I am first checking if a number is present in mysql using select query .If number is not present then insert.Following is my code
PreparedStatement pt1=con.prepareStatement("select * from registerSmsUsers where mobile='"+mobile+"'");
PreparedStatement pt=con.prepareStatement("insert into registerSmsUsers values(?,?,?)");
pt.setString(1, name);
pt.setString(2, email);
pt.setString(3, mobile);
ResultSet rs1=pt1.executeQuery();
if(rs1.next())
{pt.executeUpdate();}
i dont know whether this is a efficient way or not.Please suggest me a better way then this
Probably the easiest way in mysql is:
insert ignore into registerSmsUsers values(?,?,?)
When assuming you have unique key on mobile
You may check it here: How to 'insert if not exists' in MySQL?
Or here: http://dev.mysql.com/doc/refman/5.6/en/insert.html
Many of the proposed solutions (including yours) have a race condition that can cause a primary key or unique constraint violation. You code also have a possible SQL injection attack by concatenating SQL rather than using prepared statement parameters. Use SELECT...FOR UPDATE.
PreparedStatement ps = con.prepareStatement("SELECT name, email, mobile FROM registerSmsUsers WHERE mobile=? FOR UPDATE",
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
ps.setString(1, mobile);
ResultSet rs = ps.executeQuery();
if (rs.next()) { // it exists already
rs.moveToCurrentRow();
rs.updateString(3, mobile);
rs.updateRow();
} else { // it does NOT exist
rs.moveToInsertRow();
rs.updateString(1, name);
rs.updateString(2, email);
rs.updateString(3, mobile);
rs.insertRow();
}
rs.close();
ps.close();
EDIT: Just make sure you have an index on registerSmsUsers.
CREATE INDEX registerSmsUsers_mobile_ndx ON registerSmsUsers(mobile)
or a unique contraint (which implicitly creates an index):
ALTER TABLE registerSmsUsers ADD CONSTRAINT registerSmsUsers_mobile_unq UNIQUE (mobile)
With an index, even with millions of records the update/insert will basically be instant.
EDIT2: Added cursor/result set options.
I think it would be better to create a stored procedure and then in that stored procedure you can first use the IF NOT EXISTS clause to check if the user exists using the select statement. If the user is not present you can insert the user in database.
Something like this:
IF NOT EXISTS(SELECT 1 FROM `registerSmsUsers` WHERE mobile= #mobile) THEN
BEGIN
INSERT INTO
`registerSmsUsers`
(
//column names
)
VALUES
(
//values
);
END;
END IF;
Also there is a INSERT IGNORE statement which you can use like this:
insert ignore into registerSmsUsers values(?,?,?)
if not exists(select * from registerSmsUsers where mobile='232323') <-- will check your mobile no
begin
insert into registerSmsUsers values(?,?,?)
end
This one is also an efficient way to check your method is also working fine but this also can be done
See difference is you will have only one query here
i hope this will help you thanks
[Edit]
Your questions answer
Ya there is a execution time diff between yours and mine query its depends upon a database size what you are using if you are using small size database (probably 1000 people) then you will not see any diff between your query and mine query but if your are using lakhs of users then your will have a performace issues check include execution plan in mysql you will get realtime difference between two
As requested, here is my tweaked version of brettw's answer:
import java.sql.*;
public class MySQLtest {
public static void main(String[] args) {
Connection con;
try {
con = DriverManager.getConnection(
"jdbc:mysql://192.168.1.3/zzzTest?" +
"useUnicode=yes&characterEncoding=UTF-8" +
"&user=root&password=whatever");
String newName = "Gord";
String newEmail = "gord#example.com";
String newMobile = "416-555-1212";
String sql =
"SELECT " +
"id, " +
"name, " +
"email, " +
"mobile " +
"FROM registerSmsUsers " +
"WHERE mobile = ? " +
"FOR UPDATE";
PreparedStatement pst = con.prepareStatement(
sql,
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
pst.setString(1, newMobile);
ResultSet rs = pst.executeQuery();
if (rs.next()) {
rs.moveToCurrentRow();
rs.updateString("name", newName);
rs.updateString("email", newEmail);
rs.updateRow();
System.out.println("Existing row updated.");
}
else {
rs.moveToInsertRow();
rs.updateString("name", newName);
rs.updateString("email", newEmail);
rs.updateString("mobile", newMobile);
rs.insertRow();
System.out.println("New row inserted.");
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
Note that id is the Primary Key for the table: int(11) NOT NULL AUTO_INCREMENT

Categories

Resources