I have a database with a AUTO_INCREMENTING id column and a name column. If I delete a row from the data I would like to update all of the other rows id so the sequence is right again, I am very lost please help me.
I tried this:
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT COUNT(id) FROM " + table_name_products);
int count = 0;
while(rs.next()){
count = rs.getInt("COUNT(id)");
}
stmt = conn.createStatement();
for(int i = 1; i <= count; i++){
if(i > id){
stmt.addBatch("UPDATE " + table_name_products + " SET id = "+ i-- +" WHERE id = "+ i +";");
}
}
I don't think this is possible.
I think the only solution would be to cache all rows after the one you are deleting some place, delete those rows, then add the cached rows to the table again.
There might be database management command to do this, but you wouldn't want to be doing it after every delete.
What about a database trigger. Have a look here.
A database trigger is procedural code that is automatically executed
in response to certain events on a particular table or view in a
database.
Related
I have a table with 3 columns and approximately 11,000 rows. The first row is an auto-increment primary key, followed by two Integers. These integers are the primary key ID of another table, which has the information I require. (The information I'm looking for is first names).
My plan is to output the necessary information to a standard text file using a FileWriter with each row being represented by one line like this "user1, user2". Once all ~11,000 rows have been fully processed, I would like to print a success message, then terminate the program.
The problem is I don't know the best way to go about retrieving this information in bulk, without it skipping rows. I've also attempted to use a while loop, however have been gotten stuck in the loop, resulting in corruption. Here's my latest attempt, which is terminating before it completing:
//Code to get total number of rows in table
//
for(int i = 0; i < size; i++) {
statement1 = connect.createStatement();
rs1 = statement1.executeQuery("select * from table2 limit (i-1), 1");
while(rs1.next() {
int user1 = rs1.get("user1");
int user2 = rs1.get("user2");
statement2 = connect.createStatement();
StringBuilder builder = new StringBuilder();
rs2 = statement2.executeQuery("select * from table1 where id = user1");
while(rs2.next()) {
String name = rs2.get("name");
builder.append(name).append(", ");
}
rs3 = statement2.executeQuery("select * from table1 where id = user2");
while(rs3.next()) {
String name = rs2.get("name");
builder.append(name);
}
}
//Code here to write the row to file, ensure empty StringBuilder, and close necessary SQL
}
System.out.println("Successfully processed" + size + " rows!");
System.out.println("Terminating program");
System.exit(0);
I want to add column based on data means if am getting 5 value in warehouse then add 5 column in table like warehouse1, warehouse2, ..........etc.
//connection is defined here
Connection con = DbUtil.getConnection();
PreparedStatement stm = null;
ResultSet rs = null;
int i = 1;
// in workaddress am getting unlimited value , i want to add column till condition got false
if(request.getParameter("workaddress") != null)
{
// here i have define column name warehouse + i with increment but i got error duplicate column name
stm = con.prepareStatement("ALTER TABLE tbl_buyer ADD warehouse" + i++ + " VARCHAR(100)");
stm.executeUpdate();
}
Try to add i++ before ( or use ++i ) because it affect the value then it makes the increment , due to this it'll throw duplicate column name error .
i++;
stm = con.prepareStatement("ALTER TABLE tbl_buyer ADD warehouse" + i + " VARCHAR(100)");
I want to print my rows count at the end, But it shows 1
public void showRecords() {
try {
Statement st1 = con.createStatement();
ResultSet result1 = st1.executeQuery("select * from mytable");
while (result1.next()) {
System.out.println(result1.getString(1) + " " + result1.getString(2));
}
ResultSet rs1 = st1.executeQuery("select count(*) from mytable");
int rows = rs1.last() ? rs1.getRow() : 0;
System.out.println("Number of rows is: "+ rows); //print 1
} catch (SQLException sqle) {
System.out.println("Can not excute sql statement");
sqle.printStackTrace();
}
}
Output:
...
Number of rows is: 1
Output: ... Number of rows is: 1
That's absolutely correct because the ouput of a count query like
select count(*) from mytable
would only contain a single row containing the total number of rows. For you to now retrieve that count you should make use of the Resultset's getter methods as usual.
int rows = rs1.getInt(1);
To retrieve the count the way you wanted to; use the same approach with your first query
ResultSet result1 = st1.executeQuery("select * from mytable");
int rows = result1.last() ? result1.getRow() : 0;
System.out.println("Number of rows is: "+ rows); // should print the count
The count(*) does not have a column name (or only a "generated" one that you might not know). Therefor you need to get the value by column index.
Additionally you need to call next() on the ResultSet in order to be able to obtain the value:
ResultSet rs1 = st1.executeQuery("select count(*) from mytable");
int rows = 0;
if (rs1.next() {
rows = rs1.getInt(1);
}
System.out.println("Number of rows is: "+ rows); //print 1
Selecting the count from a RecoredSet always returns a value of 1, i.e. the record containing the result of the query. You want
ResultSet rs1 = st1.executeQuery("select count(*) from mytable");
if (rs1.next()) {
int rows = rs1.getInt("COUNT")
}
You must read the value from the rowcount query, as it is a normal query. Like
rows = rs1.getInt(1);
I've written a blog post about retrieving query metadata without extra roundtrip, which is something people typically do to paginate their data. I really recommend you don't re-run your queries all the time just to count stuff. A simple approach would be to use window functions, which are now supported in a lot of SQL dialects:
SELECT *, count(*) OVER () FROM mytable
Of course, since you're using low level JDBC API to iterate your ResultSet, why not just count things in the client at that point? E.g.
try (ResultSet rs = s.executeQuery("select * from mytable")) {
int i = 0;
while (rs.next()) {
System.out.println(rs.getString(1) + " " + rs.getString(2));
i++;
}
System.out.println("Number of rows is: " + i);
}
I am working with Oracle Database 10g, java and try to use ResultSet to insert new row.
I have object of ResultSet which is updateble and insensitive in direction meaning that you can traverse in any direction.
When I insert row in ResultSet using moveToInsertRow, insertRow, and setter method, the row is inserted in Database, but while traversing ResultSet, I am not able to view newly inserted row
Can any one help me.
My Code is :
import java.sql.*;
import java.io.*;
import java.util.Date;
public class TestResultSet{
public static void main(String...args){
try{
Connection con = DriverManager.getConnection("jdbc:oracle:thin:#//localhost:1521/xe", "system", "admin");
Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("Select EnrNo, Name, Gender, DOB From Student");
int i;
while(rs.next()){
for(i = 1; i < 5; i++)
System.out.print(rs.getString(i) + ", ");
System.out.println();
}
//Inserting New Row
rs.moveToInsertRow();
rs.updateLong(1, 117020365276L);
rs.updateString(2, "Ashfaq");
rs.updateInt(3, 1);
Date d = new Date();
rs.updateDate(4, new java.sql.Date(d.getYear(), d.getMonth(), d.getDay()));
rs.insertRow();
//New Row Insertion ends here
rs.first(); //Moving to first row
do{
for(i = 1; i < 5; i++) //Index starts from 1, not from 0
System.out.print(rs.getString(i) + ", ");
System.out.println();
}while(rs.next());
}
catch(SQLException ex){ ex.printStackTrace(); }
catch(Exception ex){ ex.printStackTrace(); }
}
}
/*
Student Table Schema
EnrNo Numeric(12) Primary Key
Name varchar2(25);
Gender Numeric(1);
DOB date
*/
The problem is that the new row has been added to the database, not to the current rows recovered from database. So, in order to recognize the new row, you must do another read to your table(s). It could be inneficient (since it depends on how many rows and how complex your query is) but that's how it works.
Knowing this, your code should be like this:
ResultSet rs = stmt.executeQuery("Select EnrNo, Name, Gender, DOB From Student");
int i;
while(rs.next()) {
for(i = 1; i < 5; i++)
System.out.print(rs.getString(i) + ", ");
System.out.println();
}
//Inserting New Row
rs.moveToInsertRow();
rs.updateLong(1, 117020365276L);
rs.updateString(2, "Ashfaq");
rs.updateInt(3, 1);
Date d = new Date();
rs.updateDate(4, new java.sql.Date(d.getYear(), d.getMonth(), d.getDay()));
rs.insertRow();
//New Row Insertion ends here
//Moving to first row of the current recovered resultset
//thus not working as expected
//rs.first();
//close the resultset
rs.close();
//retrieve the rows from database again
rs = stmt.executeQuery("Select EnrNo, Name, Gender, DOB From Student");
do{
for(i = 1; i < 5; i++) //Index starts from 1, not from 0
System.out.print(rs.getString(i) + ", ");
System.out.println();
} while(rs.next());
I remember there were third party libraries that supported the functionality you are looking for, they are pretty expensive.
In general, yes, you will have to refetch. However, you can be smart about it: you can intelligently partition your query to fetch only a few hundred rows
e.g. by using two tables, one for production data, other for new
data, and sometimes merging them (you can use in-memory tables for the new data, and you can create cross-table views, if needed, although not neccessary)
you can create an autoincrement index, and fetch only the latest rows,
or you can use ROWNUM in Oracle, SELECT TOP in SQL Server, LIMIT in MySQL, etc.
and of course, you can implement a custom database driver :-)
In general, if you fetch more than a few hundred rows regularly, something is wrong, and maybe you should reconsider your client side interface and implementation.
A ResultSet that is TYPE_SCROLL_INSENSITIVE is not meant to detect updates to the underlying database (that is what the insensitive means here). If you want the ResultSet to detect changes, then you should use TYPE_SCROLL_SENSITIVE.
However as the changes usually occur in a different transaction, I believe most databases are unable to offer TYPE_SCROLL_SENSITIVE, and if they can then they probably only allow you to see changes to the data of the selected rows, but not detect additional (or removed) rows.
If you try to use TYPE_SCROLL_SENSITIVE, you might want to check if your database actually supports that type (eg using DatabaseMetaData.supportsResultSetType(int)). Or by checking if the created ResultSet is actually of the specified type (the JDBC spec allows drivers to 'downgrade' type and/or concurrency if it isn't supported).
You might also want to check DatabaseMetaData.ownInsertsAreVisible(int) and related methods for your specific database and driver.
Try this:
String query = "Select EnrNo, Name, Gender, DOB From Student";
try {
conn = DriverManager.getConnection(DB_URL, USER, PASS);
// change this to reflect your specific situation
stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
String EnrNo = rs.getString("EnrNo");
String name = rs.getString("Name");
String gender = rs.getString("Gender");
String date = rs.getString("DOB");
System.out.println(EnrNo + "\t" + name + "\t" + gender + "\t" + date);
}
} catch (SQLException e) {
e.printStackTrace();
}
// make sure you add these as your class variables:
Connection conn = null;
Statement stmt = null;
I am trying to retrieve generated keys from an executeBatch() transaction but I only get the last key to be added.
this is my code:
PreparedStatement ps_insert = conn.prepareStatement(insertQuery, PreparedStatement.RETURN_GENERATED_KEYS);
for (int i = 0 ; i < adding_dates.length ; i++){
ps_insert.setInt(1, Integer.parseInt(consultant_id));
ps_insert.setDate(2, adding_dates[i]);
ps_insert.setInt(3, Integer.parseInt(room_id));
ps_insert.addBatch();
}
ps_insert.executeBatch();
ResultSet rs = ps_insert.getGeneratedKeys(); //<-- Only the last key retrieved
conn.commit();
What am I doing wrong?
EDIT: Apologies for not mentioning that I use H2 (http://www.h2database.com/html/main.html) database in embedded mode.
According to H2 jdbc driver javadocs, this is the normal behaviour:
Return a result set that contains the last generated auto-increment
key for this connection, if there was one. If no key was generated by
the last modification statement, then an empty result set is returned.
The returned result set only contains the data for the very last row.
You must iterate the ResultSet to retrieve the keys.
PreparedStatement ps_insert = conn.prepareStatement(insertQuery, PreparedStatement.RETURN_GENERATED_KEYS);
for (int i = 0 ; i < adding_dates.length ; i++){
ps_insert.setInt(1, Integer.parseInt(consultant_id));
ps_insert.setDate(2, adding_dates[i]);
ps_insert.setInt(3, Integer.parseInt(room_id));
ps_insert.addBatch();
}
ps_insert.executeBatch();
ResultSet rs = ps_insert.getGeneratedKeys(); //<-- Only the last key retrieved
if (rs.next()) {
ResultSetMetaData rsmd = rs.getMetaData();
int colCount = rsmd.getColumnCount();
do {
for (int i = 1; i <= colCount; i++) {
String key = rs.getString(i);
System.out.println("key " + i + "is " + key);
}
}
while (rs.next();)
}
conn.commit();
This is a limitation of H2 implementation. This is an issue.
For now use inserts/updates without batch, or query generated keys somehow through select.
If you are sharing a session/connection between 2 threads, and two of those threads try to execute statements at the same time, then you might see this kind of problem.
You probably need to either (a) use a connection pool or (b) synchronise your entire access to the DB.
for instance for option (b)
put a synchronize token infront of your method to make it thread safe
Just a thought as i dont know you complete execution context