What to insert data into 2 tables in a single hit - java

pstmt = conn.prepareStatement(queryBuilder.toString());
pstmt.setString(count++, commonDTO.getGroupName());
pstmt.setString(count++, commonDTO.getSubGrpNameHindi());
pstmt.setString(count++, commonDTO.getGroupCode());
pstmt.setInt(count++, commonDTO.getIsActive());
pstmt.executeUpdate();
StringBuilder queryBuilder = new StringBuilder();
queryBuilder = queryBuilder.append(SLCMQueryConstant.Get_SubGrp_Id);
pstmt.setString (1, commonDTO.getGroupName());
rs = pstmt.executeQuery();
int x = 0;
while(rs.next())
{
x= rs.getInt("subject_Group_ID");
}
queryBuilder= queryBuilder.append(SLCMQueryConstant.MapSubject_to_SubGrp);
pstmt.setInt(count++, x);
pstmt.setInt(count++, commonDTO.getSubGrpID());
pstmt.setInt(count++, commonDTO.getSubjectMaxMark());
pstmt.setInt(count++, commonDTO.getSubjectMinMark());
pstmt.executeUpdate();
conn.commit();
I am trying to insert a new row into first table.then I want id of newly added
row and insert into 2nd table but there is an exception.

The error message tells you exactly what's wrong - executeQuery is for executing SELECT queries, not INSERTS/UPDATES. Use executeUpdate instead, as e.g. described here.
Seeing you have added your query above - to execute multiple queries, run multiple executeQuery / executeUpdate statements. As long as you don't have auto-commit set and commit the third query, all three queries will be executed as a single commit (i.e. cannot be interrupted).
It is not possible to run multiple queries with a single executeQuery / executeUpdate, separated by semicolon. This syntax is simply what many clients use to separate queries textually, but the clients will send these queries separately with multiple requests as well.
I'd guess that running three separate queries in a single transaction will be exactly what you need. However, if for some reason you absolutely want to do it with a single execute, you can use a stored procedure, which you prepare ahead of time.

You have to create prepared statements from your built queries:
pstmt = conn.prepareStatement(queryBuilder.toString());
pstmt.setString(count++, commonDTO.getGroupName());
pstmt.setString(count++, commonDTO.getSubGrpNameHindi());
pstmt.setString(count++, commonDTO.getGroupCode());
pstmt.setInt(count++, commonDTO.getIsActive());
pstmt.executeUpdate();
StringBuilder queryBuilder = new StringBuilder();
queryBuilder = queryBuilder.append(SLCMQueryConstant.Get_SubGrp_Id);
pstmt = conn.prepareStatement(queryBuilder.toString()); // <<<<<<-----
pstmt.setString(1, commonDTO.getGroupName());
Recordset rs = pstmt.executeQuery();
int x = 0;
while(rs.next())
{
x = rs.getInt("subject_Group_ID");
}
And you have to reset your prepared statement parameter counter:
queryBuilder= queryBuilder.append(SLCMQueryConstant.MapSubject_to_SubGrp);
pstmt = conn.prepareStatement(queryBuilder.toString()); // <<<<<<-----
count = 1; //<<<<<-----
pstmt.setInt(count++, x);
pstmt.setInt(count++, commonDTO.getSubGrpID());
pstmt.setInt(count++, commonDTO.getSubjectMaxMark());
pstmt.setInt(count++, commonDTO.getSubjectMinMark());
pstmt.executeUpdate();
conn.commit();

Related

put data in List thenn insert it its values into database

I have to store questions in session afterward in List then insert them all into database by one click
my servlet
Question question = new Question(title, content, idExam);
request.getSession().setAttribute("question", question);
int quizKey = ExamDAO.add_question(question);
ArrayList<Question> ques = new ArrayList<Question>();
ques.add(question);
my dao
cnx = Connect.getConnection();
String req = "insert into question(title, content, id_examen) values(?,?,?)";
PreparedStatement st = cnx.prepareStatement(req, Statement.RETURN_GENERATED_KEYS);
st.setString(1, question.getTitre());
st.setString(2, question.getContenu());
st.setInt(3, question.getIdExamen());
st.executeBatch();
ResultSet rs = st.getGeneratedKeys();
if (rs.next()) {
quizKey = rs.getInt(1);
}
how to do that ?
Try st.executeUpdate(). This is usually used for manipulating statements like DELETE, INSERT or UPDATE. The method will return either the row count for SQL Data Manipulation Language (DML) statements or 0 for statements that return nothing.
If you have a List<Question> and you wish to insert all in one go then you have to utilize what is called as - batching or batch update. Refer here for more details
You will be iterating your list of questions and setting parameters for each question then adding that statement to batch (by using st.addBatch()) & then finally call - st.executeBatch().
In your code sample, you are executing a batch but there is only one prepared statement in that batch. You need as many prepared statements as number of questions in the list.
String req = "insert into question(title, content, id_examen) values(?,?,?)";
PreparedStatement st = cnx.prepareStatement(req, Statement.RETURN_GENERATED_KEYS);
for(Question question : ques){
st.setString(1, question.getTitre());
st.setString(2, question.getContenu());
st.setInt(3, question.getIdExamen());
st.addBatch();
}
st.executeBatch();
With this approach, you might have issues in collecting generated keys as illustrated in this SO question so if you really need those ids , you will have to turn off auto commit, execute updates in loop without batching, collected generated ids in a map or list for each insert statement and then finally commit your connection in the end.

Insert performance tuning

Currently we are selecting data from one database and inserting it into a backup database(SQL SERVER).
This data always contains more than 15K records in one select.
We are using Enumeration to iterate over the data selected.
We are using JDBC PreparedStatement to insert data as:
Enumeration values = ht.elements(); -- ht is HashTable containing selected data.
while(values.hasMoreElements())
{
pstmt = conn.prepareStatement("insert query");
pstmt.executeUpdate();
}
I am not sure if this is the correct or efficient way to do the faster insert.
For inserting 10k rows it takes near about 30 min or more.
Is there any efficient way to make it fast?
Note: Not using any indexes on the table.
Use a batch insert, but commit after a few entris, don't try to send all 10K at once. Try investigating to get the best size, it' a trade off to memory vs network trips.
Connection connection = new getConnection();
Statement statement = connection.createStatement();
int i = 0;
for (String query : queries) {
statement.addBatch("insert query");
if ((i++ % 500) == 0) {
// Do an execute now and again, don't send too many at once
statement.executeBatch();
}
}
statement.executeBatch();
statement.close();
connection.close();
Also, from your code I'm not sure what you are doing, but use paramaterised queries rather than sending 10K insert statements as text. Something like:
String q= "INSERT INTO data_table (id) values (?)";
Connection connection = new getConnection();
PreparedStatement ps = connection.prepareStatement(q);
for (Data d: data) {
ps.setString(1, d.getId());
ps.addBatch();
}
ps.executeBatch();
ps.close();
connection.close();
You can insert all the values in one sql command:
INSERT INTO Table1 ( Column1, Column2 ) VALUES
( V1, V2 ), ( V3, V4 ), .......
You may also insert the values by bulks of 500 records, for example, if the query would become very big. It is not efficient at all to insert on row per statement remotely (using a connection). Another solution is to do the inserts using a stored procedure. You just pass the values to it as parameters.
Here is how you can do it using the INSERT command above:
Enumeration values = ht.elements(); -- ht is HashTable containing selected data.
int i=0;
String sql="";
while(values.hasMoreElements())
{
sql+="(" + values + ")"; //better use StringBuffer here
i++;
if(i % 500 == 0) {
pstmt = conn.prepareStatement("insert query "+sql);
pstmt.executeUpdate();
sql="";
}
else
sql += " , ";
}

get size of ResultSet by using SELECT COUNT(*)

I want to retrieve all the data from database, and at the same time, I want to know how many rows of data I get. And this is my SQL:
rs = s.executeQuery("SELECT COUNT(*), * FROM tblUser");
Is this a valid SQL statement? and after I retrieved all the data, how to set them into different variables? For example, I have a column called UserIDin the database, I can simply get it by using rs.getString('UserID'), but how to get the result of the COUNT(*)?
Your SQL is not valid. The ANSI standard way to do what you want uses window functions:
select count(*) over () as total_cnt,
u.*
from tblUser u;
This adds a new column to every row -- which seems to be what you want. There are other mechanisms, depending on the underlying database for doing this.
The results you request are not interrelated, so run two queries:
rs1 = s.executeQuery("SELECT COUNT(*) FROM tblUser");
rs2 = s.executeQuery("SELECT * FROM tblUser");
and retrieve the values (one only for rs1) the usual way.
You can do this to count the rows in resultset
String query = "Select * from tblUser";
rs = s.executeQuery(query);
public int getCount(ResultSet rs) {
int rows = 0;
while(rs.next()) {
i++;
}
return i;
}
This way you can get the resultset as well as count
Since you are already accessing the recordset within VBA probably the simplest was to return the count of the record set is to:
rs = s.executeQuery("SELECT * FROM tblUser");
If Not rs.EOF Then
' Important: You must move to the last record to
' obtain the count of the full recordset
rs.MoveLast
rsCount = rs.RecordCount
' Remember to Return to the First Record so that you can
' continue to use the recordset
rs.MoveFirst
End If
An alternative if your RDBMS doesn't support window functions
rs = s.executeQuery("SELECT B.cnt, U.*
FROM tblUser U,
(SELECT count(*) cnt FROM tblUser) B");

How to perform an update query in Java? [duplicate]

This question already has an answer here:
What is wrong with this update query in java?
(1 answer)
Closed 7 years ago.
I am not so into database and I have the following problem in a Java application that have to perform a very simple query that update a field on a table of my DB.
So, the original query is something like this:
UPDATE coda_tx c SET c.FK_STATO = 2 WHERE c.PK_CODA = 62816;
so I have implemented the following Java method that implement the previous query, this one:
public void updateStatus(int pkCoda, int newStatus) {
String sql;
StringBuffer sb = new StringBuffer();
sb.append("UPDATE coda_tx c SET c.FK_STATO = ");
sb.append(newStatus);
sb.append(" WHERE c.PK_CODA = ");
sb.append(pkCoda);
sql = sb.toString();
try {
statment = connection.createStatement();
ResultSet rs = statment.executeQuery(sql);
} catch (SQLException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
My only doubt is related about the section by which the query is performed, this one:
statment = connection.createStatement();
ResultSet rs = statment.executeQuery(sql);
I think that this is wrong because actually there is ResultSet that is an object used to retrieve rows by a SELECT operation. In this case I am updating a field of a specific row and I am not retrieving rows putting theme into a ResultSet object.
So, how can I correctly handle this situation? How have I to perform my query?
Here is how you could do it:
// updateCount contains the number of updated rows
int updateCount = statment.executeUpdate(sql);
You are looking for statement.executeUpdate() which will return the number of rows affected by the update.
int executeUpdate(String sql) throws SQLException
Executes the given SQL statement, which may be an INSERT, UPDATE, or DELETE statement or an SQL statement that returns nothing, such as an SQL DDL statement.
Reference: http://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html#executeUpdate(java.lang.String)
If your method recives for example two variables like fkStato and pkCoda, that contains the value you want, you can make a simple query:
int fkStato=2;
int pkCoda=62816;
try
{
// create our java preparedstatement using a sql update query
PreparedStatement ps = conn.prepareStatement(
"UPDATE coda_tx c SET c.FK_STATO = ? WHERE c.PK_CODA = ?;");
// set the preparedstatement parameters
ps.setInt(1,fkStato);
ps.setInt(2,pkCoda);
// call executeUpdate to execute our sql update statement and returns number of rows affected
int updateCount = ps.executeUpdate();
ps.close();
}
catch (SQLException se)
{
// log the exception
throw se;
}

Getting resultset from insert statement

i have the below code, where I'm inserting records to a table. When I try to get resultset, it returns null. How to get the latest added row into a resultset?
String sql1 = "INSERT INTO [xxxx].[dbo].[xxxxxx](WORKFLOW_SEQ_NBR," +
" WORKFLOW_LOG_TYPE_CODE, WORKFLOW_STATUS_CODE, DISP_CODE, DISP_USER, DISP_COMMENT, DISP_TITLE, DISP_TS)" +
"VALUES(?,?,?,?,?,?,?,?)";
PreparedStatement pst = connect.prepareStatement(sql1);
pst.setString(1, ...);
pst.setString(2, ...);
...
...
...
pst.executeUpdate();
ResultSet rstest = pst.executeQuery();
// ResultSet rstest = pst.getResultSet();
EDIT: Resolved
added following method to go to the last added row
st.execute("Select * from [xxxx].[dbo].[xxxxxxxxx]");
ResultSet rstest = st.getResultSet();
rstest.afterLast();
GETLASTINSERTED:
while(rstest.previous()){
System.out.println(rstest.getObject(1));
break GETLASTINSERTED;//to read only the last row
}
When using a SQL statement such as INSERT, UPDATE or DELETE with a PreparedStatement, you must use executeUpdate, which will return the number of affeted rows. In this case there is simply no ResultSet produced by the sql operation and thus calling executeQuery will throw a SQLException.
If you actually need a ResultSet you must make another statement with a SELECT SQL operation.
See the javadoc for PreparedStatement#executeQuery and PreparedStatement#executeUpdate
Seems like this is an older question, but i'm looking for a similar solution, so maybe people will still need this.
If you're doing an insert statement, you can use the :
Connection.PreparedStatement(String, String[]) constructor, and assign those to a ResultSet with ps.getGeneratedKeys().
It would look something like this:
public void sqlQuery() {
PreparedStatement ps = null;
ResultSet rs = null;
Connection conn; //Assume this is a properly defined Connection
String sql = "insert whatever into whatever";
ps = conn.prepareStatement(sql, new String[]{"example"});
//do anything else you need to do with the preparedStatement
ps.execute;
rs = ps.getGeneratedKeys();
while(rs.next()){
//do whatever is needed with the ResultSet
}
ps.close();
rs.close();
}
Connection#prepareStatement() - Creates a PreparedStatement object for sending parameterized SQL statements to the database.
which means connect.prepareStatement(sql1); created the PreparedStatement object using your insert query.
and when you did pst.executeUpdate(); it will return the row count for SQL Data Manipulation Language (DML) statements or 0 for SQL statements that return nothing
Now if you again want to fetch the data inserted you need to create a new PreparedStatement object with Select query.
PreparedStatement pstmt = connect.prepareStatement("SELECT * FROM tableName");
then this shall give you the ResultSet object that contains the data produced by the query
ResultSet rstest = pstmt.executeQuery();

Categories

Resources