Here is the code:
public static Connection getConnection() throws Exception {
String name1 = "Danny";
String city1 = "Wien";
try {
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/supermarket??verifyServerCertificate=false&useSSL=true";
String username = "myuser";
String password = "mypass";
Class.forName(driver);
Connection conn = DriverManager.getConnection(url, username, password);
String sql = "insert into marketinfo "
+ " (name, country)" + " values (" + name1 + ", " + city1 + ")";
Statement insertie = conn.prepareStatement(sql);
insertie.executeUpdate(sql);
} catch (Exception e) {
System.out.println(e);
}
return null;
}
My error is "Unknown column 'Danny' in 'field list'" .
In Sql database my table contains id, name and city. I want to pass the id field because that id is incremented automatically.
There's alot going on in that code, and as others have suggested you should break it up. But actually performing the query can be done like this:
public class YourClass {
private static final String SQL = "INSERT INTO marketinfo (name, country) VALUES (?,?)";
public void addMarketInfo(String name, String city) {
try (Connection conn = getConnection();
PreparedStatement stmt = conn.prepareStatement(SQL)) {
stmt.setString(1, name);
stmt.setString(2, city);
stmt.executeUpdate();
} catch (SQLException e) {
// This is fine for debugging, but you probably want to log this or throw an exception
// Depends on how the rest of your application is set up
e.printStackTrace();
}
}
}
All your code creating the connection should most likely get moved to another class, and then called by the getConnection() method as in my example.
If you're using JDBC, PreparedStatements are used ALOT. It's worth looking more more examples on how they are used. Among other benefits, they're really helpful for avoiding string concatenation bugs like your original question.
This is the wrong way to do it. You should learn about PreparedStatement and how to bind values to parameters.
But it's worse than that.
Your method is getConnection, but it's also performing the query. Methods should do one thing well.
You don't close any of your resources. Another bad idea.
You print a stack trace to the console. Better to log it.
You hard wire your connection parameters instead of passing them in.
There's no connection pooling here.
seems you missed inner quotes around var name1 and city1
String sql = "insert into marketinfo "
+ " (name, country)" + " values ('"+ name1 +"', '"+ city1 +"')";
but most important you should use parametrized query instead of string concat .
To fix this you need to quote your variables in the SQL:
String sql = "insert into marketinfo "
+ " (name, country)" + " values ('"+ name1 +"', '"+ city1 +"')";
However, this is awful code, and you should not do it like this.
See here for why not: https://www.acunetix.com/websitesecurity/sql-injection/
As a hit, your sql should look like this:
String sql = "insert into marketinfo "
+ " (name, country)" + " values (:name, :city)";
Then, you use a prepared statement to set the values. Code like this is why websites get all their private information stolen.
String or varchar type should be between two quotes 'some string', but this still not secure so to avoid Syntax errors (Like you have now) or SQL Injection it's better to use PreparedStatement :
String sql = "insert into marketinfo (name, country) values (?, ?)";
try(PreparedStatement insertie = con.prepareStatement(sql);){
insertie.setString(1, name1);
insertie.setString(2, city1);
insertie.executeUpdate();
//...
}
Related
I'm passing my method InsertQuery variables from another method which are entered by the user via Scanner.
How do I fill in the iName, iType etc. into my iQuery so that I can insert them into my DB?
public void InsertQuery (String iName, String iType, int health_Problem, Date date2, String aRemind, String docName, String docType, String docAdress)
{
final String url = "jdbc:mysql://localhost/ehealthdb?serverTimezone=UTC";
final String DBUSER = "root";
final String DBPSWD = "root";
try {
Connection con = DriverManager.getConnection(url,DBUSER,DBPSWD);
Statement stmt = con.createStatement();
String iQuery = "INSERT into appointment"
+ "(ID, PatientID, Insurance_Name, Insurance_Type, Health_Problem, Appointment_Date, Appointment_Remind, Doctor_Name,Doctor_Type,Doctor_Adress)"
+ "values ('1','1',,'Gesetzlich','5','15.01.2020','1 Week','Musterarzt','Hausarzt','Musterstraße')";
stmt.executeUpdate(iQuery);
} catch (Exception e) {
System.out.println("Something went wrong #InsertQuery");
}
}
The easiest approach would probably be to use a PreparedStatement:
public void insertQuery
(String iName, String iType, int healthProblem, Date date2, String aRemind, String docName, String docType, String docAddress)
throws SQLException {
final String url = "jdbc:mysql://localhost/ehealthdb?serverTimezone=UTC";
final String DBUSER = "root";
final String DBPSWD = "root";
try (Connection con = DriverManager.getConnection(url,DBUSER,DBPSWD);
PreparedStatement stmt = con.prepareStatement(
"INSERT into appointment" +
"(ID, PatientID, Insurance_Name, Insurance_Type, Health_Problem, Appointment_Date, Appointment_Remind, Doctor_Name, Doctor_Type, Doctor_Adress) " +
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)")) {
stmt.setString(1, iName);
stmt.setString(2, iType);
stmt.setInt(3, healthProblem);
stmt.setTimestamp(4, new Timestamp(date2.getTime()));
stmt.setString(5, aRemind);
stmt.setString(6, docName);
stmt.setString(7, docType);
stmt.setString(8, docAddress);
stmt.executeUpdate();
}
}
Don't use a statement, use a PreparedStatement. Otherwise, you get hacked.
More generally, JDBC is a tricky beast and not a particularly nice API. For fairly good reasons - it is designed to be the lowest common denominator, and it is more focused on exposing all the bells and whistles of all databases in existence, than in giving you, programmer who wants to interact with a database, a nice experience.
Try JDBC or JOOQ.
Your exception handling is also wrong. If you catch an exception, either handle it, or make sure you throw something. Logging it, (or worse, printing it) definitely does not count. Add throws to your method signature. If that's not possible (and it usually is possible, try that first), throw new RuntimeException("Uncaught", e) is what you want. not e.printStackTrace(), or even worse, what you did: You just tossed out all relevant information. Don't do that.
The recommended approach is to use PreparedStatement which solves the following two important problems apart from many other benefits:
It helps you protect your application from SQL Injection.
You will not have to enclose the text values within single quotes yourself.
Typical usage is as shown below:
String query = "INSERT INTO appointment(ID, PatientID, Insurance_Name, Insurance_Type, Health_Problem) VALUES (?, ?, ?, ?, ?)";
try (PreparedStatement pstmt = con.prepareStatement(query)) {
//...
pstmt.setString(1, id);
pstmt.setString(2, patientId);
pstmt.setString(3, insuranceName);
//...
pstmt.executeUpdate();
} catch(SQLException e) {
e.printStackTrace();
}
Note that for each ?, you will have to use pstmt.setXXX. Another thing you need to understand is that in the method call, pstmt.setString(1, Id), 1 refers to the first ? and not the first column in your table.
Some other important points:
I have used try-with-resources statement which is an easier and recommended way to close the resources after the program is finished with it. Learn more about it from Oracle's tutorial on it.
Always follow Java naming conventions e.g. Insurance_Name should be named as insuranceName.
I used this way and it is working greatly
for iName
public void InsertQuery (String iName, String iType, int health_Problem, Date date2, String aRemind, String docName, String docType, String docAdress)
{
final String url = "jdbc:mysql://localhost/ehealthdb?serverTimezone=UTC";
final String DBUSER = "root";
final String DBPSWD = "root";
try {
Connection con = DriverManager.getConnection(url,DBUSER,DBPSWD);
Statement stmt = con.createStatement();
String iQuery = "INSERT into appointment"
+ "(ID, PatientID, Insurance_Name, Insurance_Type, Health_Problem, Appointment_Date, Appointment_Remind, Doctor_Name,Doctor_Type,Doctor_Adress)"
+ "values ('1','1',,'"+iName+"','5','15.01.2020','1 Week','Musterarzt','Hausarzt','Musterstraße')";
stmt.executeUpdate(iQuery);
} catch (Exception e) {
System.out.println("Something went wrong #InsertQuery");
}
}
So I'm importing information from a .csv file into a database. However I'm having trouble with the user inputted description in the csv file as they contain apostrophes which is breaking the SQL import.
My Import statement is String sqlJob =
"INSERT INTO job (ID, Job_Contact, Internal_Comment, Customer_Name,"
+ " Duration, Job_Location, Job_Completion_Date, Job_Technician,"
+ " Job_Asset, Job_Type, Job_Description) VALUES ('"
+csvRecord.get(i)+"', '"+csvRecord.get(26)+"', '"+csvRecord.get(16)
+"', '"+csvRecord.get(2)+"', '"+csvRecord.get(31)+"', '"+csvRecord.get(27)
+"', '"+csvRecord.get(28)+"', '"+csvRecord.get(29)+"', '"+csvRecord.get(30)
+"', '"+csvRecord.get(33)+"', '"+csvRecord.get(34)+"');";
A simplified form would be
"INSERT INTO job (ID, Description) VALUES ('"
+ csvRecord.get(i) + "', '" + csvRecord.get(34) + "');";
The problem is csvRecord.get(34) will sometimes contain apostrophes. For example "My name's Bob" and that apostrophe in Bob is breaking the surrounding apostrophes that are needed to declare that the value is a string for the SQL.
Is there an easy way to parse the string and add escape characters in front of apostrophes or should I format my original SQL command a different way.
Thanks!
The problem is you are assembling the SQL statement as a String, concatenating the parameter values. This is highly not advisable.
Use PreparedStatements instead that are easier to use. You can pass parameters without any modification and they won't interfere with the correct execution of the SQL statement.
Also as a valuable bonus, your code will be free of SQL Injection problems.
Example from the JDBC Tutorial:
String updateString = "update COFFEES set SALES = ? where COF_NAME = ?";
PreparedStatement updateSales = con.prepareStatement(updateString);
updateSales.setInt(1, numSales);
updateSales.setString(2, coffeeName);
updateSales.executeUpdate();
As you see, the parameters are NOT concatenated into the String, but they will take the place of the ? symbols.
Even if coffeeName has the value "Africa's Best" (apostrophe included) the query will work well.
Use PreparedStatement so you can be in save.
String name = request.getParameter( "ID" );
String message = request.getParameter( "Job_Contact" );
Connection c = null;
try
{
String url = "jdbc:mysql://localhost/**"databasename"**;
String username = "**<Database Login>**";
String password = "**<Database password>**";
**// at the ? section you can add any quantity you need to**
String sql = "insert into **<databasename>**(name, message) values (?, ?)";
c = DriverManager.getConnection( url, username, password );
PreparedStatement pstmt = c.prepareStatement( sql );
pstmt.setString( 1, name );
pstmt.setString( 2, message );
pstmt.executeUpdate();
}
catch( SQLException e )
{
throw new ServletException( e );
}
finally
{
try
{
if( c != null ) c.close();
}
catch( SQLException e )
{
throw new ServletException( e );
}
}
I have compiled my JavaFX application and when I try to take the data from the UI and update the database I get this error:
java.sql.SQLSyntaxErrorException: Lexical Error at line 1 , column 105. Encountered "#" (64) after : ""
at org.apache.derby.client.am.SQLExceptionFactory.getSQLException(Unknown Source)
at org.apache.derby.client.am.ClientStatement.execute(Unknown Source)
at Query.generateOperation(Query.java:45)
at AdminAccount.addAdmin(AdminAccount.java:27)
at Root.lambdaExpression(Root.java:89)
This is the code which is referenced for Query ->
public void generateOperation(String query) {
try {
Statement statement = connection.createStatement();
statement.execute(query) // line raised by compiler
} catch (SQLException e) {
e.printStackTrace();
}
}
This is the code which is referenced for AdminAccount ->
public void addAdmin(String username, String password, String email) {
int id = generateId(); // return random number for id
String values = id + ", " + username + ", " + password + ", " + email;
DB.generateOperation("insert into APP.ADMINDETAILS (ID , USERNAME , PASSWORD , EMAIL) values (" + values + ")"); // DB is the Query object I use to interact with the database . This line is raised by the compiler
}
This is the code which is called by the user interface
submit.setOnAction(e -> {
if (...) {
adminAccount.addAdmin(usernameEntry.getText(), passwordEntry.getText(), emailEntry.getText()) ; // this is the line raised by compiler
}
});
What should I amend to this code so that I don't get the lexical error when parsing the SQL statement. I think there is trouble parsing the email entry as the compiler references the "#" symbol. Should I be using another method for constructing SQL statements?
The correct way of doing things is to NOT concatenate values into a query string. You need to use PreparedStatement, with placeholders for each value you want to set, and then explicitly set each value before you execute.
Given your code, you would need to do something like:
try (PreparedStatement insertStatement = connection.prepareStatement(
"insert into APP.ADMINDETAILS (ID, USERNAME, PASSWORD, EMAIL) values (?, ?, ?, ?)")) {
insertStatement.setInt(1, id);
insertStatement.setString(2, username);
// Do NOT do this in a real application, hash is with a password hash algorithm
insertStatement.setString(3, password);
insertStatement.setString(4, email);
insertStatement.executeUpdate();
}
The question marks in the statement are the placeholders for values, and using the setXXX methods ensures the values are correctly set before execution. This makes your query safe because it will prevent SQL injection.
I'm trying to figure out why this code is throwing an SQL exception. When I run this code it prints "Bad SQL in customer insert ps", which is the message in that inner catch block. I've got multiple prepared statements with SQL inserts like this both in this class and also elsewhere in my application. They're all working fine. I've looked through this one over and over again, and I can't figure out why this one is throwing an exception.
try {
Connection conn = DBconnection.getConnection();
PreparedStatement ps = conn.prepareStatement("SELECT customerId FROM customer WHERE customerName=\"" + name + "\";");
System.out.println(ps.toString());
ResultSet rs = ps.executeQuery();
if (rs.next()) {
customerId = rs.getString("customerId");
}
try {
PreparedStatement customerInsert = DBconnection.getConnection().prepareStatement("INSERT "
+ "INTO customer (customerName, addressId, active, createDate, createdBy, lastUpdate, lastUpdateBy)"
+ "VALUES(\"" + name + "\", " + addressId + ", " + active + ", UTC_TIMESTAMP(), \"" + LogInController.getUserName() + "\", UTC_TIMESTAMP(), \"" + LogInController.getUserName() + "\");");
customerInsert.executeUpdate();
System.out.println(customerInsert.toString());
System.out.println(rs.toString());
} catch (SQLException sq) {
System.out.println("Bad SQL in customer insert ps");
}
} catch (SQLException customerIdException) {
System.out.println("Bad SQL in customer ps");
}
You're using PreparedStatement as though you were using Statement. Don't put the parameters in the SQL, put in placeholder ? marks. Then use the various setXyz methods (setString, setInt, etc.) to fill in the parameters:
PreparedStatement customerInsert = DBconnection.getConnection().prepareStatement(
"INSERT INTO customer (customerName, addressId, active, createDate, createdBy, lastUpdate, lastUpdateBy)" +
"VALUES(?, ?, ?, ?, ?, ?, ?);"
);
customerInsert.setString(1, name);
customerInsert.setInt(2, addressId);
// ...etc. Notice that the parameter indexes start with 1 rather than 0 as you might expect
I would like to add a date value from JXDatePicker into my SQL database, however I'm getting this error when running it:
java.sql.sqldataexception: the syntax of the string representation of a datetime value is incorrect
This is my code:
try {
String url = "jdbc:derby://localhost:1527/Members";
String username = "admin1";
String password = "admin1";
Connection con = DriverManager.getConnection(url, username, password);
Statement stmt = con.createStatement();
String query = "INSERT INTO BOOKING(MEMBERID, NAME, CONTACT, "
+ "EMAILADDRESS, RESERVATIONDATE, RESERVATIONTIME) "
+ "VALUES('"+txtMemberID.getText()+"', '"+txtName.getText()+"', "
+ "'"+txtContact.getText()+"', '"+txtEmail.getText()+"', "
+ "'"+comboDate.getDate()+"', '"+comboTime.getSelectedItem()+"')";
stmt.execute(query);
JOptionPane.showMessageDialog(null, "Booking created");
txtMemberID.setText(null);
txtName.setText(null);
txtContact.setText(null);
txtEmail.setText(null);
comboDate.setDate(null);
comboTime.setSelectedItem("00");
}
catch(SQLException ex) {
JOptionPane.showMessageDialog(null, ex.toString());
}
The datatype specified for the Date attribute in my database is Date.
Thank you.
Your problem is that you're trying to embed a Date value (or a String representation of one) into the INSERT statement. Instead of concatenating variables into the query literal, you should use parameterized SQL through a PreparedStatement. In addition to protecting your code from SQL injection, parameterized statements are re-usable by the database, which means that the DB doesn't need to parse the SQL before each execution -- this is especially important if you're running a large number of queries in a loop.
Another thing that you should take care of, is closing the resources you've opened. In your example code, the Connection and Statement are left open after they are no longer needed. This is easy to fix using the try-with-resources statement, which was introduced in Java 7. The resources declared within the try clause get automatically closed after the statement is executed.
Putting it all together, here's an example of what the modified code could look like:
String query = "INSERT INTO BOOKING(MEMBERID, NAME, CONTACT, "
+ "EMAILADDRESS, RESERVATIONDATE, RESERVATIONTIME) "
+ "VALUES(?, ?, ?, ?, ?, ?)";
try (Connection con = DriverManager.getConnection(url, username, password);
PreparedStatement ps = con.prepareStatement(query)) {
ps.setString(1, txtMemberID.getText());
ps.setString(2, txtName.getText());
ps.setString(3, txtContact.getText());
ps.setString(4, txtEmail.getText());
ps.setDate(5, new java.sql.Date(comboDate.getDate().getTime()));
ps.setString(6, comboTime.getSelectedItem().toString());
ps.executeUpdate();
JOptionPane.showMessageDialog(null, "Booking created");
/*clear the UI components etc.*/
} catch(SQLException ex) {
JOptionPane.showMessageDialog(null, ex.toString(), JOptionPane.ERROR_MESSAGE);
}