I have a table TotalSales on my database with columns Date(Primary) and Sales. I send query thru my Java Program.
I want to add a row if Date row not exists, and if Date row exists, the value on Sales will be updated. On update, the new value on Sales will be 'current value on Sales' + 'the value of variable totalBill'.
Lets say before execution: row under Sales = 0,
after execution: row under Sales = Sales + totalBill;
I tried this code:
String query = "INSERT INTO TotalSales (Date, Sales) VALUES(date, totalBill)
ON DUPLICATE KEY UPDATE Sales= VALUES(Sales)+VALUES(totalBill)";
st = con.prepareStatement(query);
st.execute();
But doesn't work:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'totalBill' in 'field list'
Can anyone help?
You need to take advantage of the parameterised nature of PreparedStatements and bind the values you want to apply before you execute the statement, something like...
String query = "INSERT INTO TotalSales (Date, Sales) VALUES(?, ?)
ON DUPLICATE KEY UPDATE Sales= VALUES(Sales)+?";
st = con.prepareStatement(query);
st.setDate(1, date);
st.setLong(2, totalBill);
st.setLong(3, totalBill);
for example
Take a look at Using Prepared Statements for more details
You are not appending the variable to your insert query, rather simply using a string. So change this:
String query = "INSERT INTO TotalSales (Date, Sales) VALUES(date, totalBill)
ON DUPLICATE KEY UPDATE Sales= VALUES(Sales)+VALUES(totalBill)";
to
String query = "INSERT INTO TotalSales (Date, Sales) VALUES(" + date + "," + totalBill + ")
ON DUPLICATE KEY UPDATE Sales= VALUES(Sales)+VALUES(totalBill)";
ADVICE: But for this case, you should learn to use PreparedStatement
Related
ok, I am a newbie. I have two ArrayList and I want to insert data from the arralylist to table. one arraylist is for the table parameters to insert and other arraylist for inserting the values of the table.
I have tried searching if there was a dynamic way to insert but could not find any.
ArrayList<String> list= new ArrayList<>();
ArrayList<String> values= new ArrayList<>();
list.add("userid");
list.add("name");
list.add("email");
values.add(userID);
values.add(name);
values.add(email);
String sql = "insert into users (" + list + ") values( " + values + ")";
stmt.executeUpdate(sql);
I want to insert the data into the table. but parameters like userid should be in ''(quotes) and name should be in ''(quotes). but they are not converted automatically. is there any other way to do the same task?
IS there any way to get the data from JSON and insert into tables locally?
You should not not concatenate values like that into a SQL String. Use a PreparedStatement instead:
String sql = "insert into users (userid, name, email) values (?,?,?)";
PreparedStatement pstmt = connection.prepareStatement(sql);
The preferred way to insert multiple rows, is to use batching
for (int i=0; i < values.size(); i++) {
pstmt.setString(i+1, values.get(i);
}
pstmt.executeUpdate();
Passing a value for a column name userid as a String seems to be wrong to begin with. Usually those are stored as integers.
You can use String.join method to compose the query:
String sql = "insert into users (" + String.join(", ", list) + ") values( '" + String.join("', '", values) + "')";
But such by-hand sql composing from raw Strings is dangerous and can be vulnerable to injection attacks. I suggest using other solutions like orm.
I'm trying to insert values into a table (inquiry) the first value is of type Date , and I'm getting an SQL error SQL State S1009. what is the proper way to convert the date , what am I doing wrong?
String sqlStatement = "INSERT INTO inquiry (INQUIRY_DATE,INQUIRY_NOTE,INQUIRER_ID,PROGRAM_ID,CLASS_ID,CORPORATE_ID)\n"
+ "VALUES (?,?,?,?);";
ps = con.prepareStatement(sqlStatement);
java.sql.Date sDate = new java.sql.Date(inquiry.getInquiryDate().getTime());
int parameterIndex = 1;
ps.setDate(parameterIndex, sDate);
ps.setString(parameterIndex++, inquiry.getInquiryNote());
ps.setInt(parameterIndex++, inquiry.getInquirer().getInquirerID());
ps.setInt(parameterIndex++, inquiry.getProgramID());
ps.setInt(parameterIndex++, inquiry.getClassProgramID());
ps.setInt(parameterIndex++, 1);
sqlStatement = "INSERT INTO inquiry (INQUIRY_DATE,INQUIRY_NOTE,INQUIRER_ID,PROGRAM_ID,CLASS_ID,CORPORATE_ID)\n"
+ "VALUES (?,?,?,?);";
The parameterized query doesn't have enough ?, you queried 6 columns with 2 ? missing, it should be VALUES (?,?,?,?,?,?); ? are used for holding the places for your setXXX() column values
i need some solution from my foreign key in inserting a FK ID the problem is when i insert the ID, and the Payment it will insert first Customer_ID and the second is default to null value and on next column it will set to the inserted and the other one is null here's my code
pStmt2 = conn.prepareStatement("insert into Audittrail_tbl (Customer_ID) values ((Select Name_ID from Customer_tbl where FName ='"+txtFName.getText()+"' and LName = '"+txtLName.getText()+"'))");
pStmt2 = conn.prepareStatement("insert into Audittrail_tbl (Payment) values ('"+txtPayment.getText()+"')");
pStmt2.executeUpdate();
Your code should be:
String sql = "insert into Audittrail_tbl (Customer_ID, Payment)" +
" select Name_ID, ?" +
" from Customer_tbl" +
" where FName = ?" +
" and LName = ?";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, txtPayment.getText());
stmt.setString(2, txtFName.getText());
stmt.setString(3, txtLName.getText());
stmt.executeUpdate();
}
Or better yet, if Payment is an amount column:
// Using BigDecimal
stmt.setBigDecimal(1, new BigDecimal(txtPayment.getText()));
// Using Double
stmt.setDouble(1, Double.parseDouble(txtPayment.getText()));
Since that will parse the text to number in Java code, where you can better handle parse errors.
Note: Using insert-from-select, instead of insert-values with a subquery, will allow you to select multiple columns from Customer_tbl if needed.
You're doing two inserts, which creates two records. if you want to update the record created by the first query, you need to UPDATE for the second query instead.
And why use two queries? Why not
pStmt2 = conn.prepareStatement("
insert into Audittrail_tbl (Customer_ID, Payment)
values (
(Select Name_ID from Customer_tbl where FName ='"+txtFName.getText()+"' and LName = '"+txtLName.getText()+"'),
'"+txtPayment.getText()+"')");)");
Of course, that won't work as-is (I'm too lazy to check quote/bracket matching), but should give you the general idea.
I want to use several times the same values.
If I use in dbForge for MySQL next query,
SET #v1 = 123, #v2='2014-04-11', #v3 = 'user1', #v4='title1';
INSERT INTO test_table (TID, CREATED, OWNER, TITLE)
VALUES (#v1,#v2,#v3,#v4)
ON DUPLICATE KEY UPDATE
CREATED=#v2, OWNER=#v3, TITLE=#v4
it correctly executes, but in Java, when I use code
final String dbQuerry = "SET #v1 = %s, #v2='%s', #v3 = '%s', #v4='%s';\n"+
"INSERT INTO test_table (TID, CREATED, OWNER, TITLE)\n" +
"VALUES (#v1,#v2,#v3,#v4)\n" +
"ON DUPLICATE KEY UPDATE\n" +
"CREATED=#v2, OWNER=#v3, TITLE=#v4";
String currentQuerry = String.format(dbQuerry, t.getParam("ID"),
t.getParam("Date"),
t.getParam("User"),
t.getParam("Title"));
mDBStatement.execute(currentQuerry);
I have an exception
SQL Exception: 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 'INSERT INTO test_table (TID, CREATED, OWNER, TITLE) VALUES
(#v1,#v2,#v3,#v4) ON ' at line 2
I can use something like this
final String dbQuerry = "INSERT INTO test_table (TID, CREATED, OWNER, TITLE)\n" +
"VALUES (?,?,?,?)\n" +
"ON DUPLICATE KEY UPDATE\n" +
"CREATED=?, OWNER=?, TITLE=?";
PreparedStatement st = mDBConnection.prepareStatement(dbQuerry);
st.setInt(1, Integer.valueOf(t.getParam("ID")));
st.setString(2, t.getParam("Date"));
st.setString(5, t.getParam("Date"));
st.setString(3, t.getParam("User"));
st.setString(6, t.getParam("User"));
st.setString(4, t.getParam("Title"));
st.setString(7, t.getParam("Title"));
But it looks ugly.
Is there is a way to solve this problem?
One option is to use the special VALUES() function to reference the value that would have been inserted into a column, if the INSERT had succeeded, like this:
...
ON DUPLICATE KEY
UPDATE CREATED = VALUES(CREATED)
, OWNER = VALUES(ONWER)
, TITLE = VALUES(TITLE)
The latter form in your example is preferred, using placeholders for the bind variables. What's ugly is having to supply the same value twice.
I'd recommend something like this:
final String dbQuerry = "INSERT INTO test_table (TID,CREATED,OWNER,TITLE)\n" +
" VALUES (?,?,?, ?)\n" +
" ON DUPLICATE KEY UPDATE\n" +
" CREATED=VALUES(CREATED), OWNER=VALUES(OWNER), TITLE=VALUES(TITLE)";
PreparedStatement st = mDBConnection.prepareStatement(dbQuerry);
st.setInt(1, Integer.valueOf(t.getParam("ID")));
st.setString(2, t.getParam("Date"));
st.setString(3, t.getParam("User"));
st.setString(4, t.getParam("Title"));
And that's not ugly. That's the normative pattern.
Using the special VALUES() function is especially useful if we're upserting more than one row, either with a VALUES clause e.g.
INSERT INTO fee (fi, fo, fum)
VALUES
(1,'doo','dah'),(2,'menom','menah'),(3,'buhdeep','uhdeepee')
ON DUPLICATE KEY
UPDATE fo = VALUES(fo)
, fum = VALUES(fum)
Or, with an INSERT ... SELECT form:
INSERT INTO fee (fi, fo, fum)
SELECT t.ay, t.bee, t.cee FROM sometable t
ON DUPLICATE KEY
UPDATE fo = VALUES(fo)
, fum = VALUES(fum)
BTW... the error being returned from the first form is the type of error we'd expect if allowMultiQueries=true is not included in the connect string. Note that enabling multiple queries per execution effectively disables a security feature.
Consider carefully the SQL text that would be generated and sent to the database with some carefully crafted values:
val = "foo'; DROP TABLE students; --"
Using a prepared statement (with static SQL text with placeholder for bind variables, as in the example above) prevents this mode of SQL injection. And disallowing multiple statements in a single execution is another way to thwart SQL injection attacks.
I believe the # variables are used in stored procedures only...
Either you define a stored procedure or you can use the second option :
final String dbQuerry = "INSERT INTO test_table (TID, CREATED, OWNER, TITLE)\n" +
"VALUES (?,?,?,?)\n" +
"ON DUPLICATE KEY UPDATE\n" +
"CREATED=?, OWNER=?, TITLE=?";
PreparedStatement st = mDBConnection.prepareStatement(dbQuerry);
st.setInt(1, Integer.valueOf(t.getParam("ID")));
st.setString(2, t.getParam("Date"));
st.setString(5, t.getParam("Date"));
st.setString(3, t.getParam("User"));
st.setString(6, t.getParam("User"));
st.setString(4, t.getParam("Title"));
st.setString(7, t.getParam("Title"));
I'm supposed to add data from my csv file into my database. I have no problem adding data into the database, however, I have a situation where my java program has to add new values or update current values into the database, say under my column "date". When a new data is not identified in my current database, it would be added. However, under the same row, there's a column called "demand". If the date is the same but the demand is different. It would have to be updated. At the moment, my script can only retrieve the data line by line from mysql and compare with the data collected from the csv file. When the date is different, it can add the data into a new row. The problem is that the java program that I created can only read line by line from the beginning. I would have a repetition of data because when it start comparing from the earliest data to the latest. For example, my earliest date is 01 jan and it is compared to my csv data say 31 jan. However, my later entries has a 31 jan already stored. But my java program continue to add this data in because it compared from the beginning. I will explain in greater detail if you need more information.
public void readDataBase(int val, String d1, String d2, String d3, String d4 ) throws Exception {
try {
Class.forName("com.mysql.jdbc.Driver");
connect = DriverManager.getConnection("jdbc:mysql://localhost/testdb?"
+ "user=root&password=");
statement = connect.createStatement();
resultSet = statement.executeQuery("SELECT COUNT(*) FROM testdb.amg");
while (resultSet.next()) {
total = resultSet.getInt(1);
}
resultSet = statement.executeQuery("select * from testdb.amg");
try{
int id;
String Date,Demand;
while (resultSet.next()) {
id = resultSet.getInt("id");
Date = resultSet.getString("Date");
Demand = resultSet.getString("Demand");
System.out.println("total: " + total);
System.out.println("d4: " + d4);
if (!Date.equals(d1) && !Demand.equals(d3))
{
int val1 = total +1;
preparedStatement = connect
.prepareStatement("insert into testdb.amg values (?, ? ?)");
preparedStatement.setInt(1, val1);
preparedStatement.setString(2, d1);
preparedStatement.setString(3, d3);
preparedStatement.executeUpdate();
System.out.println("UpdatedII");
}
Identify the distinct columns in your database (date + demand + whatever_is_distinct ) and define a UNIQUE constraint on that combination.
By doing that ,during insertion, if there is any Constraint Violation exception that gets thrown , update that record or else the record gets inserted.
As Rocky said, define the unique key on the table. Since the database is MySQL, you can achieve what you want by simple query with INSERT... ON DUPLICATE KEY UPDATE ... INSERT ... ON DUPLICATE KEY UPDATE Syntax
In your case it can be
insert into testdb.amg values (?, ? ?) on duplicate key update <update fields here>
So the final query shall be
"insert into testdb.amg values (?, ?, ?) on duplicate key update Demand=?"
and add
preparedStatement.setString(4, d3);