I'm new in MySQL. I have a problem here. I have a query of inserting a data to the database but my problem is how to avoid duplication of records.
So here are my codes:
private void btnSaveGuestActionPerformed(java.awt.event.ActionEvent evt) {
String name = nameTextField.getText();
String address = addressTextField.getText();
String nationality = nationalityTextField.getText();
String com = comNameTextField.getText();
String email = emailTextField.getText();
String contact = contactNoTextField.getText();
if( name.isEmpty() || address .isEmpty() || nationality.isEmpty() || com.isEmpty() || email.isEmpty() || contact.isEmpty() ){
JOptionPane.showMessageDialog(null, "Please input any of the following.");
}
else{
try{
String query = "INSERT INTO guestlist (Name, address, Nationality, CompanyName, email, contactNo)"
+ "VALUES ?, ?, ?, ?, ?, ?";
PreparedStatement pst = conn.prepareStatement(query);
ResultSet rs = pst.executeQuery("SELECT * FROM guestlist");
pst.setString(1, nameTextField.getText());
pst.setString(2, addressTextField.getText());
pst.setString(3, nationalityTextField.getText());
pst.setString(4, comNameTextField.getText());
pst.setString(5, emailTextField.getText());
pst.setString(6, contactNoTextField.getText());
pst.execute();
pst.close();
}catch(Exception e){
JOptionPane.showMessageDialog(null, e);
}
}
}
Sorry for my ignorance here but I'm very new to DBMS. I hope you would answer my question. Thanks a lot and have a nice day! :)
In databases in general, you prevent duplication of records by creating unique indexes or constraints. Actually, these are basically the same thing (unique constraints are implemented using unique indexes).
So, if you wanted email to be unique, you can do:
create unique index unq_guestlist_email on guestlist(email);
Of course, you can specify multiple columns, so the combination of all the columns has to be unique.
Then, if you try to insert a record that is already there, the database will return an error. (You can ignore this error in various ways.)
in mysql you can use unique constrainst (http://www.w3schools.com/sql/sql_unique.asp).
But, if also you want validate insert data without errors in java, when you insert registers you can validate the columns that are part of your unique value, not to be repeated.
Related
I have this code that adds Product to Products table in the database but it is adding more than one row.
Here's the code:
public int addProduct(Products product, String supplierName) {
//find a product
String checkAllProducts = "SELECT * FROM products WHERE product_name = ?";
//Insert product and supplier id where supplier exist in suppliers table sql statement
String insertSql = "INSERT INTO products (product_name, product_type, supplier_id, number_of_stocks, price_per_unit, packaging_type) SELECT ?,?,suppliers.supplier_id,?,?,? FROM suppliers WHERE suppliers.supplier_name = ?";
//Get connection
Connection conn = DbUtil.getConnection();
//Resultset for checking existing products
ResultSet resultSet = null;
int inserted = 0;
try {
//Prepare check all products statement
allProducts = conn.prepareStatement(checkAllProducts);
allProducts.setString(1, product.getProductName());
resultSet = allProducts.executeQuery();
//If doesn't exist in products table
if (!resultSet.next()) {
//Prepare insert statement
addProduct = conn.prepareStatement(insertSql);
//Get product parameter's data
addProduct.setString(1, product.getProductName());
addProduct.setString(2, product.getProductType());
addProduct.setInt(3, product.getNumberOfStocks());
addProduct.setBigDecimal(4, product.getPricePerUnit());
addProduct.setString(5, product.getPackagingType());
addProduct.setString(6, supplierName);
//Confirm insert
int confirmation = JOptionPane.showConfirmDialog(null, "Are you sure you want to insert this product?", "Insert Confirm", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
if (confirmation == JOptionPane.YES_OPTION) {
//execute insert
inserted = addProduct.executeUpdate();
}
}//Else don't insert and show error messages.
else {
JOptionPane.showMessageDialog(null, "Product already exists.", "Invalid insert.", JOptionPane.ERROR_MESSAGE);
}
} catch (SQLException ex) {
Logger.getLogger(ProductDAO.class.getName()).log(Level.SEVERE, null, ex);
} finally {
DbUtil.close(conn, allProducts, resultSet);
DbUtil.close(conn, addProduct, resultSet);
}
return inserted;
}
As you can see in the code above, I'm checking if a product doesn't exist in the table then insert with confirmation. It's successfully adding but it's adding more than one row. For example, assume that I have initialised the productDao object and I test it out in this way: productDAO.addProduct(new Products("Hotdogs", "Full", 55, new BigDecimal(0.30), "Box"), "Wing Yip");. After doing that, it inserted 14 of these as you can see in the image's link below;
14 Duplicate Rows
Does anyone know why this is happening? Please let me know thanks.
The second part of your insert statement is a select statement:
SELECT
?, ?,
suppliers.supplier_id,
?, ?, ?
FROM products, suppliers
WHERE
products.supplier_id = suppliers.supplier_id
AND suppliers.supplier_name = ?
This has the ability to select all records that have that supplier name and which appear in both tables. Evidently that supplier has 14 products, so that is how many new records are inserted.
To fix this remove the implicit JOIN. It isn't needed for the supplier_id lookup.
INSERT INTO products (
product_name,
product_type,
supplier_id,
number_of_stocks,
price_per_unit,
packaging_type
) SELECT
?, ?,
suppliers.supplier_id,
?, ?, ?
FROM suppliers
WHERE suppliers.supplier_name = ?
Thanks to #Scary Wombat and #4castle for the help. What I did now is to create a separate statement and added more code as you can see below.
//find supplier
String checkSupplierQuery = "SELECT products.supplier_id FROM products, suppliers WHERE products.supplier_id = suppliers.supplier_id AND suppliers.supplier_name = ? ";
//Prepare check supplier statement
PreparedStatement checkSupplier = conn.prepareStatement(checkSupplierQuery);
checkSupplier.setString(1, supplierName);
resultSet = checkSupplier.executeQuery();
String supplier = "";
while (resultSet.next()) {
supplier = resultSet.getString("products.supplier_id");
}
This solved my problem but I'm trying with INSERT INTO SELECT statement which it didn't work as I expected. Thanks again for those who helped me. :-)
I'm making a java program using Netbeans, I want to insert data into my "data supplier" table. I cannot post my JFrame picture as my reputation is not enough.
I've set "Kode Supplier" as PRIMARY_KEY and NOT_NULL, and allow the rest to be NULL
In the code below, telpField and hpField will show an error if I didn't type anything in it's textbox
Is it possible because it is INT type?
This is my code:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
try{
String sql = "INSERT INTO datasupplier (`Kode Supplier`, `Nama Supplier`, `Contact Person`,"
+ " `Alamat`, `NoTelp`, `NoHP`, `Bank Account`, `A/C Info`, `A.N.`, `Keterangan`)"
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
pst = conn.prepareStatement(sql);
//Get value from the textboxes
pst.setString(1, codeField.getText());
pst.setString(2, nameField.getText());
pst.setString(3, cpField.getText());
pst.setString(4, addressField.getText());
pst.setString(5, telpField.getText());
pst.setString(6, hpField.getText());
pst.setString(7, bankField.getText());
pst.setString(8, acField.getText());
pst.setString(9,anField.getText());
pst.setString(10, ketField.getText());
pst.execute();
JOptionPane.showMessageDialog(null, "Tabel Telah Di Update");
}
catch(Exception e){
JOptionPane.showMessageDialog(null, "Data Invalid");
}
DataSupplierTable();
}
//Set JComboBox First Diplayed Item
private void setTableCombo(){
tableCombo.setSelectedItem("Data Supplier");
}
//Bind the table and databarang.datasupplier
private void DataSupplierTable(){
String sql = "SELECT * FROM datasupplier";
try{
pst = conn.prepareStatement(sql);
rs = pst.executeQuery();
supplierTable.setModel(DbUtils.resultSetToTableModel(rs));
supplierTable.isCellEditable(0,0);
}catch(Exception e){
}
}
This is my table (using MySQL Community Server Database, InnoDB)
Kode Supplier INT(30) PRIMARY_KEY NOT_NULL,
Nama Supplier CHAR(45),
Contact Person VARCHAR(20),
Alamat VARCHAR(45),
NoTelp INT(30),
NoHP INT(30),
Bank Account CHAR(30),
A/C Info VARCHAR(45),
A.N. CHAR(45),
Keterangan VARCHAR(100)
Yes, this is because your Kode Supplier, NoTelp and NoHP columns are integer columns. For integer columns, you should be using the setInt method rather than setString.
But the setInt method only accepts an primitive int for the value of the field. So the first thing you'll need to do is convert the String value of the field to int. This is done with a statement like:
int telpVal = Integer.parseInt(telpField.getText());
But this means you have to decide what to do in the following cases:
The user entered a value in the GUI field which is not an integer, like ABC, 1.2 or 123456789123456789. If that happens, then the statement I gave would throw a NumberFormatException.
You could decide to display an error message and not call the insert statement when this happens. Or you may decide to insert a NULL. Or you may decide to insert a default value like 0.
The user entered no value in the GUI field - it is an empty string. Note that there is a difference between an empty string and a null. You may decide to handle this case the same way you handle the previous one. Or you may decide to handle it separately.
Suppose you decide that:
If the user entered an illegal number, you'll show an error message and will not insert the row.
If the user did not enter a value and left the field empty, you want to insert a null.
Then you'll need to handle it like this:
String fieldName;
try {
String sql = "INSERT INTO datasupplier (`Kode Supplier`, `Nama Supplier`, `Contact Person`,"
+ " `Alamat`, `NoTelp`, `NoHP`, `Bank Account`, `A/C Info`, `A.N.`, `Keterangan`)"
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
pst = conn.prepareStatement(sql);
//Get value from the textboxes
// Kode supplier is integer, but is not allowed to be null
// so don't handle an empty field case, just let parseInt
// throw the exception.
fieldName = "Kode Supplier";
pst.setInt(1, Integer.parseInt(codeField.getText()));
pst.setString(2, nameField.getText());
pst.setString(3, cpField.getText());
pst.setString(4, addressField.getText());
// Handle the NoTelp field - if empty, insert null. If not,
// parse the number. Handle illegal number values in catch.
fieldName = "NoTelp";
if ( telpField.getText().isEmpty() ) {
pst.setNull(5, Types.INTEGER);
} else {
pst.setInt(5, Integer.parseInt(telpField.getText());
}
// Handle the NoHP field
fieldName = "NoHP";
if ( hpField.getText().isEmpty() ) {
pst.setNull(6, Types.INTEGER);
} else {
pst.setInt(6, Integer.parseInt(hpField.getText());
}
pst.setString(7, bankField.getText());
pst.setString(8, acField.getText());
pst.setString(9,anField.getText());
pst.setString(10, ketField.getText());
pst.executeUpdate();
JOptionPane.showMessageDialog(null, "Tabel Telah Di Update");
}
catch (NumberFormatException nfe) {
// Display error to the user
JOptionPane.showMessageDialog(null, "Invalid number in field " + fieldName)
}
catch(SQLException e){
JOptionPane.showMessageDialog(null, "Data Invalid");
}
Notes
I handled Kode Supplier differently than NoTelp and NoHP because it is not allowed to be null. If the field is empty, NumberFormatException will be thrown from parseInt and will go to the catch part.
I kept a fieldName variable which I set before trying each parseInt. If an exception is thrown, we can use it for displaying the specific field where the error occurred in the dialog box. You can do other things like keeping the JTextField that you are currently handling, and in the catch highlighting it and giving it focus.
When you use setNull, you have to pass the type of the field as the second parameter. All the types are in java.sql.Types. So remember to import java.sql.Types.
Don't use a catch (Exception e). It's too broad. In this case we expect only NumberFormatException and SQLException. If any other exception happens, especially a runtime exception, you want to know about it and see the stack trace. If you have catch (Exception e) you'll just get a dialog box that says "Data Invalid" and that is not helpful. "Catch all" is bad.
Im using a PostgreSQL database, and when i'm trying to insert the data, it gives me an error problemDatabase error: ERROR syntax error at or near ":" Position 206.
Here is a code for insert query :
public static Model_Customer Insert(String FName, String LName, String Registration, String Make, String Model, String Engine, String Year, String Mileage, String Type, String Date, String Time) throws Exception {
try{
Statement stmt = Model_Customer.conn.createStatement();
ResultSet rs = stmt.executeQuery("INSERT INTO appointment (fname, lname, registration, make, model, engine, year, mileage, type, date, time) VALUES ("+FName+",'"+LName+"','"+Registration+"','"+Make+"','"+Model+"','"+Engine+"','"+Year+"','"+Mileage+"','"+Type+"','"+Date+"',"+Time+") RETURNING appointmentid");
if(rs.next())
return Model_Customer.QueryID(rs.getInt(1));
}catch(Exception e){
throw new Database_Exception(e.getMessage());
}
return null;
}
In Debug it goes okay to the executeQuery and straight after it, it goes to the catch exception and gives an error. Table and columns in the database are there. There's no ":" anywhere in the code except the messages, so im not sure why it goes like this.
Thanks for your answer Joop Eggen I have used you way and had to add
stmt.executeUpdate();
Worked like a charm! Thanks!
PreparedStatement stmt = conn.prepareStatement(
"INSERT INTO appointment (fname, lname, registration, make, model, "
+ "engine, year, mileage, type, \"date\", \"time\") "
+ "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
stmt.setInt(1, FName);
stmt.setString(2, LName);
stmt.setString(3, Registration);
...
int updateCount = stmt.executeUpdate(Statement.RETURN_GENERATED_KEYS);
ResultSet rs = stmt.getGeneratedKeys();
if(rs.next())
return Model_Customer.QueryID(rs.getInt(1));
JDBC offers a database engine independent way to retrieve the generated keys: a result set of inserted rows with the generated keys per row.
RETURN_GENERATED_KEYS is probably not needed. Some field names might be reserved key words, which then need double quotes around them.
About recommending PreparedStatement:
The first remark on every ...+var+... construed statement, will be: use a prepared statement with ... ? .... There are two very important reasons (besides the efficiency of a PreparedStatemen and using BLOBs):
SQL injection, see this;
you can leave out the apostrophes ('), and escaping of apostrophe, backslash etcetera is done for you, and you can pass typesafe parameters (int, java.sql.Date).
I have created a small 3 tier program, consisting of : front end -> servlet -> database.
Front end I enter some details into a form. They are passed to a servlet, which will render some HTML and display the values entered into the form, while also calling a class DatabaseHelper. The DatabaseHelper then connects and inserts these same values into a table.
I know the values are being passed to the servlet class ok, as they are being displayed in the HTML. So the problem must lie within the prepared statement. Problem is, I cannot see any fault with the statement itself. When I query the table itself, there is no data there.
Database connectivity is functional, as I can insert values into a database using hardcoded statements, just not a prepared statement.
Here is a look at the statement Im using. Any advice is much appreciated.
public void addRegisterDetails(String name, String email, String country, String password, ){
try{
String driver = "com.mysql.jdbc.Driver";
Class.forName(driver).newInstance();
// Make db connection
con = DriverManager.getConnection(url, USERNAME, PASSWORD);
st = con.createStatement();
String query = " INSERT INTO user_information (name, email, country, password)" + " VALUES (?, ?, ?, ?)";
PreparedStatement preparedStmt = con.prepareStatement(query);
preparedStmt.setString (1, name);
preparedStmt.setString (2, email);
preparedStmt.setString (3, country);
preparedStmt.setString (4, password);
preparedStmt.execute();
}catch(ClassNotFoundException ex) {
System.out.println(ex);
}catch(Exception e){
e.printStackTrace();
}
}
Table definition
id| name | email | country | password
all VARCHAR except the id, which is type INT.
You should invoke the method executeUpdate() on the statement object.
Also, I don't see any call to commit the data, any transaction handling. It's fine if you skipped that piece of code for the purpose of this question; otherwise it's quite an important step ( commit if all goes well, rollback for exception scenarios)
Use executeUpdate for database write operations:
preparedStmt.executeUpdate();
Answer: The database ID was not set to auto increment. For some reason this does not allow you to then insert data to table. Thanks to ChadNC for pointing this out.
Also, why st = con.createStatement();?
And why do you have a leading space in your query?
String query = " INSERT INTO user_information (name, email, country, password)"
+ " VALUES (?, ?, ?, ?)";
This leading space may or may not matter...
Lastly, you should be closing your connection when you're through with it, using try-with-resources or a finally block.
Hi I am trying insert data into the database using prepared statement but I am getting syntax error could u please help
public boolean SignUp(String last_name, String first_name,String email, String password,String confirm_password,String phone){
Connect connect = new Connect();
Connection conn = connect.Connection();
java.sql.PreparedStatement preparedStatement = null;
//NULL is the column for auto increment
String insertQuery = "INSERT INTO users VALUES (NULL, ?, ?, ?, ?, ?, ?)";
preparedStatement = conn.prepareStatement(insertQuery);
preparedStatement.setString(1, last_name);
preparedStatement.setString(2, first_name);
preparedStatement.setString(3, email);
preparedStatement.setString(4, password);
preparedStatement.setString(5, confirm_password);
preparedStatement.setString(6, phone);
int rs = preparedStatement.executeUpdate(insertQuery);
conn.close();
}
here is the error message
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 '?, ?, ?, ?, ?, ?)' at line 1
I found the answer :)
Use preparedStatement.execute() instead of executeUpdate(sql). You have already set the sql and params - the new setting in executeUpdate(sql) overrides the bind.
You should change the statement to list the columns explicitly, and drop NULL from the list of values.
String insertQuery = "INSERT INTO users"
+ " (last_name, first_name, email, password, confirm_password, phone)"
+ " VALUES(?,?,?,?,?,?)";
This way your insert statement is no longer dependent on the order of columns in your users table, and is also immune to addition of columns to the table.
Note that although this design is probably OK for a toy or an education system, but in a real production system storing password in a table is very dangerous. Storing confirm_password is rather unusual, too: normally your system checks that password is the same as confirm_password, and then inserts a salted password hash and a salt into the table.
Just a guess, not I'm not certain. But if one of the fields is autoincrement, then I don't think you need to insert it. Try taking out that NULL....