The current format of my List<String[]> is:
60 52 0 0 1512230400
76 52 1 1 1514044800
42 52 4 1 1516464000
Whereby each separated value by space is a row in my database table, for example: 60 52 0 0 1512230400. I want to insert the 5 separate values per loop. I want to insert all these lines into my database but am not sure on exactly how. This is also a working connection to my database as of now.
This is my rough idea:
String query = "INSERT INTO games (team1_id, team2_id, score1, score2, created_at) VALUES (? ,?, ?, ?, ? )";
Connection con = DBConnector.connect();
PreparedStatement stmt = con.prepareStatement(query);//prepare the SQL Query
for (String[] s : fixtures) {
}
Any help is amazing.
Many thanks
In your for-loop, you can do something like this:
stmt.setString(1, s[0]); //team1_id if it's of string type in db
stmt.setInt(2, Integer.parseInt(s[1])); //team2_id if it's of type integer in db
stmt.setInt(3, Integer.parseInt(s[2])); //score1
stmt.setInt(4, Integer.parseInt(s[3])); //score2
stmt.setLong(5, Long.parseLong(s[4])); //created_at
stmt.executeUpdate();
The above code shows you how to deal with String, Long and Integer, you can use other types similarly.
List<String[]> fixtures = new ArrayList<>();
fixtures.add(new String [] {"60","52","0","0","1512230400"});
fixtures.add(new String [] {"76","52","1","1","1514044800"});
fixtures.add(new String [] {"42","52","4","1","1516464000"});
String query =
"INSERT INTO games (team1_id, team2_id, score1, score2, created_at)\n"
+ " VALUES (? ,?, ?, ?, ? )";
try(
Connection con = DBConnector.connect();
PreparedStatement stmt = con.prepareStatement(query);
) {
for (String[] s : fixtures) {
stmt.setString(1,s[0]);
stmt.setString(2,s[1]);
stmt.setString(3,s[2]);
stmt.setString(4,s[3]);
stmt.setString(5,s[4]);
stmt.execute();
}
con.commit();
}
With this approach, we pass the bind variables as strings. If needed, based on the actual type of the columns being inserted to, conversion from string (VARCHAR) to numeric (NUMBER) will happen by the database.
You got basically all of it right, but didn't take the next step of actually setting the bind-variables ...
This can work if the input List is already created:
List<String[]> fixtures = ...; // assuming this data is already created
String query = "INSERT INTO games (team1_id, team2_id, score1, score2, created_at) VALUES (? ,?, ?, ?, ? )";
try (Connection con = DBConnector.connect();
PreparedStatement stmt = con.prepareStatement(query)) {
for (String [] row : fixtures) {
// This gets executed for each row insert
for (int i = 0; i < row.length; i++) {
stmt.setInt(i+1, Integer.parseInt(row[i]);
}
stmt.executeUpdate();
}
}
catch(SQLException ex) {
ex.printStackTrace();
// code that handles exception...
}
Related
I want to read the rows of a table with 30000000 rows. I have used st.setFetchSize(10000) thinking I will get the 30000000 rows in packages of 10000 but I only get the first 10000 rows and the program ends. Please could anyone tell me how to get all 30000000 rows in packages of 10000?
public class InsertBatch {
public static void main(String[] args) throws SQLException {
try (Connection connection = DriverManager.getConnection("jdbc:postgresql://localhost:5432/postgres", "postgres", "root")) {
connection.setAutoCommit(false);
Statement st = connection.createStatement(
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY,
ResultSet.FETCH_FORWARD
);
System.out.println(new Date());
st.setFetchSize(10000);
System.out.println("start query ");
ResultSet rs = st.executeQuery("SELECT * FROM contratacion");
System.out.println("done query ");
String insert = "INSERT INTO contrato(contrato, codigo_postal,cups) VALUES(?, ?, ?)\n" +
"ON CONFLICT (contrato) DO\n" +
"UPDATE SET codigo_postal = excluded.codigo_postal, cups = excluded.cups";
PreparedStatement pst = connection.prepareStatement(insert);
int cont = 0;
while(rs.next()) {
cont++;
Integer contrato = rs.getInt(1);
Integer codigo_postal = rs.getInt(2);
String cups = rs.getString(3);
pst.setInt(1, contrato);
pst.setInt(2, codigo_postal);
pst.setString(3, cups);
pst.executeUpdate();
connection.commit();
System.out.println(cont);
}
System.out.println(new Date());
} catch (SQLException ex) {
}
}
}
Please read the documentation, i.e. the javadoc of createStatement​(int resultSetType, int resultSetConcurrency, int resultSetHoldability):
Parameters:
resultSetType - one of the following ResultSet constants: ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE
resultSetConcurrency - one of the following ResultSet constants: ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE
resultSetHoldability - one of the following ResultSet constants: ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT
Your code is:
Statement st = connection.createStatement(
ResultSet.TYPE_FORWARD_ONLY, // Good
ResultSet.CONCUR_READ_ONLY, // Good
ResultSet.FETCH_FORWARD // BAD !!!!!
);
As you can see, the 3rd parameter is not one of the valid values.
Since you call connection.commit(); inside the while(rs.next()) loop, it'd work much better for you if you pass ResultSet.HOLD_CURSORS_OVER_COMMIT.
Of course, you shouldn't even be doing that, because 3000000 INSERT statements will take forever, especially if you commit each one individually. Yikes!
If you have to, because you need to process the data in Java, at least use batching.
Instead, just write it as a single statement:
INSERT INTO contrato ( contrato, codigo_postal, cups )
SELECT contrato, codigo_postal, cups
FROM contratacion
ON CONFLICT (contrato) DO UPDATE
SET codigo_postal = excluded.codigo_postal
, cups = excluded.cups
try {
currentCon = ConnectionManager.getConnection();
psParent=currentCon.prepareStatement("insert into accommodation (type,name,price,description,username)values(?,?,?,?,?)", PreparedStatement.RETURN_GENERATED_KEYS);
psParent.setString(1,type);
psParent.setString(2,name);
psParent.setFloat(3,price);
psParent.setString(4,username);
psParent.executeUpdate();
accid= 0;
rs = psParent.getGeneratedKeys();
if (rs.next())
accid = rs.getInt(1);
rs.close();
psParent.close();
psChild=currentCon.prepareStatement("insert into room (accid, bed)values(?,?)");
psChild.setInt(1,accid);
psParent.setString(2,bed);
psChild.executeUpdate(); }
after I run this, I got this error message : failed: An Exception has occurred! java.sql.SQLRecoverableException: internal error
Is there's something wrong with the code? Thank you for your help
Your usage of getGenereatedKeys() actually looks correct to me for Oracle, but the problem is actually with your first insert statement. You have placeholders (and column names) for 5 columns, but you only bind 4 values. Try something like this:
String sql = "insert into accommodation (type, name, price, description, username) ";
sql += "VALUES (?, ?, ?, ?, ?)";
String generatedColumns[] = { "ID" };
psParent = currentCon.prepareStatement(sql, generatedColumns);
psParent.setString(1, type);
psParent.setString(2, name);
psParent.setFloat(3, price);
psParent.setString(4, description); // I ADDED THIS LINE
psParent.setString(5, username);
psParent.executeUpdate();
I am assuming that you have a variable containing a description to be inserted. If not, then remove description and its placeholder from the prepared statement entirely, or just insert null.
i got issue when i go to Insert value to DB (do nothing).
before that i do select table to get last id, and it worked.
Here's my Code:
IDBManager dbManager = getParentExtension().getParentZone().getDBManager();
Connection connection = null;
int idRoom = params.getInt("idRoom");
String betsmall = params.getUtfString("betsmall");
int Uid = params.getInt("recid");
try{
connection = dbManager.getConnection();
PreparedStatement stmt = connection.prepareStatement("SELECT id_game from detail_game ORDER BY id_game DESC LIMIT 1");
ResultSet res = stmt.executeQuery();
if (!res.first())
{
trace("bla bla");
}
int id = res.getInt("id_game");
trace (id);
// **till here there is no problem, i can get id from select query
PreparedStatement stmts = connection.prepareStatement("INSERT INTO detil_bet (id_user, id_room, id_bet, bettype) VALUES (?, ?, ?, ? ");
stmts.setInt(1, Uid);
stmts.setInt(2, idRoom);
stmts.setInt(3, id);
stmts.setString(4, betsmall);
stmts.executeUpdate();
}
}
Here's the problem, insert do nothing.
PreparedStatement stmts = connection.prepareStatement("INSERT INTO detil_bet (id_user, id_room, id_bet, bettype) VALUES (?, ?, ?, ? ");
Looks like you need some end parentheses in "VALUES".
A catch block to print stack trace would have told you the issue here as well. I'm not the best SQL guy, I always use this to check my SQL syntax as well to double check if I've done everything right.
your connection seems not auto commit. Try to add
stmts.commit();
after "stmts.executeUpdate();".
I'm having problems trying to insert the values into my database.
When i do the code below it works
insertString = "insert into Players
values(1,'Fred','Fish','fredfish#gamer.net','Ithroeann',19770322)";
statement.executeUpdate(insertString);
but when I try to do this look here it gives me an incorrect syntax near '0' error
I'm trying to loop it to add it automatically through a file
Scanner input = new Scanner(new File("players.txt"));
while (input.hasNext()) {
String[] temp;
String str = input.next();
temp = str.split("\\|");
insertString = "insert into Players values(temp[0], temp[1],temp[2],temp[3],temp[4],temp[5])";
statement.executeUpdate(insertString);
}
This is a String. If you want to append elements of the temp array to the String, you can't do it this way.
You can do it like this :
insertString = "insert into Players values("+temp[0]+",'"+temp[1]+"','"+temp[2]+"','"+temp[3]+"','"+temp[4]+"',"+temp[5]+")";
statement.executeUpdate(insertString);
Of course using a PreparedStatement would be a much better solution.
PreparedStatement stmt = conn.prepareStatement("insert into Players values(?,?,?,?,?,?)");
stmt.setInt (1, Integer.parseInt(temp[0]));
stmt.setString (2, temp[1]);
stmt.setString (3, temp[2]);
stmt.setString (4, temp[3]);
stmt.setString (5, temp[4]);
stmt.setInt (6, Integer.parseInt(temp[5]));
stmt.executeUpdate();
Use a PreparedStatement to bind your query parameters as
PreparedStatement pStmt = connection.prepareStatement(
"insert into Players values (?, ?, ?, ?, ?, ?)");
// index starts from 1
int i = 1;
// bind first int value
pStmt.setInt(i, Integer.parseInt(temp[0]));
// bind string values
for (; i < temp.length; i++)
pStmt.setString(i, temp[i-1]);
// bind last int value
pStmt.setInt(i, Integer.parseInt(temp[i-1]));
// execute insert
pStmt.executeUpdate();
Unless the code posted above is partial, it seems like you're missing the statement preparation part. Try something like the following:
Scanner input = new Scanner(new File("players.txt"));
while (input.hasNext()) {
String[] temp;
String str = input.next();
temp = str.split("\\|");
dbConnection = getDBConnection(); // Implement this method based on your DB configuration
String insertString = "insert into Players values(?, ?, ? , ?, ?, ?)";
PreparedStatement statement = dbConnection.createStatement();
statement.setInt(temp[0]); // int, or whichever type you have
statement.setInt(temp[1]); // int, or whichever type you have
statement.setInt(temp[2]); // int, or whichever type you have
statement.setInt(temp[3]); // int, or whichever type you have
statement.setInt(temp[4]); // int, or whichever type you have
// ^ for the above, if all fields are the same - you can do this in a loop
statement.executeUpdate(insertTableSQL); // execute the insert
This question already has answers here:
java.sql.SQLException: Column count doesn't match value count at row 1
(3 answers)
Closed 6 years ago.
I have encountered an error, java.sql.SQLException:
Column count doesn't match value count at row 1
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3609)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3541)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2002)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2163)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2624)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2127)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2427)
It's super frustrating, because I have been making amendments to the code like changing in the arg to all string, but the error still appears.
public void readDataBase(int val, String d1, String d2, String d3, String d4 ) throws Exception {
try {
// This will load the MySQL driver, each DB has its own driver
Class.forName("com.mysql.jdbc.Driver");
// Setup the connection with the DB
connect = DriverManager
.getConnection("jdbc:mysql://localhost/MAXdb?"+ "user=root&password=");
// Statements allow to issue SQL queries to the database
statement = connect.createStatement();
// Result set get the result of the SQL query
resultSet = statement
.executeQuery("select * from MAXdb.emcsg");
writeResultSet(resultSet);
// PreparedStatements can use variables and are more efficient
preparedStatement = connect
.prepareStatement("insert into MAXdb.emcsg values (default,?, ?, ? , ?, ?)");
// Parameters start with 1
preparedStatement.setInt(1, val);
preparedStatement.setString(2, d1);
preparedStatement.setString(3, d2);
preparedStatement.setString(4, d3);
preparedStatement.setString(5, d4);
preparedStatement.executeUpdate();
preparedStatement = connect
.prepareStatement("SELECT id, Date, Time, Demand, SUPPLY from MAXdb.emcsg");
resultSet = preparedStatement.executeQuery();
writeResultSet(resultSet);
} catch (Exception e) {
throw e;
} finally {
close();
}
}
My second class:
public void Csvreader() throws IOException {
try {
// TODO code application logic here
CSVReader reader = new CSVReader(new FileReader("D:/TEST.csv"));
String nextLine[];
int i = 1;
Mysql sen = new Mysql();
while ((nextLine = reader.readNext()) != null) {
try {
sen.readDataBase( i, nextLine[0], nextLine[1], nextLine[2], nextLine[3] );
i = i+1;
} catch (Exception ex) {
Logger.getLogger(Opencsv.class.getName()).log(Level.SEVERE, null, ex);
}
}
} catch (FileNotFoundException ex) {
Logger.getLogger(Opencsv.class.getName()).log(Level.SEVERE, null, ex);
}
}
Database:
Field Type Collation Attributes Null Default Extra Action
id int(11) No None
Date text utf8_general_ci No None
Time text utf8_general_ci No None
Demand text utf8_general_ci No None
SUPPLY text utf8_general_ci
Well, I suspect this is the problem:
insert into MAXdb.emcsg values (default,?, ?, ? , ?, ?)
You haven't specified which column each of those parameters is meant to refer to - and I suspect you've not got 6 columns. Even if you do have 6 columns in the table, it would be a good idea to explicitly state in the SQL which column you mean to use for each parameter.
It seems that the following statement:
insert into MAXdb.emcsg values (default,?, ?, ? , ?, ?)
causes an error. Check if emcsg has 6 columns.
Had you tried changing this
preparedStatement = connect
.prepareStatement("insert into MAXdb.emcsg values (default,?, ?, ? , ?, ?)");
to this
preparedStatement = connect
.prepareStatement("insert into MAXdb.emcsg values (?, ?, ? , ?, ?)");
That might work for you.
Regards
It seems to me, that there is a problem with your database structure. I think you don't have all the fields you assume you have.
Do you definitely have six columns in the database table?
Always google an error message or error code. Quite often the first link returned will clearly explain the problem and provide a solution.
Your method signature
public void readDataBase(int val, String d1, String d2, String d3, String d4 )
has 5 variables, but your method call has 6:
preparedStatement = connect
.prepareStatement("insert into MAXdb.emcsg values (default,?, ?, ? , ?, ?)");