Java MySQL with prepared statement says parameter index out of range - java

I've looked on here before, but none of the answers helped me out!
I have the following code:
public void addSerialToDb(String serial) {
System.out.println(serial);
try{
System.out.println(getMaxInt());
}catch (Exception e){
e.printStackTrace();
}
String serialV2 = ""+serial;
try{
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection(url, user, password);
pst = con.prepareStatement("INSERT INTO blogdata.serials" + "VALUES(?, ?)");
pst.setInt(1, getMaxInt());
pst.setString(2, serialV2);
pst.executeUpdate();
}catch (Exception e) {
e.printStackTrace();
}
closeDataBase();
}
In my database scheme, there are 2 columns, first one is integer (id) and second one is a VARCHAR(45) (serial). But still I get the following error:
java.sql.SQLException: Parameter index out of range (2 > number of parameters, which is 0).
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:964)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:897)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:886)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:860)
at com.mysql.jdbc.PreparedStatement.checkBounds(PreparedStatement.java:3321)
at com.mysql.jdbc.PreparedStatement.setInternal(PreparedStatement.java:3306)
at com.mysql.jdbc.PreparedStatement.setString(PreparedStatement.java:4021)
at DataBase.SerialDataBase.addSerialToDb(SerialDataBase.java:41)
I used this method on another program, but since switched to IntelliJ it stopped working.
Thanks in advance!
EDIT:
I forgot to mention, I'm using Java 1.8, the mySql connector 5.1.40 and running MySql 5.7.15

According to your comment getMaxInt() method, the problems is because of prepare statement object. It's being updated in getMaxInt() method and parameters not match error occurred. I think it's program logic error and you just need to change this program logic. I also recommend to not concat the String if it's not needed.
Below is just ok.
pst = con.prepareStatement("INSERT INTO blogdata.serials (column1,column2) VALUES (?,?)";

Try using the insert statement like this:
"INSERT INTO blogdata.serials (column1,column2) VALUES (?,?)";

Related

Adding new values to mysql database no longer possible?

Hi guys please consider the code below. I was using it to add new values to my table(booking) in mysql database(seat_booking).
Variables include String(id,cname,ctype,event_name) and int(seatsno).I also call a function EventName() in this code and, trust me guys it works perfectly and I am able to derive the event name from the another table(events) but the only problem arises in this method.
Guys my project is to make a seat booking GUI app so this code does work when I used it to add new events for the "Admin" mode but doesn't work here ,i.e., when I need it to store the booking values for a particular customer. Please help guys. I would really appreciate it.
private void newbookbtnActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
try {
Class.forName("java.sql.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost/seat_booking","root","<mypassword>");
Statement stmt = con.createStatement();
String query = "SELECT * FROM booking";
ResultSet rs = stmt.executeQuery(query);
String cname = tfcname.getText();
int seatsno = Integer.parseInt(tfseatsno.getText());
String evtname = EventName();
String ctype = "Normal Customer"; long bookid = getID();
String id = Long.toString(bookid);
String query1="insert into booking values('"+ id +"','"+ cname +"','"+ ctype +"','"+evtname+"',"+ seatsno+");";
stmt.executeUpdate(query1);
JOptionPane.showMessageDialog(null, "Booking successfull!");
stmt.close();
con.close();
}
catch (Exception e)
{
JOptionPane.showMessageDialog(null,"Error encountered while booking new event!");
}
}
I have tried putting the e.Stacktrace(); statement in the application and I ran it the following was the resulting output for error:
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 's Track Events Warm-up,1)' at line 1
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1053)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4120)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4052)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2503)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2664)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2788)
at com.mysql.jdbc.StatementImpl.executeUpdate(StatementImpl.java:1816)
at com.mysql.jdbc.StatementImpl.executeUpdate(StatementImpl.java:1730)
at CustomerNewBook.newbookbtnActionPerformed(CustomerNewBook.java:256)
at CustomerNewBook.access$100(CustomerNewBook.java:16)
at CustomerNewBook$2.actionPerformed(CustomerNewBook.java:110)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
...
You use the wrong driver class. correct is:
Class.forName("com.mysql.jdbc.Driver");
java.sql.Driver is only an Interface. For more informations see the javadoc
BTW: Learn about prepared Statements to prevent sqlinjection
Do not supress error Messages. Atleast log them or put it into the message Dialog:
catch (Exception e)
{
e.printStacktrace();
JOptionPane.showMessageDialog(null,"Error encountered while booking new event!"+e.getMessage());
}
Update 2 (for this comment) :
Check the error,
You have an error in your SQL syntax ... near s Track Events Warm-up,1) ...
The problem is with the Strings that you are passing. Make sure any of your variables (id, cname, ctype, evtname) doesn't contain single qoutes(') or any other escape characters which may disturb the query.
This problem would easily be solved by using Prepared Statements. Try,
String query1 = "INSERT INTO `booking` VALUES(?, ?, ?, ?, ?)";
PreparedStatement stmt = con.prepareStatement(query1);
stmt.setString(1, id); //1 specifies the first parameter in the query
stmt.setString(2, cname);
stmt.setString(3, ctype);
stmt.setString(4, evtname);
stmt.setInt(5, seatsno); //use setInt() to parse ints
stmt.executeUpdate();
Update (for this comment):
In your catch block, comment the JOptionPane line and add the following,
catch (Exception e){
e.printStackTrace();
// JOptionPane.showMessageDialog(null, ...);
}
then run your application once again and update the question with the error output.
Original answer :
If you are using jdbc:mysql you need the MySQL connector.
Download it from mysql-connector-java-8.0.12,
Add the mysql-connector-java-8.0.12.jar to your project.
Change the driver class,
Class.forName("com.mysql.jdbc.Driver");
Clean and build (Optional but recommended).

How to inject a SQL command to drop a table in java

My java code for SQL Query is
String sqlSt="INSERT INTO users(id,name,place) values ("+null+",'"+request.getParameter("name")+"','"+request.getParameter("place")+"');";
I have tried out
name= a'); DROP TABLE users; --
as well as
place =a'); DROP TABLE users; --
but it returns an Ecxeption as below
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 'DROP TABLE users; --','chennai')' at line 1
Note: when i tried the same in mysql command line. It worked!!!! i don't know what happens in jdbc
The real problem is actually JDBC, it only allows one sql if you dont tell it otherwise.
Look at this question for more info:
Multiple queries executed in java in single statement
But also i would try this instead, name =
a',''); DROP TABLE users; --
Since you specificed 3 columns in your insert:
(id,name,place)
You need to provide 3 values for the sql to be valid, not just 2.
Also you can sent the text null, sending a java null value is not necessary and i am not even sure how that works. I think this might be better:
String sqlSt="INSERT INTO users(id,name,place) values (null,'"+request.getParameter("name")+"','"+request.getParameter("place")+"');";
Instead of null, use an empty string ''
String sqlSt = "INSERT INTO users(id, name, place) values ('', '" + request.getParameter("name") + "', '" + request.getParameter("place") + "');";
It's better to use prepared statements to avoid confusion.
String sqlSt = "INSERT INTO users(id, name, place) values ('', ?, ?)";
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(query);
ps.setString(1, request.getParameter("name"));
ps.setString(2, request.getParameter("place"));
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
ps.close();
}
The real problem is with your Query. It is better to use a PreparedStatement for executing a query.
Your Code should be :
String sqlSt="INSERT INTO users(id,name,place) values (?,?,?)";
PreparedStatement pstmt = null;
try{
pstmt = dbConnection.prepareStatement(sqlSt);
pstmt.setString(1,null);
pstmt.setString(2,request.getParameter("name"));
pstmt.setString(3,request.getParameter("place"));
pstmt.executeUpdate();
}catch (Exception e) {
e.printStackTrace();
} finally {
pstmt.close();
}
If you don't want to use a PreparedStatement, just remove last ; from your query.
So your query will be :
String sqlSt="INSERT INTO users(id,name,place) values ("+null+",'"+request.getParameter("name")+"','"+request.getParameter("place")+"')";

how to validate a username value with mysql and java to avoid duplicate user name

good day, i have a problem with this method, for some reason it gives me an error. "Java.sql.SqlException: statement is not executing". But it checks if the value is duplicate and prompts the error as the method below show. This has stopped my registration from completing. thanks for your help
public static void UserExists(String y){
try{
query = " select * from MailRegister where Username=?";
pst = connect.prepareStatement(query); //passes my query to java predefined prepared statement
pst.setString(1, Username.getText()); //passes the value of the username to the prepared statement
rs = pst.executeQuery(); //this would execute the query passed in the prepared statement
if(rs.next()){
JOptionPane.showMessageDialog(null, " Sorry This Username is Taken");
}
pst.close();
rs.close();
}catch(Exception e){
JOptionPane.showMessageDialog(null, e);//shows error dialog
}
}
You probably get this error because your objects are not closed properly all the time. Your connect is breaking. A good practice is to open and close the connection when required to prevent leaks.
In the code above, pst.close(); and rs.close(); should be in a finally.
Or even cleaner, the prepared statement should go inside a :
try (pst = connect.prepareStatement(query)) {...}
That way you don't have to close it yourself, the JVM will handle it for you.

SQLServerException: A result set was generated for update

I'm trying to insert a new record into an MS SQL database, and I'm getting an exception I've never seen before. When I call executeUpdate the following exception is thrown:
com.microsoft.sqlserver.jdbc.SQLServerException: A result set was generated for update.
This is the Java code that produces the error:
// addComment method adds a new comment for a given requestId
public CommentBean addComment(CommentBean comment) {
PreparedStatement stmt = null;
INative nat = null;
Connection conn = null;
try {
nat = dbConn.retrieveNative();
conn = (Connection)nat.getNative("java.sql.Connection");
stmt = conn.prepareStatement(ADD_COMMENT);
stmt.setInt(1, comment.getRequestId());
stmt.setString(2, comment.getComment());
stmt.setString(3, new SimpleDateFormat("MM/dd/yyyy").format(comment.getDateCreated()));
stmt.setString(4, comment.getCreatedBy());
comment.setCommentId(stmt.executeUpdate()); // exception
} catch(Exception ex) {
System.err.println("ProjectRegistration::SQLDAO - addComment");
ex.printStackTrace();
} finally {
try {
if (stmt != null) stmt.close();
} catch (Exception e) {}
}
return comment;
}// end addComment
Where ADD_COMMENT is defined as a String:
private static final String ADD_COMMENT = "INSERT INTO RequestComments OUTPUT INSERTED.commentId VALUES(?,?,?,?)";
For the sake of being thorough, the table is defined as:
CREATE TABLE RequestComments (
commentId int NOT NULL PRIMARY KEY IDENTITY(1,1),
requestId int FOREIGN KEY REFERENCES Requests(requestId),
comment varchar(400),
dateCreated date,
createdBy varchar(12)
);
I don't think I'm doing anything terribly complicated here, but I can't think of why I'm getting this exception. I have a method in the same class which does the exact same type of insertion (literally the same query with a different table name and number of values), and it has no issues. Does anyone have any ideas on how to resolve this issue?
This particular error can also be caused by an INSERT-trigger, which has a SELECT-statement as a part of the trigger code.
To test whether this is the case, you can try:
using executeQuery(), instead of executeUpdate() - and display the result.
executing the insert in tool like MySQL Workbench, SQL Server Management Studio, or whatever flavour of database design tools are available for your DBMS, to see whether a result is returned.
Related: sql server error "A result set was generated for update"
I'm hoping this may help others looking at the same error message, as it did for me. My solution was to live with a call to executeQuery(), although it only handles an underlying issue, instead of fixing it.
This instruction stmt.executeUpdate() is not returning the commentId, it returns a ResultSet which you could then get the commentId from. Something like this,
ResultSet rs = stmt.executeQuery(); // Not update, you're returning a ResultSet.
if (rs.next()) {
comment.setCommentId(rs.getInt(1));
}
you are using OUTPUT in your insert query i.e you will get a resultset after your query executes and to hold that you need an object of class ResultSet to hold that data
SqlServer : When SET NOCOUNT is ON, the count is not returned. When SET NOCOUNT is OFF, the count is returned.
Connection conn = DriverManager.getConnection(connectDB,user,pwd);
String sql = " set nocount off;INSERT INTO test (name) values (1)";
PreparedStatement prepareStatement = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
System.out.println(prepareStatement.executeUpdate());
ResultSet generatedKeys = prepareStatement.getGeneratedKeys();
if(generatedKeys.next()){
System.out.println(generatedKeys.getString(1));
}
Related:
set-nocount-on-usage
I've had a similar problem where after a while an insert on a autonumber table would give a "A result set was generated for update." at random. I use connection pooling and somehow the driver can get into a state where executeUpdate in combination with Statement.RETURN_GENERATED_KEYS doesn't work anymore. I found out that in this state an executeQuery does the trick, but in the initial state executeQuery does not work. This lead me to the following workaround:
PreparedStatement psInsert = connection.prepareStatement("INSERT INTO XYZ (A,B,C) VALUES(?,?,?)", Statement.RETURN_GENERATED_KEYS);
ResultSet rs = null;
try {
psInsert.setString(1, "A");
psInsert.setString(2, "B");
psInsert.setString(3, "C");
Savepoint savePoint = connection.setSavepoint();
try {
psInsert.executeUpdate();
rs = psInsert.getGeneratedKeys();
} catch (SQLServerException sqe)
{
if (!sqe.getMessage().equals("A result set was generated for update."))
throw sqe;
connection.rollback(savePoint);
rs = psInsert.executeQuery();
}
rs.next();
idField = rs.getInt(1);
} finally {
if(rs != null)
rs.close();
psInsert.close();
}

problems with update statement in SQLite

I have created a database using SQLite. I want to update the value of a "features" column( type Blob)...but i do not know how to write the "update" statement .
This is what i tried:
try {
stat = conn.createStatement();
} catch (SQLException e) {
}
try {
byte[] b = getFunction();
stat.executeUpdate("update table set features="+b);
} catch (SQLException e) {
}
i get the follwing error :
java.sql.SQLException: unrecognized token: "[B#13a317a"
so i guess that "b" is the problem ?
[B#13a317a looks like a array to string result (b.toString() in this case). You should use a prepared statement for the blob like:
update table set features=?
An example is here.
Generally, you should never create a SQL by concatenating strings. This is the recipe for SQL injection problems.
Try this one with PreparedStatement:
Connection con = null;
PreparedStatement stmt = null;
try {
byte[] b = getFunction();
con = ...;
stmt = con.prepareStatement("update table set features=?");
stmt.setBytes(1, b);
stmt.executeUpdate();
con.commit();
}
catch (SQLException e) {
//handle exception (consider con.rollback()) and con maybe null here)
}
finally {
//close stmt and at least con here (all maybe null here)
}
Personally I am always using PreparedStatements. When you have to write a lot of this code then consider writing some Utility-Classes to reduce Boilerplate-Code.
In particular you should consider writing Utilty-Classes for null-safe calling methods on Connection, Statement and ResultSet methods when you are dealing with plain JDBC.
EDIT
What Thomas Jung wrote about preventing SQL Injections is another big pro for always using PreparedStatements. +1 for him :-)
stat.executeUpdate("update table set features="+b[0].toString());
you have to use +

Categories

Resources