I have been trying to insert a "batch" of data into a SQLITE db in an Android application. I am getting no errors, but when trying to select from that Table later, no data is returned.
The application uses both SQL server and SQLITE since the device wont always be connected to the network it cannot access SQLServer all the time, so I am running a query to select from SQLServer and then I pass that resultset to the method that is meant to push the data to the SQLITE DB
The process flow I am following is as follows:
Delete everything currently in the sqliteDB
mDb = mDbHelper.getReadableDatabase();
mDb.execSQL("delete from TABLE_1");
Get data from SQLserver
Connection con = connectionClass.CONN();
connect = con;
try {
PreparedStatement statement = connect.prepareStatement("Exec SelectAll '" + Param1+ "'");
rs = statement.executeQuery();
liteAdapter.insertIntoDbLite(rs);
con.close();
} catch (SQLException ex) {
String error = ex.getMessage();
}
Pass resultset from step 2 to the method that should batch insert the data to sqlite
//Insert Records into Bale Table from SQL Server
public void insertIntoDbLite(ResultSet rs)
{
mDb = mDbHelper.getWritableDatabase();
mDb.beginTransaction();
try {
ContentValues values = new ContentValues();
try {
while (rs.next()) {
//put value(Column_Name, record)
values.put("COL1", rs.getString("Col1_Val"));
values.put("COL2", rs.getString("Col2_Val"));
values.put("COL3", rs.getString("Col3_Val"));
values.put("COL4", rs.getString("Col4_Val"));
values.put("COL5", rs.getString("Col5_Val"));
values.put("COL6", rs.getString("Col6_Val"));
values.put("COL7", rs.getString("Col7_Val"));
values.put("COL8", rs.getString("Col8_Val"));
values.put("COl9", rs.getString("Col9_Val"));
}
mDb.insert("TABLE_1", null, values);
}
catch (java.sql.SQLException e)
{
Log.e("Error in SQL",e.toString());
}
mDb.setTransactionSuccessful();
}
catch(Exception ex)
{
Log.e("Error in transaction",ex.toString());
}
finally
{
//End the transaction
mDb.endTransaction();
}
}
so it all seems to run fine, but when I later query the db and to a select, no values are returned from this table,
am I missing something or just doing it wrong?
Thanks
There appears to be nothing glaringly wrong with the given code. The likely scenario is that the update is in not performing the update due to a constraint (a rule such as, but not limited to NOT NULL, UNIQUE). Another, perhaps less likely scenario is that the while loop isn't being entered.
You could distinguish which by changing
mDb.insert("TABLE_1", null, values);
to
Log.d("INSERT","Return from insert is " + Long.toString(mDb.insert("TABLE_1", null, values)));
This will then either write output with :-
(a) no output to the log indicating that the while loop was not entered, so rs is empty.
(b) -1 being the sole value(s) returned, indicating that the update is not being done due to constraints.
(c) with all or some positive (> 0) value(s) returned, this would indicate, that the updates are being performed and that the issue is likely with the method used to checked the data later.
If (b) then changing mDb.insert to mDb.insertOrThrow should result in the first exception being caught which should indicate the issue.
Related
Currently I have created DB logic which will execute a given command against a target database in order to retrieve specific data.
Currently trying to figure out the correct way to wait for a given value to be present within the database before proceeding with the next database command.
Please could you give your thoughts on the below logic?
createDatabaseConnection(); //will create the DB connection
//Will execute a given DB query
public static void executeSqlUpdateStatement(String query) throws SQLException {
try {
Statement st = con.createStatement();
st.executeUpdate(query);
} catch(MySQLTransactionRollbackException ex) {
Statement st = con.createStatement();
st.executeUpdate(query);
} catch (SQLException e) {
System.out.println("Unable to execute method executeSqlUpdateStatement, Exception: " + e.getStackTrace());
}
}
//Example DB Query
while(!DbManager.executeSingleStatementSqlQueryExtractBasedOnColumn(Booking_Scripts.verifyStatusOfMostRecentBooking("212sdsgge23dds6847"), 1).equals("COMPLETED")) {
//run a command until while equals true (COMPLETED)
}
closeDatabaseConnection(); //will close the DB connection
As you can see from the above code, only until the specific SQL data equals 'COMPLETED' will it break the loop, happy the hear your thoughts on the above logic?
I am working on a JAVA program which need to update database from text files. I have successfully inserted and updated data. But i am facing a problem with here, this method. Query runs without error and giving me the response. But the database table is not updating.
private void filteData() {
System.out.println("filteData");
Statement statementAtenLogInsert = null;
Statement statementqCheck = null;
Statement statementUpdateProLog = null;
Statement statementEnterError = null;
ResultSet rs = null;
int rcount;
//Update successfull attendance_test
String attenLogInsertSuccess = "INSERT INTO attendance_log (user_id, check_in, check_out) SELECT user_id, check_in, check_out FROM process_log WHERE flag = 'S'";
try {
statementAtenLogInsert = connection.createStatement();
statementAtenLogInsert.execute(attenLogInsertSuccess);
int qSuccess = statementAtenLogInsert.executeUpdate(attenLogInsertSuccess);
System.out.println("qSuccess " + qSuccess);
if(qSuccess > 0){
String deleteProcessLog = "DELETE FROM process_log WHERE flag = 'S'";
statementAtenLogInsert.execute(deleteProcessLog);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Here the attenLogInsertSuccess and deleteProcessLog queries are not working. Mean nothing happened from database table side. But qSuccess giving me a value. That means attenLogInsertSuccess is triggering. But nothing happened from mysql side.
You need to close your connection in order to flush the changes to the database.
Try adding connection.close(); somewhere in your pipeline, typically you close the connection in a finally block to ensure it is always closed but it appears you have defined your connection elsewhere, presumably for re-use in the calling function.
You also need to close your statements before closing the connection. See this similar answer for the pattern.
Here is my stored procedure:
CREATE OR REPLACE PROCEDURE VIEWBROKERS
(o_username OUT USERS.USERNAME%TYPE)
AS
BEGIN
SELECT USERNAME
INTO o_username
FROM USERS
WHERE Role_ID = 3 ;
END VIEWBROKERS;
Here is my method calling the stored procedure:
public ResultSet pullBrokers() {
ResultSet rs = null;
try {
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
con = DriverManager.getConnection(Messages.getString("OracleUserManagement.0"), Messages.getString("OracleUserManagement.1"), Messages.getString("OracleUserManagement.2")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
String storedProcedure = "{call VIEWBROKERS(?)}";
CallableStatement statement = con.prepareCall(storedProcedure);
statement.registerOutParameter(1, java.sql.Types.VARCHAR);
rs = statement.executeQuery();
con.commit();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
return rs;
}
And lastly when I tried to print out the results:
public class TEST {
public static void main(String[] args) throws SQLException{
OraclePullListOfUsers pull = new OraclePullListOfUsers();
ResultSet rs = pull.pullBrokers();
try {
while (rs.next()){
System.out.println(rs.getString(1));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
I get the error message ORA-01422: exact fetch returns more than requested number of rows
Which is strange ,because there are only two rows of data in the table...
If someone could point me in the right the direction, that would be awesome!
Looks like you're problem is not related to Java, just on the SQL side. Could it be that both those two rows in the table have Role_ID=3?
The root cause for your problem:
ORA-01422: exact fetch returns more than requested number of rows
is that PL/SQL select into statement expects a query to match to exactly one row. If the query returns no rows or if the query return more than one row (as in your case) it will throw an exception.
You can't use select into to save the results to a single out variable if the query can return more than one row. Instead your subprogram should return a cursor (that is a pointer to a record set) that your Java component can query. Note that returning a cursor is not the only option, but in your case it looks like a good starting point.
This issue has been addressed several times in StackExchange universe. Please take a look e.g.
Return many rows on a plsql Oracle10g
How to return multiple rows from the stored procedure? (Oracle PL/SQL)
Calling Oracle PL/SQL stored procedure from java middle tier using JDBC on Linux?
A Java example Using Ref Cursors To Return Recordsets.
I get following error on Result set
java.sql.SQLException: ResultSet not open. Verify that autocommit is OFF.
at org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(Unknown Source)
at org.apache.derby.client.am.SqlException.getSQLException(Unknown Source)
at org.apache.derby.client.am.ResultSet.next(Unknown Source)
public ResultSet insertDb(int Id,String firstName,String lastName,String title) throws SQLException{
try {
try {
Class.forName(driver);
con = DriverManager.getConnection(connectionURL);
} catch (SQLException ex) {
Logger.getLogger(Connect.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(Connect.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(con.getAutoCommit());
statement = con.createStatement() ;
res = statement.executeQuery("SELECT * FROM CUSTOMER") ;
con.setAutoCommit(false);
System.out.println(con.getAutoCommit());
while(res.next()){
if(res.getString("ID").equalsIgnoreCase(Integer.toString(Id))){
UNIQUE = false;
error= "Duplicate Entry Found Please Enter New Data";
throw new SQLException("Duplicate info<br>ID " + Id );
}
}
// IF value to be added IS UNIQUE
if(UNIQUE){
String qry1= "insert into CUSTOMER(ID, FIRSTNAME,LASTNAME,TITLE) values(?,?,?,?)";
stm = con.prepareStatement(qry1);
String ID=Integer.toString(Id);
stm.setString(1, ID);
stm.setString(2, firstName);
stm.setString(3, lastName);
stm.setString(4, title);
stm.executeUpdate();
}
}
catch(Exception e){
String errorMessage = "Exception caught : ";
System.out.println(errorMessage + e.toString());
}finally{
if (con != null){
con.close();
}
}
return res;
}
Try moving the setAutoCommit() and getAutoCommit() to before you create and execute the statement. Changing it after you execute the statement may be invalidating the query.
The problem is that you have closed your query before reading your resultset. Closing the query, closes the resultset, hence why you get the "ResultSet not open" error. You should close the query right at the end, in a finally block:
i.e. con.setAutoCommit(false);
will close the query and along iwth it it closes the resultset also.
Not strictly related, but your code probably doesn't do what you expect. This kind of read-modify-write code doesn't work well when there are multiple concurrent invocations.
If you imagine two invocations running though the code, it becomes clear that sometimes, depending on the execution order, BOTH invocations could reach the insert statement.
In addition, selecting from a table without using a WHERE clause is not generally useful. In this case you select '*', then iterate over all the results to see if "ID" == Id. The database is much much better at that than java is. You should add a where clause. (Note that this still won't solve the above problem)
Its also generally a bad idea to 'select *' from any table. Just pick the columns that you need. This will 'fail fast' if the schema changes and the columns that you need are no longer available, and will allow the database optimiser to do the 'right thing' about its disk accesses.
Finally, if its just a numeric ID that you are looking to assign, its normal practice to use 'autonumber' for these, rather than get the program to pick them. Different databases call them different things, so you might also know them as IDENTITY, or have to use a sequence.
In case it helps anyone down the line, I had the same error with Derby 10.5.1.1 that turned out to be a bug in the driver itself that would appear some times and not others depending on the underlying data. Upgrading the driver to a newer version (10.8.2.2) resolved the problem.
i am using java sqlite (org.sqlite.JDBC) with this i am adding a new row of data to the table, one field is supposed to take up a big amount of base64 encoded data (like pdf) the type of this field is sql-TEXT. now, if i delete the row with "DELETE FROM table WHERE id='id'" the row gets deleted as expected, my sqlite browser confirms this. but the table was befor the deletion like 4KB big, after adding the row it was 12MB and after deleting it remains 12MB big. is there a kind of cleanup i have to do?
in sqlite admin(http://sqliteadmin.orbmu2k.de/) there is a "Cleanup" button after pressing that everything is fine, which means the database shrinks to its size befor adding stuff (4KB). after asking google i realy cannot find such a sql command. it seems that only the index informations get deleted from my databasefile, not the content itself. this behavior is known from windows delete functions.
beside that, here is the java snippet i use:
public void deleteRowById(String table, int id){
try {
Connection connection = null;
Class.forName("org.sqlite.JDBC");
connection = DriverManager.getConnection("jdbc:sqlite:C:\\meinedb");
//statement = connection.createStatement();
String sql = "DELETE FROM "+table+" WHERE id='"+id+"'";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.executeUpdate();
pstmt.close();
connection.close();
} catch (SQLException ex) {
Logger.getLogger(FileSpinner.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex){
}
}
You can shrink a SQLite database with the VACUUM statement. Read the manual I link to for details.