Most of my code seems to work, but I keep on getting Exception in thread "main" java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0). It happens after the finally block in readDatabase(). It doesn't get to the print statement System.out.println("DOESN'T GET HERE");
I don't know why. Here is the class where everything is processed. In the main class, it just makes an object of this one and calls readDatabase();
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
//static because when creating an object of it in main, you won't have to make an object of the outer class (SQLProject) first
public class MySQLAccess{
private Connection connect = null;
private Statement statement = null;
private PreparedStatement preparedStatement = null;
private ResultSet resultSet = null;
public void readDatabase() throws Exception
{
try{
Class.forName("com.mysql.jdbc.Driver");
connect = DriverManager.getConnection("jdbc:mysql://localhost/test", "root", "");
statement = connect.createStatement();
System.out.println("here1");
resultSet = statement.executeQuery("select * from test.comments");
writeResultSet(resultSet);
preparedStatement = connect.prepareStatement("INSERT INTO test.comments values(default, ?, ?, ?, ?, ?, ?)");
//columsn in test.comments
// myuser, email, webpage, datum, summary, COMMENTS
preparedStatement.setString(1, "Test");
preparedStatement.setString(2, "TestEmail");
preparedStatement.setString(3, "TestWebpage");
preparedStatement.setDate(4, new java.sql.Date(2009, 12, 11));
preparedStatement.setString(5, "Test Summary");
preparedStatement.setString(6, "Test Comment");
System.out.println("here2");
preparedStatement.executeUpdate();
preparedStatement = connect.prepareStatement("SELECT myuser, webpage, datum, summary, comments FROM test.comments");
System.out.println("here3");
resultSet = preparedStatement.executeQuery();
writeResultSet(resultSet);
preparedStatement = connect.prepareStatement("DELETE FROM test.comments WHERE myuser='?';");
preparedStatement.setString(1, "Test");
preparedStatement.executeUpdate();
resultSet = statement.executeQuery("SELECT * FROM test.comments;");
System.out.println("Writing meta data");
writeMetaData(resultSet);
}
catch (Exception e){
throw e;
}
finally{
close();
System.out.println("ALMOST");
}
System.out.println("DOESN'T GET HERE");
}
private void writeMetaData(ResultSet resultSet) throws SQLException
{
System.out.println("The columns in the table are: ");
System.out.println("Table: " + resultSet.getMetaData().getTableName(1));
for(int i=1;i<=resultSet.getMetaData().getColumnCount(); i++)
{
System.out.println("Column " + i + " " + resultSet.getMetaData().getColumnName(i));
}
}
private void writeResultSet(ResultSet resultSet) throws SQLException
{
while(resultSet.next())
{
String user = resultSet.getString("myuser");
String website = resultSet.getString("webpage");
String summary = resultSet.getString("summary");
Date date = resultSet.getDate("datum");
String comment = resultSet.getString("comments");
System.out.println("User: " + user);
System.out.println("website: " + website);
System.out.println("summary: " + summary);
System.out.println("date: " + date);
System.out.println("comment: " + comment);
}
}
private void close()
{
try{
if(resultSet != null)
resultSet.close();
if(statement != null)
statement.close();
if(connect != null)
connect.close();
}
catch(Exception e){
e.printStackTrace();
System.out.println("hello");
System.out.println(e);
}
}
}//private inner class
preparedStatement =
connect.prepareStatement("DELETE FROM test.comments WHERE myuser='?';");
preparedStatement.setString(1, "Test");
This is the problematic statement. The question mark is enclosed in quotes and so the statement parser is not able to find it out and so the next statement is throwing the error.
Though the parameter type is String, the corresponding placeholder shouldn't be included in quotes. The prepared statement processor will take care of generating the appropriate SQL based on the data type of parameters. So, it is always a plain ? that should be used as placeholder for parameters of any data type.
So, those two statements should simply be as follows:
preparedStatement =
connect.prepareStatement("DELETE FROM test.comments WHERE myuser=?");
preparedStatement.setString(1, "Test");
Related
Here's the code:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String PatientID = jtxtPatientID.getText();
try {
Connection con = ConnectionProvider.getCon();
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("select *from patient where PatientID='" + PatientID + "'");
jTable1.setModel(DbUtils.resultSetToTableModel(rs));
while(rs.first()){
jlbPID.setVisible(false);
jtxtPatientID.setEditable(false);
}
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Connection Error");
}
}
My code is going to the catch block, but I don't know why.
First of all, answering your question, your problem is that "select *from patient where PatientID='" + PatientID + "'" is not a valid SQLstatement, because the * and the FROM clause are together. Instead, add a space on it.
Just change:
ResultSet rs = st.executeQuery("select *from patient where PatientID='" + PatientID + "'");
with:
ResultSet rs = st.executeQuery("select * from patient where PatientID='" + PatientID + "'");
And, as a side note, just a mere recommendation: Don't use the Statement interface if your SQL has parameters, instead, use the PreparedStatement interface. Otherwise, your code will be vulnerable to SQL Injection.
And, please, change your catch blocks to someting which is able to log what's happening on your application. It will help you a lot when debugging. What I recommend you is, basically, this:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
private static final Logger LOG = LogManager.getLogger(Myclass.class);
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String PatientID = jtxtPatientID.getText();
String sql = "select * from patient where PatientID=?";
try {
Connection con = ConnectionProvider.getCon();
PreparedStatement st = con.prepareStatement(sql);
st.setString(1, PatientID);
ResultSet rs = st.executeQuery();
jTable1.setModel(DbUtils.resultSetToTableModel(rs));
while(rs.first()){
jlbPID.setVisible(false);
jtxtPatientID.setEditable(false);
}
} catch (SQLException e) {
LOG.error("Error while processing the SQL statement...", e);
JOptionPane.showMessageDialog(null, "Connection Error");
}
}
I used log4j2 for the logging purposes of this example.
Below is my code:
I'm passing three parameters to method insertRecordIntoTable which will execute JDBC insert query but I'm receiving Invalid column index.
Below are log statements which got printed:
Inside insertRecordIntoTable
ID from sequence 14
Invalid column index
private static void insertRecordIntoTable(String userName, String targetEmail, String siteName) throws SQLException {
Connection dbConnection = null;
PreparedStatement preparedStatement = null;
System.out.println("Inside insertRecordIntoTable ");
String insertTableSQL = "insert into TableName values(?,?,?,?,?)";
try {
dbConnection = getDBConnection();
preparedStatement = dbConnection.prepareStatement(insertTableSQL);
ResultSet srs = preparedStatement.executeQuery("SELECT id_seq.NEXTVAL FROM dual");
if ( srs!=null && srs.next() ) {
int myId = srs.getInt(1);
System.out.println("ID from sequence "+myId);
preparedStatement.setInt(1, myId);
System.out.println("Inserted ID value "+myId);
srs.close();
}
preparedStatement.setString(2, userName);
System.out.println("Inserted username value "+userName);
preparedStatement.setString(3, targetEmail);
System.out.println("Inserted targetEmail value "+targetEmail);
preparedStatement.setString(4, siteName);
System.out.println("Inserted sitecode value "+siteName);
preparedStatement.setTimestamp(5, getCurrentTimeStamp());
System.out.println("Inserted date value "+getCurrentTimeStamp());
preparedStatement .executeUpdate();
System.out.println("Inserted values ");
System.out.println("Inserted name & email into the table...");
// execute insert SQL stetement
preparedStatement.executeUpdate();
System.out.println("Record is inserted into DBUSER table!");
} catch (SQLException e) {
System.out.println(e.getMessage());
} finally {
if (preparedStatement != null) {
preparedStatement.close();
}
if (dbConnection != null) {
dbConnection.close();
}
}
}
You are using the same PreparedStatement variable twice
preparedStatement.executeQuery("SELECT id_....);
Create and use another variable for this Query else the original Query will be overwritten.
Also consider what is going to happen if
if ( srs!=null && srs.next() ) {
returns false
I tried to save / edit / delete a new row in the database. writing in the gui values to be saved with getText ()
here is the code
Connection conn = Connessione.ConnecrDb();
Statement stmt = null;
ResultSet emps = null;
try{
String sql;
sql = "INSERT INTO PROGETTO.LIBRO (ISBN, DISPONIBILITA, TITOLO, CASA_EDITRICE, CODICE_AUTORE, GENERE, PREZZO)"
+ "VALUES (txt_isbn, txt_disp, txt_titolo, txt_casa, txt_autore, txt_genere, txt_prezzo)";
stmt = conn.createStatement();
emps = stmt.executeQuery(sql);
String ISBN= txt_isbn.getText();
String DISPONIBILITA= txt_disp.getText();
String TITOLO= txt_titolo.getText();
String CASA_EDITRICE= txt_casa.getText();
String CODICE_AUTORE= txt_autore.getText();
String GENERE= txt_genere.getText();
String PREZZO = txt_prezzo.getText();
JOptionPane.showMessageDialog(null, "SALVATO");
}catch(SQLException | HeadlessException e)
{
JOptionPane.showMessageDialog(null, e);
}
finally
{
try{
if (emps != null)
emps.close();
}
catch (SQLException e) { }
try
{
if (stmt != null)
stmt.close();
}
catch (SQLException e) { }
}
Getting this error: column not allowed here
Above code just takes care of insert operation. How can I delete and modify table record?
You have asked 2 different questions here
1. Column not allowed here
This happened because you have not passed values for any of parameter into insert statement.
I am not sure about your requirement however I will use PreparedStatement for this scenario.
Example
String insertTableSQL = "INSERT INTO DBUSER"
+ "(USER_ID, USERNAME, CREATED_BY, CREATED_DATE) VALUES"
+ "(?,?,?,?)";
PreparedStatement preparedStatement = dbConnection.prepareStatement(insertTableSQL);
preparedStatement.setInt(1, 11);
preparedStatement.setString(2, "MindPeace");
preparedStatement.setString(3, "system");
preparedStatement.setTimestamp(4, getCurrentTimeStamp());
preparedStatement .executeUpdate();
2. This code is only to save the data, delete, and modify an entire row how can I do?
Answer is very simple. You have to write code for the same :)
You need 3 SQL statement which has DELETE and UPDATE operation just like insert in above example.
String sql = "INSERT INTO PROGETTO.LIBRO (ISBN, DISPONIBILITA, TITOLO, "
+ "CASA_EDITRICE, CODICE_AUTORE, GENERE, PREZZO)"
+ "VALUES (?, ?, ?, ?, ?, ?, ?)";
try (PreparedStatement stmt = conn.createStatement()) {
NumberFormat numberFormat = NumberFormat.getInstance(Locale.ITALY);
String ISBN = txt_isbn.getText();
String DISPONIBILITA = txt_disp.getText();
String TITOLO = txt_titolo.getText();
String CASA_EDITRICE = txt_casa.getText();
String CODICE_AUTORE = txt_autore.getText();
String GENERE = txt_genere.getText();
BigDecimal PREZZO = new BigDecimal(
numberFormat.parse(txt_prezzo.getText()).doubleValue())
.setScale(2);
stmt.setString(1, ISBN);
stmt.setString(2, DISPONIBILITA);
stmt.setString(3, TITOLO);
stmt.setString(4, CASA_EDITRICE);
stmt.setString(5, CODICE_AUTORE);
stmt.setString(6, GENERE);
stmt.setBigDecimal(7, PREZZO);
int updateCount = stmt.executeUpdate();
JOptionPane.showMessageDialog(null, "SALVATO");
} catch(SQLException | HeadlessException e) {
JOptionPane.showMessageDialog(null, e);
}
Try-with-resources closes the stmt automatically.
The prepared statement replaces the value in the SQL with something like:
INSERT INTO table(column1, colum2, ....)
VALUES('De\'l Rey',
1234.50,
...)
for:
"De'l Rey"
1.234,50
updateCount should be 1 on success.
Wooow..true!!
I created three buttons to delete / update / insert and now it all works and automatically updates the tables.
you've been very very great. Thank you very much.
one last thing.
if I wanted to insert an error message when I delete / update etc "book not found" I tried to create an if:
Boolean found = false;
try{
sql= delete......
etc
if (!found)
JOptionPane.showMessageDialog(null, "NOT FOUND","ERRORE",JOptionPane.WARNING_MESSAGE);
etc...
Connection conn = Connessione.ConnecrDb();
Statement stmt = null;
ResultSet emps = null;
try{
String sql= "DELETE FROM progetto.libro WHERE isbn =?"; /
pst=(OraclePreparedStatement) conn.prepareStatement(sql);
pst.setString (1, txt_isbn.getText());
pst.execute();
JOptionPane.showMessageDialog(null, "ELIMINATO");
Update_table();
txt_isbn.setText("");
txt_disp.setText("");
txt_titolo.setText("");
txt_casa.setText("");
txt_autore.setText("");
txt_genere.setText("");
txt_prezzo.setText("");
}
catch (Exception e)
{
JOptionPane.showMessageDialog(null,e);
}
if you find the book must exit the book removed, or "not found". but as I deployed I always come out "deleted". why?
thanks again
package controller;
import pojo.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcConn {
int found=0;
public boolean register(Member c)
{
Connection conn=null;
Statement stmt =null;
ResultSet rs = null;
try
{
Class.forName("oracle.jdbc.driver.OracleDriver");
conn= DriverManager.getConnection("jdbc:oracle:thin:#localhost","system","system");
stmt=conn.createStatement();
System.out.println("Data base is connected");
rs= stmt.executeQuery("select USERID from member");
System.out.println("Hi");
while(rs.next())
{
System.out.println("bye");
if((c.getUserId()).equals(rs.getString(1)) )
{
System.out.println("bye");
found=1;
break;
}
}
if(found==1)
{
return false;
}
else
stmt.executeUpdate("insert into member values ('"+ c.getName() +"','"+c.getEmail()+ "','"+c.getMobileNo()+ "','"+c.getAddress1()+"',,'"+c.getAddress2()+"','"+c.getUserId()+"','"+c.getPassword()+"','"+c.getSecretQuestion()+"','"+c.getSecretAnswer()+"')");
return true;
}
catch(ClassNotFoundException e)
{
System.out.print(e);
e.printStackTrace();
}
catch(SQLException e)
{
System.out.print(e);
}
return false;
}
public boolean login(String userid, String password)
{
Connection conn=null;
Statement stmt =null;
ResultSet rs = null;
try
{
Class.forName("oracle.jdbc.driver.OracleDriver");
conn = DriverManager.getConnection("jdbc:oracle:thin:#localhost","system","system");
stmt=conn.createStatement();
rs= stmt.executeQuery("select userid, password from member where userid = '"+userid+"'");
if(rs==null)
{
return false;
}
else
{
while(rs.next())
{
String uid,pass;
uid=rs.getString(1);
pass=rs.getString(2);
if(password.equals(pass))
{
return true;
}
else
{
return false;
}
}
}
}
catch(ClassNotFoundException e)
{
System.out.print(e);
}
catch(SQLException e)
{
System.out.print(e);
}
return false;
}
}
I am invoking the code from one servlet. It is showing me the following output.Though the same code is working correctly in somewhere else:
Output:
Data base is connected
Hi
java.sql.SQLException: ORA-00936: missing expression
Can anyone help me with the problem.
In your insert you have the following
+c.getAddress1()+"',,'"+c.getAddress2()+
There should be only one comma instead of two
I suggest to use PreparedStatement to avoid such error.
Advantage of using PreparedStatement over Statement
A SQL statement is precompiled and stored in a PreparedStatement object.
This object can then be used to efficiently execute this statement multiple times.
Reduces execution time.
Automatic prevention of SQL injection attacks by builtin escaping of quotes and other special characters
Read more PreparedStatements and performance
See Java Tutorial on Using Prepared Statements
sample code:
String insertTableSQL = "INSERT INTO DBUSER"
+ "(USER_ID, USERNAME, CREATED_BY, CREATED_DATE) VALUES"
+ "(?,?,?,?)";
PreparedStatement preparedStatement = dbConnection.prepareStatement(insertTableSQL);
preparedStatement.setInt(1, 11);
preparedStatement.setString(2, "mkyong");
preparedStatement.setString(3, "system");
preparedStatement.setTimestamp(4, getCurrentTimeStamp());
// execute insert SQL stetement
preparedStatement .executeUpdate();
Find complete Sample example here to learn more about it.
Use prepared statements to avoid such issues. This will also avoid issues which you may face because of certain special characters like single quotes etc.
If not, then try one of the following:
If there is no column between address1 and address2, then use below (extra comma removed):
String query = " stmt.executeUpdate("insert into member values ('"+ c.getName() +"','"+c.getEmail()+ "','"+c.getMobileNo()+ "','"+c.getAddress1()+"','"+c.getAddress2()+"','"+c.getUserId()+"','"+c.getPassword()+"','"+c.getSecretQuestion()+"','"+c.getSecretAnswer()+"')"); ";
stmt.executeUpdate (query);
If there is supposed to be an empty value that has to be inserted, then use below (an empty field is inserted using ,'', )
String query = " stmt.executeUpdate("insert into member values ('"+ c.getName() +"','"+c.getEmail()+ "','"+c.getMobileNo()+ "','"+c.getAddress1()+"', '' ,'"+c.getAddress2()+"','"+c.getUserId()+"','"+c.getPassword()+"','"+c.getSecretQuestion()+"','"+c.getSecretAnswer()+"')"); ";
stmt.executeUpdate (query);
In your insert statement you can specify which columns you insert/update that would correspond to the SQL syntax having insert into member (col1, col2) values (val1, val2). The number of columns should be exactly the same before and after values in parenthesis. Incorrect number of columns or values are caused the error.
I am trying to create a servlet on a specific URL to handle a HTML post from another server and receive all parameters and their values and insert them into a database.
Got to this code so far:
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.*;
import java.sql.*;
public class QueryServlet extends HttpServlet {
#Override
public void doPost(HttpServletRequest req,HttpServletResponse res) throws IOException, ServletException
{
String instId=req.getParameterValues("instId")[0];
String cartId=req.getParameterValues("cartId")[0];
String desc=req.getParameterValues("desc")[0];
String cost=req.getParameterValues("cost")[0];
String amount=req.getParameterValues("amount")[0];
String currency=req.getParameterValues("currency")[0];
String name=req.getParameterValues("name")[0];
String transId=req.getParameterValues("transId")[0];
String transStatus=req.getParameterValues("transStatus")[0];
String transTime=req.getParameterValues("transTime")[0];
String cardType=req.getParameterValues("cardType")[0];
Connection conn = null;
Statement stmt = null;
PrintWriter out=res.getWriter();
try
{
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/orders", "root", "root");
stmt = conn.createStatement();
String sqlStr = "insert into orderdetails values('"+transId+"','"+instId+"','"+cartId+"','"+desc+"'"+cost+"','"+amount+"','"+currency+"','"+name+"','"+transStatus+"','"+transTime+"','"+cardType+")";
out.println("<html><head><title>Query Response</title></head><body>");
out.println("<h3>Thank you for your query.</h3>");
out.println("<p>You query is: " + sqlStr + "</p>"); // Echo for debugging
ResultSet rset = stmt.executeQuery(sqlStr); // Send the query to the server
}
catch(SQLException ex)
{
ex.printStackTrace();
}
}
}
I have tried some changes to it and I allways get errors.
Could you give me a hand?
Btw, I have very little knowledge of java, been trying to "hack my way" into doing this from other people examples and from going trough guides.
Thanks in advance
Edit: I can't log into my dev machine atm as it is having problems and is down, it had something to do with Null pointer or Null value, can't give the exact error atm, will update as soon as possible.
I am also aware of the SQL injection with the code, just trying to test it first and make it work and change the code before I set it live.
There where some quote/comma hickups and it should be exevcuteUpdate.
However it is important to use a PreparedStatement:
easier on the SQL string, escapes special chars in the strings (like apostrophe)
you can used typed parameters, like BigDecimal below
security SQL injection
I used the try-with-resources syntax to close the stmt.
String instId = req.getParameter("instId");
String cartId = req.getParameter("cartId");
String desc = req.getParameter("desc");
String cost = req.getParameter("cost");
BigDecimal amount = new BigDecimal(req.getParameter("amount"));
String currency = req.getParameter("currency");
String name = req.getParameter("name");
String transId = req.getParameter("transId");
String transStatus = req.getParameter("transStatus");
String transTime = req.getParameter("transTime");
String cardType = req.getParameter("cardType");
Connection conn = null;
Statement stmt = null;
PrintWriter out = res.getWriter();
try {
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/orders", "root", "root");
String sqlStr = "insert into orderdetails "
+ "values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
try (PreparedStatement stmt = conn.prepareStatement(sqlStr)) {
stmt.setString(1, transId);
stmt.setString(2, instId);
stmt.setString(3, cartId);
stmt.setString(4, desc);
stmt.setString(5, cost);
stmt.setBigDecimal(6, amount);
stmt.setString(7, currency);
stmt.setString(8, name);
stmt.setString(9, transStatus);
stmt.setString(10, transTime);
stmt.setString(11, cardType);
int updateCount = stmt.executeUpdate();
out.println("<html><head><title>Query Response</title></head><body>");
out.println("<h3>Thank you for your query. " + updateCount + " record(s) updated.</h3>");
out.println("<p>You query is: " + sqlStr + "</p>"); // Echo for debugging
for (Enumeration<String> en = req.getParameterNames(); en.hasMoreElements();) {
String paramName = en.nextElement();
String paramValue = req.getParameter(paramName);
out.println("<p>" + paramName + ": " + paramValue + "</p>"); // Echo for debugging
}
} // Does stmt.close()
} catch (SQLException ex) {
ex.printStackTrace();
}
For inserting or updating or deleting use executeUpdate() but you are using executeQuery()
and executeUpdate method returns an integer(No.of rows affected) so change
ResultSet rset = stmt.executeQuery(sqlStr);
to
int update= stmt.executeUpdate(sqlStr);
Also prefer to use PreparedStatement