Is this the correct syntax for a prepared statement in java:
INSERT INTO table (id, version, data)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE
data = IF(version > values(version), data, values(data)),
version = IF(version > values(version), version, values(version))
I am looking for the best way to insert or update millions of rows from within a for-loop in java taking advantage of PreparedStatement's addBatch.
If the SQL statement is correct, you need to wrap it as follows:
String sql = ...
PreparedStatement prep;
prep = conn.prepareStatement(sql);
prep.setInt(1, x);
prep.setString(2, y);
prep.setString(3, z);
prep.execute();
To use addBatch, use:
String sql = ...
PreparedStatement prep;
prep = conn.prepareStatement(sql);
for (...) {
prep.setInt(1, x);
prep.setString(2, y);
prep.setString(3, z);
prep.addBatch();
}
prep.execute();
Related
I am working on a project and I want to insert into 2 different tables, so I wrote those 2 queries (query1, query2), when i run the program with just one query i don't get any exceptions but when executing together i have a bunch of exceptions, i used preparedStatement execute() and didn't work
note : im not very experienced please explain easily
private void loadBusesToDB() throws SQLException{
Connection connection = connect();
String query = "INSERT INTO Bus (nomLigne, Marque, Matricule, Capacite)"
+ "VALUES (?, ?, ?, ?)";
String query2 = "INSERT INTO Lignes (nomLigne, Sntv Depart, SNTV Arrive, prix)"
+ "VALUES (?, ?, ?, ?)";
PreparedStatement ps = null;
PreparedStatement ps2 = null;
try {
ps = connection.prepareStatement(query);
ps2 = connection.prepareStatement(query2);
for(Bus bus : Bus.buses){
ps.setString(1, bus.getNomLigne());
ps.setString(2, bus.getMarque());
ps.setString(3, bus.getMatricule());
ps.setInt(4, bus.getCapacite());
ps.addBatch(); // THE INSERT HAPPENS HERE
}
ps.executeBatch();
for(Lignes ligne : Lignes.lignes){
ps2.setString(1, ligne.getNomLigne());
ps2.setString(2, ligne.getDepart());
ps2.setString(3, ligne.getArrive());
ps2.setFloat(4, ligne.getPrix());
ps2.addBatch(); // THE INSERT HAPPENS HERE
}
ps2.executeBatch();
} catch (SQLException ex) {
ex.printStackTrace();
System.out.println("ERROR HERE");
throw ex;
}finally{
ps.close();
ps2.close();
connection.close();
}
}
Error:
net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::3.0.2 user lacks privilege or object not found: SNTV
at net.ucanaccess.jdbc.UcanaccessConnection.prepareStatement(UcanaccessConnection.java:509)
at sntv.MainMenuController.loadBusesToDB(MainMenuController.java:135)
at sntv.MainMenuController.initialize(MainMenuController.java:277)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
As #uaraven points out, you have a syntax error regarding column names in the second query. In SQL, any identifier (including table, column, stored procedures, functions, etc.) with spaces or special characters/symbols in their names or names match reserved words need to be escaped when referenced in any clause (SELECT,FROM, JOIN, WHERE, GROUP BY, HAVING, ORDER BY ).
Now, different RDBMS's handle such escaping differently. Consider the following depending on your database. SQLite may be the only RDBMS that includes all.
Double Quotes (ANSI-SQL standard) (Oracle, DB2, Postgres, RedShift, Teradata, SQLite, with added rules of capitalization for some; SQL Server/MySQL does support with mode changes)
String query2 = "INSERT INTO Lignes (nomLigne, \"SNTV DEPART\", \"SNTV ARRIVE\", prix)"
+ " VALUES (?, ?, ?, ?)";
Square Brackets (SQL Server, Sybase, SQLite, MS Access)
String query2 = "INSERT INTO Lignes (nomLigne, [Sntv Depart], [SNTV Arrive], prix)"
+ " VALUES (?, ?, ?, ?)";
Backticks (MySQL, MariaDB, Google BigQuery Standard SQL, SQLite, MS Access)
String query2 = "INSERT INTO Lignes (nomLigne, `Sntv Depart`, `SNTV Arrive`, prix)"
+ " VALUES (?, ?, ?, ?)";
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);
}
I bumped into this problem and i cannot figure out what is wrong with this code. I use jdbc and ms managment system for the databse and its connection.
code:
try {
//create user
preparedStatement = conn.prepareStatement("INSERT INTO Users(name, pass, type) VALUES (nick=?,pass=?,type=?)",
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
preparedStatement.setString(1, user.getNickName());
preparedStatement.setString(2, user.getPassword());
preparedStatement.setInt(3, type);
rs = preparedStatement.executeQuery();
System.out.println(rs.toString());
catch (Exception e) {
System.out.println("Exception: " + e);
}
error:
Exception: com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near '='.
The way you are using the ? characters is invalid in JDBC:
"INSERT INTO Users(name, pass, type) VALUES (nick=?,pass=?,type=?)
One ? represents the whole bind variable. Try
"INSERT INTO Users(name, pass, type) VALUES (?, ?, ?)"
Also, use executeUpdate to execute an insert statement (or update, or delete).
Remove the field names from the value list. These are already in the name list. Also use executeUpdate for database write operations:
preparedStatement =
conn.prepareStatement("INSERT INTO Users(name, pass, type) VALUES (?,?,?)",
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
preparedStatement.setString(1, user.getNickName());
preparedStatement.setString(2, user.getPassword());
preparedStatement.setInt(3, type);
int rowCount = preparedStatement.executeUpdate();
I have a PreparedStatement and CallableStatement:
String sql = "INSERT INTO parcels (cadastr,the_geom,status_id) VALUES(?,PolygonFromText(?, 4326),?)";
PreparedStatement stmt = ce.prepareStatement(sql);
stmt.setString(1, ts.getPackage().getSpecifyParcels().getExistParcel()
.get(0).getCadastralNumber());
stmt.setString(2, WKT);
// stmt.setString(3, deleted);
stmt.setInt(3, status_id);
stmt.execute();
stmt.close();
java.sql.CallableStatement proc1 = ce
.prepareCall("{call insert_into_wgs()}");
proc1.execute();
proc1.close();
Its possible to execute this query and function insert_into_wgs() in one statement?
Use the RETURNING keyword!
INSERT INTO parcels (cadastr,the_geom,status_id)
VALUES (?, PolygonFromText(?, 4326), ?)
RETURNING insert_into_wgs()
I am inserting values in a Mysql database from java file using -
String query = "INSERT INTO genes (sent, title) VALUES ('"+sent+"','"+title+"')";
Statement stmt = con.createStatement();
int rs = stmt.executeUpdate(query);
where sent and title are variable strings extracted after applying some algorithm. But this gives sql error when sent or title contains single qoutes.
Consider using a prepared statement with parameters:
PreparedStatement pstmt = con.prepareStatement(
"INSERT INTO genes (sent, title) VALUES (?, ?)");
pstmt.setString(1, sent);
pstmt.setString(2, title);
pstmt.executeUpdate();
You should use PreparedStatement in fill the query parameters. It takes care of escaping the single quotes if any in the input parameters.
Modify your query and statement object as follows and it should be working:
String query = "INSERT INTO genes (sent, title) VALUES (? , ?)";
PreparedStatement pst = con.prepareStatement( query );
pst.setString( 1, sent );
pst.setString( 2, title );
int insertResult = pst.executeUpdate();
You should use PreparedStatements for that. PreparedStatement is under java.sql.* namespace.
String insertString = "INSERT INTO genes (sent, title) VALUES (?,?)";
// con is your active connection
PreparedStatement insertX = con.prepareStatement(updateString);
insertX.setString(1, sent);
insertX.setString(2, title);
insertX.executeUpdate();
You should never concatenate SQL statements like this, instead, use prepared statements:
String query = "INSERT INTO genes (sent, title) VALUES (?,?)";
PreparedStatement stmt = con.prepareStatement(query);
p.setString(1, sent);
p.setString(2, title);
p.executeUpdate();
If you use the string concatenation method you are exposing yourself to dangerous sql-injection attacks.
String query = "INSERT INTO genes (sent, title) VALUES (?, ?)";
PreparedStatement pt = con.prepareStatement(query);
pt.setString(1, sent);
pt.setString(2, title);
pt.executeUpdate();
Please, Remove ' from string or replace by \' from '.
Mysql allow only in \' format for special character.