After executing code I get the Data saved message but no data is recorded in my clients table? I'm new to databases with Java, What am I doing wrong or how can I fix my code?
String sqlUrl = "jdbc:mysql://localhost:3306/clientinformation";
String user = "root";
String pass = "root";
String name = firstName.getText();
String lname = lastName.getText();
String cEmail = email.getText();
String rate = rateDbl.getText();
String cUrl = url.getText();
try {
Connection con = DriverManager.getConnection(sqlUrl, user, pass);
PreparedStatement st = con.prepareStatement("insert into clients
values('"+name+"', '"+lname+"', "
+ "'"+cEmail+"', '"+rate+"', '"+cUrl+"')");
JOptionPane.showMessageDialog(null, "Data saved!");
} catch (SQLException ex) {
Logger.getLogger(newClient.class.getName()).log(Level.SEVERE, null, ex);
}
What am I doing wrong
Well, you're building your SQL statement by concatenating values. That leads to SQL injection attacks - amongst other issues. Fortunately, that hasn't actually created a problem just yet - because you're never executing your statement.
You need to:
Parameterize your SQL, to avoid a SQL injection attack - use question marks for the parameters, and then use st.setString to set each parameter:
Connection con = DriverManager.getConnection(sqlUrl, user, pass);
PreparedStatement st = con.prepareStatement(
"insert into clients values (?, ?, ?, ?, ?)");
st.setString(1, name);
st.setString(2, lname);
st.setString(3, cEmail);
st.setString(4, rate); // Should this really be a string?
st.setString(5, cUrl);
st.executeUpdate();
JOptionPane.showMessageDialog(null, "Data saved!");
Call st.executeUpdate before you display the dialog box. (Ideally you shouldn't be mixing UI and data access in the same method, but...)
Please make the changes in that order though - do not just add a call to st.executeUpdate, or you've got a horrible security hole in your app.
The reason you're not seeing the data is you prepare the statement but never execute it. Call st.execute(); or st.executeUpdate(); to execute it.
Separately, though: That code is subject to SQL injection (attacks or otherwise); fun illustration here. Half the point of prepared statements is to protect against them. Use the parameters that prepared statements give you:
PreparedStatement st = con.prepareStatement("insert into clients values(?, ?, ?, ?, ?)");
int n = 1;
st.setString(n++, name);
st.setString(n++, lname);
st.setString(n++, cEmail);
st.setString(n++, rate);
st.setString(n++, cUrl);
// And then the missing execute
st.execute();
Related
So I am having a slight problem inserting values into a table I created in netbeans. I will show you the code that works and creates a new worker in the table and then show you what goes wrong when I try to change it.
This is a method from a class called dbConnect.java
public void insertTableRow() {
try {
Connection con = DriverManager.getConnection(host, uName, uPass);
Statement stmt = con.createStatement();
String SQL = "INSERT INTO Workers VALUES (10, 'John', 'Smith', 'Engineer')";
stmt.executeUpdate(SQL);
} catch (SQLException err) {
System.out.println(err.getMessage());
}
}
And is here where I call it in the main class.
dbConnect test = new dbConnect();
test.insertTableRow();
And then I get a John Smith appears so I know I have the right code. BUT when I try to enter in variables into VALUES it all falls apart. i.e.
public void insertTableRow(int id, String firstName, String lastName, String jobTitle) {
try {
int num = id;
String fName = firstName;
String lName = lastName;
String jTitle = jobTitle;
Connection con = DriverManager.getConnection(host, uName, uPass);
Statement stmt = con.createStatement();
String SQL = "INSERT INTO Workers VALUES (num, fName, lName, jTitle)";
stmt.executeUpdate(SQL);
} catch (SQLException err) {
System.out.println(err.getMessage());
}
}
Combined with -
dbConnect test = new dbConnect();
test.insertTableRow(10, "John", "Smith", "Doctor");
System.out.println(test.getTableContents());
The error I get back is:- Column 'NUM' is either not in any table in the FROM list or appears within a join specification and is outside the scope of the join specification or appears in a HAVING clause and is not in the GROUP BY list. If this is a CREATE or ALTER TABLE statement then 'NUM' is not a column in the target table.
So what am doing wrong because I have absolutely no idea?
when I try to enter in variables into VALUES it all falls apart
Statement stmt = con.createStatement();
String SQL = "INSERT INTO Workers VALUES (num, fName, lName, jTitle)";
stmt.executeUpdate(SQL);
You're not sending any variables. You have num, fName and the other variables but you're sending them as plain text in your SQL statement. You need to pass the values of your variables into your SQL statement.
The best approach to do this is using PreparedStatement:
String SQL = "INSERT INTO Workers VALUES (?, ?, ?, ?)";
PreparedStatement pstmt = con.prepareStatement(SQL);
p.setInt(1, num);
p.setString(2, fName);
p.setString(3, lName);
p.setString(4, jTitle);
pstmt.executeUpdate();
pstmt.close();
You may also use the naive approach of concatenating the values of each variable in your SQL statement, but it is unsafe and allows SQL Injection attacks. So the best bet is to use PreparedStatement.
More info:
Difference between Statement and PreparedStatement
String sql = "UPDATE `test`.`books` SET ? = ? WHERE `isbn` = ?;";
PreparedStatement ps = null;
ps = conn.prepareStatement(sql);
ps.setString(1,whatToUp);
ps.setString(2, data);
ps.setString(3, isbn);
ps.executeUpdate(sql);
System.out.println("Statement executed");
conn.close();
Error say that something is wrong with query . I am usign MySQL 5.6.
I copied the statement from the workbench 6.0 and just placed ? wherever I needed.
Even this Gives an error:
String sql = "UPDATE `test`.`books` SET `title` = ? WHERE `isbn` = ?;";
PreparedStatement ps = null;
ps = conn.prepareStatement(sql);
ps.setString(1, data);
ps.setString(2, isbn);
ps.executeUpdate(sql);
System.out.println("Statement executed");
conn.close();
You can build the query dynamically
String sql = "UPDATE `test`.`books` SET " + whatToUp + " = ? WHERE `isbn` = ?;";
PreparedStatement ps = null;
ps = conn.prepareStatement(sql);
ps.setString(1, data);
ps.setString(2, isbn);
ps.executeUpdate(); // you need to use the overloaded method without an argument
Note that you are then vulnerable to SQL injection.
If for some reason that is wrong, remove all the quotes.
String sql = "UPDATE test.books SET " + whatToUp + " = ? WHERE isbn = ?;";
If that doesn't work, then your schema doesn't match. That's up to you.
In my rush to answer I didn't see you were using
ps.executeUpdate(sql);
This method's javadoc says
Note:This method cannot be called on a PreparedStatement or
CallableStatement.
You have to use
ps.executeUpdate();
since you've already provided the sql statement to the method.
All of this would've been solved extremely quickly if you had just provided the exception stack trace. Consider that next time you ask a question
The problem is that you are calling executeUpdate(String) on a PreparedStatement, for which the documentation says:
SQLException - [...], the method is called on a PreparedStatement or CallableStatement
You need to use executeUpdate() (so without parameters) to execute a PreparedStatement. The reason is: a prepared statement already knows its query (the one it was created with), so it makes no sense to provide a query when executing it.
Note that the MySQL implementation is not entirely conforming to JDBC. It actually does allow executing with a String here, but it causes a syntax error because of the parameter placeholders.
Your first piece of code will never work, because parameters can only be used in places of values, not in places where object names (like table names) are expected.
#SotiriosDelimanolis gave you the answer.
Just build the SQL String differently
Stringbuilder sql = new Stringbuilder("UPDATE test.books SET ");
sql.append(whatToUp);
sql.append(" = ? WHERE isbn = ?");
PreparedStatement ps = null;
ps = conn.prepareStatement(sql.toString());
ps.setString(1, data);
ps.setString(2, isbn);
ps.executeUpdate(sql.toString());
System.out.println("Statement executed");
conn.close();
I am trying to insert data a user enters into a jtextfield into an msaccess database. When I try to execute my sql statement I get an error stating Syntax error in INSERT INTO statement.
I checked my sql statement and tried a few different things but cannot seem to find any kind of syntax error.
conn = Connect.ConnectDB();
String sql = "insert into Team ("
+"TeamID,"
+"TeamCity,"
+"TeamMascot,"
+ "values("+txtid.getText()+ ",'"+txtname.getText()+"','"+txtaddress.getText()+"')" ;
try{
pst = conn.prepareStatement(sql);
pst.execute();
JOptionPane.showMessageDialog(null, "Entry " + txtid.getText() + " Saved");
UpdateJTable();
//conn.close();
}
catch(Exception e){
JOptionPane.showMessageDialog(null, e);
}
The error is the extra comma and no closing parenthesis before the keyword values
String sql = "insert into Team ("
+"TeamID,"
+"TeamCity,"
+"TeamMascot," // <<== HERE, change comma into closing parenthesis
By the way, your statement is vulnerable with SQL Injection. You can avoid it if you parameterized the values. Eg,
String sql = "insert into Team (TeamID,TeamCity,TeamMascot) values (?, ?, ?, ?)"
pst = conn.prepareStatement(sql);
pst.setString(1, txtid.getText());
pst.setString(2, txtname.getText());
pst.setString(3, txtaddress.getText());
PreparedStatement
So far I have been able to insert data into my SQL table only when i declare values inside the executedUpdate statement. What I wanted to know if there is a way that I can pass those values as variables that I will declare as parameters in the executing method like so:
public void updateSQL(String name, String dnsName, String ipV4, String ipV6, int statusCode)
{
try
{
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection connection = DriverManager.getConnection("jdbc:sqlserver://servername;database=databasename;integratedSecurity=true");
System.out.println("Database Name: " + connection.getMetaData().getDatabaseProductName());
Statement statement = connection.createStatement();
statement.executeUpdate("INSERT INTO ComputerStatus(Name, DNSName, IPAddressV4, IPAddressV6, StatusCodeID)" + "VALUES(#Name, #DNSName, #IPAddressV4, #IPAddressV6, #StatusCodeID)");
System.out.println("Data Inserted");
ResultSet resultSet = statement.executeQuery("SELECT Name FROM ComputerStatus");
while(resultSet.next())
{
System.out.println("Computer Name: " + resultSet.getString("Name"));
}
connection.close();
}
catch (Exception e)
{
e.printStackTrace();
System.err.println("Problem Connecting!");
}
}
I've tried couple of different things but no luck so far. Anyone know if this can be done?
You may use PreparedStatement instead of Statement.
PreparedStatement stmt = connection.prepareStatement("insert into test (firstname, lastname) values (?, ?");
stmt.setString(1, name);
stmt.setString(2, lname);
stmt.executeUpdate();
Using this way, you prevent SQL injection.
Have a look here :
PreparedStatement prep = conn.prepareStatement("INSERT INTO ComputerStatus(Name, DNSName, IPAddressV4, IPAddressV6, StatusCodeID) VALUES(?, ?, ?, ?, ?)");
prep.setString(1, name);
prep.setString(2, dnsName);
prep.setString(3, ipV4name);
prep.setString(4, ipV6);
prep.setInt(5, statusCode);
prep.executeUpdate();
this will help you understand.
Is there a way to retrieve the auto generated key from a DB query when using a java query with prepared statements.
For example, I know AutoGeneratedKeys can work as follows.
stmt = conn.createStatement();
stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
if(returnLastInsertId) {
ResultSet rs = stmt.getGeneratedKeys();
rs.next();
auto_id = rs.getInt(1);
}
However. What if I want to do an insert with a prepared Statement.
String sql = "INSERT INTO table (column1, column2) values(?, ?)";
stmt = conn.prepareStatement(sql);
//this is an error
stmt.executeUpdate(Statement.RETURN_GENERATED_KEYS);
if(returnLastInsertId) {
//this is an error since the above is an error
ResultSet rs = stmt.getGeneratedKeys();
rs.next();
auto_id = rs.getInt(1);
}
Is there a way to do this that I don't know about. It seems from the javadoc that PreparedStatements can't return the Auto Generated ID.
Yes. See here. Section 7.1.9. Change your code to:
String sql = "INSERT INTO table (column1, column2) values(?, ?)";
stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
stmt.executeUpdate();
if(returnLastInsertId) {
ResultSet rs = stmt.getGeneratedKeys();
rs.next();
auto_id = rs.getInt(1);
}
There's a couple of ways, and it seems different jdbc drivers handles things a bit different, or not at all in some cases(some will only give you autogenerated primary keys, not other columns) but the basic forms are
stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
Or use this form:
String autogenColumns[] = {"column1","column2"};
stmt = conn.prepareStatement(sql, autogenColumns)
Yes, There is a way. I just found this hiding in the java doc.
They way is to pass the AutoGeneratedKeys id as follows
String sql = "INSERT INTO table (column1, column2) values(?, ?)";
stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
I'm one of those that surfed through a few threads looking for solution of this issue ... and finally get it to work. FOR THOSE USING jdbc:oracle:thin: with ojdbc6.jar PLEASE TAKE NOTE:
You can use either methods:
(Method 1)
Try{
String yourSQL="insert into Table1(Id,Col2,Col3) values(SEQ.nextval,?,?)";
myPrepStatement = <Connection>.prepareStatement(yourSQL, Statement.RETURN_GENERATED_KEYS);
myPrepStatement.setInt(1, 123);
myPrepStatement.setInt(2, 123);
myPrepStatement.executeUpdate();
ResultSet rs = getGeneratedKeys;
if(rs.next()) {
java.sql.RowId rid=rs.getRowId(1);
//what you get is only a RowId ref, try make use of it anyway U could think of
System.out.println(rid);
}
} catch (SQLException e) {
//
}
(Method 2)
Try{
String yourSQL="insert into Table1(Id,Col2,Col3) values(SEQ.nextval,?,?)";
//IMPORTANT: here's where other threads don tell U, you need to list ALL cols
//mentioned in your query in the array
myPrepStatement = <Connection>.prepareStatement(yourSQL, new String[]{"Id","Col2","Col3"});
myPrepStatement.setInt(1, 123);
myPrepStatement.setInt(2, 123);
myPrepStatement.executeUpdate();
ResultSet rs = getGeneratedKeys;
if(rs.next()) {
//In this exp, the autoKey val is in 1st col
int id=rs.getLong(1);
//now this's a real value of col Id
System.out.println(id);
}
} catch (SQLException e) {
//
}
Basically, try not used Method1 if you just want the value of SEQ.Nextval, b'cse it just return the RowID ref that you may cracked your head finding way to make use of it, which also don fit all data type you tried casting it to! This may works fine (return actual val) in MySQL, DB2 but not in Oracle.
AND, turn off your SQL Developer, Toad or any client which use the same login session to do INSERT when you're debugging. It MAY not affect you every time (debugging call) ... until you find your apps freeze without exception for some time. Yes ... halt without exception!
Connection connection=null;
int generatedkey=0;
PreparedStatement pstmt=connection.prepareStatement("Your insert query");
ResultSet rs=pstmt.getGeneratedKeys();
if (rs.next()) {
generatedkey=rs.getInt(1);
System.out.println("Auto Generated Primary Key " + generatedkey);
}