SQLite insert statement always overwrite existing row - android

I have a simple insert SQLite statement :
private final String INSERT_FEED = "insert into "
+ TABLE_FEEDS
+ "([id],[first_name], [last_name], [image], [content]) "
+ "values (?,?,?,?,?)";
Which i used in a method :
public long insertFeed(FeedsModel feed) {
this.insertStmt = db.compileStatement(INSERT_FEED);
this.insertStmt.bindString(1, feed.getId() + "");
this.insertStmt.bindString(2, feed.getFirstName());
this.insertStmt.bindString(3, feed.getLastName());
this.insertStmt.bindString(4, feed.getProfileImage());
this.insertStmt.bindString(5, feed.getContentDetails());
long result = this.insertStmt.executeInsert();
return result;
}
Later, i used that method in my activity :
for(int i = 0; i < feedsAdapter.getCount() - 1; i++)
{
helper.insertFeed(feedsAdapter.getItem(i));
}
The problem is, the table always have only 1 row because the new data will overwrite the existing row, instead of inserted in a new row.

Your current for loop is inserting all the FeedsModels other than the last one. If you only have one model in the list it would explain why you are not seeing any new inserts into the table, instead do:
for (FeedsModel feedsModel : feedsAdapter) {
helper.insertFeed(feedsModel);
}

Related

How to insert to into many to many relationships. SQLite

In my android app I have an SQLite database. with this structure:
PrivateList(idList INTEGER PRIMARY KEY, name TEXT, creationDate TEXT, active INTEGER, deactivationDate TEXT);
PrivateProduct (idProduct INTEGER PRIMARY KEY, description TEXT, quantity INTEGER, active INTEGER, additionDate TEXT);
List_Product(idList INTEGER NOT NULL, idProduct INTEGER NOT NULL, PRIMARY KEY (idList, idProduct), FOREIGN KEY(idList) REFERENCES PrivateList(idList), FOREIGN KEY(idProduct) REFERENCES PrivateProduct(idProduct));
I have an autogenerator list and elements using for to try the app:
localDB = new LocalDB(this, "localBD", null, 1);
SQLiteDatabase sqLiteDatabase = localDB.getWritableDatabase();
if (sqLiteDatabase != null){
for (int i = 0; i < 10; i++){
String a = "List" + i;
String b = "Product" + i;
Log.i("execfor", "INSERT INTO PrivateList (name, creationDate, active, deactivationDate) " + " VALUES ('" + a + "', CURRENT_TIMESTAMP, 1, null);");
sqLiteDatabase.execSQL("INSERT INTO PrivateList (name, creationDate, active, deactivationDate) " + " VALUES ('" + a + "', CURRENT_TIMESTAMP, 1, null);");
sqLiteDatabase.execSQL("INSERT INTO PrivateProduct (description, quantity, active, additionDate) " + " VALUES ('" + b + "', 3, 1, CURRENT_TIMESTAMP);");
//sqLiteDatabase.execSQL("INSERT INTO List_Product (idList, idProduct) values ");//
}
}
But I can`t find the way to get rowIds from each list and product to insert both, idlist and idproduct, into List_Product.
Thank you in advance.
The main change to facilitate grabbing the id's would be to swap from using execSQL to using insert as insert returns the id of the inserted row, execsql does not.
A little more on this here Using execSQL for INSERT operation in Android SQLite.
However, I'm not sure if you can pass CURRENT_TIMESTAMP via a ContentValues and it would result getting the current timestamp as opposed to just setting the value to the literal CURRENT_TIMESTAMP. You could use DEFAULT CURRENT_TIMEPSTAMP in the respective column definitions (as I have in the code below).
I'd suggest that you would not want a link between every list/product permutation (that would be 100 rows for you 10 List rows and 10 Product rows) as in real life you would probably not have such a scenario rather you'd have some links between the two. So in the code below I've randomly created links.
First some code from the Database Helper (for my convenience named SO45449914) for performing the inserts:-
public long insertListRow(String name,
int active) {
ContentValues cv = new ContentValues();
cv.put(LISTNAME_COL,name);
cv.put(LISTACTIVE_COL,active);
cv.put(LISTDEACTIVATIONDATE_COL,"");
return this.getWritableDatabase().insert(PRIVATELISTTABLE,null,cv);
}
public long insertProductRow(String description,int quantity, int active) {
ContentValues cv = new ContentValues();
cv.put(PRODUCTDESCRIPTION_COL,description);
cv.put(PRODUCTQUANTITY_COL,quantity);
cv.put(PRODUCTACTIVE_COL,active);
return this.getWritableDatabase().insert(PRIVATEPRODUCTTABLE,null,cv);
}
public void insertListProductLink(long listid, long productid) {
ContentValues cv = new ContentValues();
cv.put(LISTPRODUCTLIST_COL,listid);
cv.put(LISTPRODUCTPRODUCT_COL,productid);
if (this.getWritableDatabase().insertOrThrow(LISTPRODUCTTABLE,null,cv) <0) {
//handle failed insert
}
}
Notes
- I've used class variables for all columns names.
- Columns that have the current time stamp get this via the default, so there is no need to have a cv.put for those columns.
In the activity is the following code :-
void doSO45449914() {
SO45449914 dbhelper = new SO45449914(this);
int loopcount = 10;
long[] listids = new long[loopcount];
long[] productids = new long [loopcount];
for (int i=0; i < 10; i++) {
listids[i] = dbhelper.insertListRow("a" + i,1);
productids[i] = dbhelper.insertProductRow("b" + i,3,1);
}
Cursor csra = dbhelper.getWritableDatabase().query(SO45449914.PRIVATELISTTABLE,
null,null,null,null,null,null
);
Cursor csrb = dbhelper.getWritableDatabase().query(SO45449914.PRIVATEPRODUCTTABLE,
null,null,null,null,null,null
);
Log.d("SO45449914","Number of rows in LIST TABLE = " + csra.getCount());
Log.d("SO45449914","Number of rows in PRODUCTS TABLE = " + csrb.getCount());
for (long aid: listids) {
Log.d("SO45449914","LIST ID from store = " + Long.toString(aid));
}
for (long bid: productids) {
Log.d("SO45449914","PRODUCT ID from store = " + Long.toString(bid));
}
for (long lid: listids) {
for (long prdid: productids) {
if ((Math.random() * 100) > 60) {
dbhelper.insertListProductLink(lid,prdid);
Log.d("SO45449914",
"Adding link between List id(" +
Long.toString(lid) +
") and product id(" +
Long.toString(prdid) +
")"
);
}
}
}
csra.close();
csrb.close();
}
Exlapnation
The first few lines prepare long arrays based upon the number of Lists and products to be created (same number of both). Integer loopcount determines how many.
The first loop, inserts Lists and Products which use the insert method storing the returned id in the respective array element.
Two Cursors are then created for obtaining row counts, which are then written to the log. The id's as stored in the arrays are output to the log.
Two nested loops are then invoked with Products being the inner (not that it matters) and randomly (about 40% of the time) a row will be inserted into the link table. I've assumed random but you always easily adjust the algorithm to follow a pattern. It's if ((Math.random() * 100) > 60) { that determines whether or not to insert a link.
The two Cursors are then closed.
Results
Here are screen shots of the resultant tables :-
PrivateList Table
PrivateProduct Table
List_Product Table
..... (44 rows in the List_Product table)
Well, this is what I did. Despite of the fact that there is a way do the same without so many rows in List_Product table; I'd like to understand the way. (Also I had problem in the for so it didnt do what I wanted exactly).
localDB = new LocalDB(this, "localBD", null, 1);
SQLiteDatabase sqLiteDatabase = localDB.getWritableDatabase();
if (sqLiteDatabase != null){
long idList;
long idProduct;
for (int i = 0; i < 10; i++){
String a = "List" + i;
String b = "Product" + i;
ContentValues contentValuesList = new ContentValues();
contentValuesList.put("name", a);
contentValuesList.put("active", 1);
contentValuesList.put("creationDate", "CreationDate");
contentValuesList.put("deactivationDate", "");
idList = sqLiteDatabase.insert("PrivateList", null, contentValuesList);
for (int j = 0; j < 10; j++){
ContentValues contentValuesProduct = new ContentValues();
contentValuesProduct.put("description", b);
contentValuesProduct.put("active", 1);
contentValuesProduct.put("quantity", 1);
contentValuesProduct.put("additionDate", "additionDdate");
idProduct = sqLiteDatabase.insert("PrivateProduct", null, contentValuesProduct);
ContentValues contentValuesListProduct = new ContentValues();
contentValuesListProduct.put("idList", idList);
contentValuesListProduct.put("idProduct", idProduct);
sqLiteDatabase.insert("List_Product", null, contentValuesListProduct);
}
I know it could be more efficient, but that it doesn't matter now.
This is the result in the database:
PrivateList:
with 10 rows
PrivateProduct:
with 100 rows.
List_Product:
The problem was that I didn't know the existance of sqlLiteDatabase.insert(...) method.
Thanks you all.

error in using insert query in android

I am saving some data and pic to my db I found out the true way to save my pic in db is to use contentvalue so this the code:
try
{
MyDataBase = new MyDatabase(this);
mydb = MyDataBase.getWritableDatabase();
ContentValues tempval;
for (int j = 0; j < myarray.arrtitle.length; j++)
{
tempval = saveimage(myarray.arrpic.get(j),myarray.arrpath[j]);
mydb.execSQL("INSERT INTO news (title,content) VALUES (\"" + myarray.arrtitle[j] +
"\",\"" + myarray.arrcontent[j] + "\"" + ")");
mydb.insert("news", null, tempval);
}
mydb.close();
Toast.makeText(getApplicationContext(), "database 2 done", Toast.LENGTH_LONG).show();
count = 5;
} catch (Exception e) {
// TODO: daabase error2
Toast.makeText(getApplicationContext(), "data error2", Toast.LENGTH_LONG).show();
}
so this is how i can save my data correctly.
but the problem is when I insert my image, it insert in new row not the row as same as title was inserted.
is there any way to handle this?
You need to use UPDATE query, if you want to edit some column data of an already existing row. Every time you execute INSERT query, it will create a new row.
You are executing INSERT query twice, once you are inserting title and content and then in next query you are inserting image path. Instead while saving image path you should execute UPDATE query for the same row in which you saved corresponding data.
Use LIKE instead of = operator.
// updating row
db.update(TABLE, tempval , "title LIKE ?", new String[] { myarray.arrtitle[j] })

To insert large amount of data in android SQLite Database

I am new in Android Development.
Currently, working with SQLite Database in Android.
My problem is that I have a large amount of data which I have to store in SQLite Database in Android.
There are 2 tables: One having 14927 rows and the other one has 9903 rows.
Currently the database in sql. And I have copy these data in excel sheet but don't understand how can I import these data in SQLite Database.
I go through the following link:
Inserting large amount of data into android sqlite database?
Here, the solution is posted regarding CSV File. But want to know other ways of doing this.
Please let me know what is the best way to import such a large data in Android.
Please help me. Thanks in advance.
Do Like This
SQLiteDatabase sd;
sd.beginTransaction();
for (int i = 0; i < data.size(); i++) {
ContentValues values = new ContentValues();
values.put(DBAdapter.Column1, "HP");
values.put(DBAdapter.Column2, "qw");
values.put(DBAdapter.Column3, "5280");
values.put(DBAdapter.Column4, "345, 546");
sd.insert(DBAdapter.TABLE, null, values);
sd.insertWithOnConflict(tableName, null, values, SQLiteDatabase.CONFLICT_IGNORE);
}
sd.setTransactionSuccessful();
sd.endTransaction();
Try this
SQLiteDatabase db = Your_DATABASE;
db.beginTransaction();
db.openDatabase();
for (int i = 0; i < array.size(); i++)
{
String sql = ( "INSERT INTO " + Table_NAME
+ "(" + COLUMN_1 + ","
+ COLUMN_2 + ","
+ COLUMN_3 + ","
+ COLUMN_4 + ","
+ ") values (?,?,?,?)");
SQLiteStatement insert = db.compileStatement(sql);
}
db.setTransactionSuccessful();
db.endTransaction();
db.closeDatabase();
Use DatabaseUtils.InsertHelper. In this article you will find an example of how to use it and other ways to speed up insertions. The example is as follows:
import android.database.DatabaseUtils.InsertHelper;
//...
private class DatabaseHelper extends SQLiteOpenHelper {
#Override
public void onCreate(SQLiteDatabase db) {
// Create a single InsertHelper to handle this set of insertions.
InsertHelper ih = new InsertHelper(db, "TableName");
// Get the numeric indexes for each of the columns that we're updating
final int greekColumn = ih.getColumnIndex("Greek");
final int ionicColumn = ih.getColumnIndex("Ionic");
//...
final int romanColumn = ih.getColumnIndex("Roman");
try {
while (moreRowsToInsert) {
// ... Create the data for this row (not shown) ...
// Get the InsertHelper ready to insert a single row
ih.prepareForInsert();
// Add the data for each column
ih.bind(greekColumn, greekData);
ih.bind(ionicColumn, ionicData);
//...
ih.bind(romanColumn, romanData);
// Insert the row into the database.
ih.execute();
}
}
finally {
ih.close();
}
}
//...
}

insert a lot of data into sqlite in android

currently, I have to insert more than 10 billions data into my android at a time. However, the problem of out of memory will crash the program. The sqlite insert test is quite simple. Just using the for loop to produce the sql insert command and wrqpped by "begin" and "commit".
private ArrayList<String> sqlInsertCmd = new ArrayList<String>();
int QUERIES_TIMES = 10000000;
private void CreateInsertQueries()
{
Random localRandom = new Random();
int i = 0;
while (i < QUERIES_TIMES)
{
int j = localRandom.nextInt(100000);
sqlInsertCmd.add("insert into " + TABLE + " (a,b,c) values (" + i + "," +
j + ",'" + String.valueOf(j) + "')");
++i;
}
}
Then..
mDB.beginTransaction();
for (int i=0; i<this.QUERIES_TIMES; i++)
{
mDB.execSQL(sqlInsertCmd.get(i));
}
mDB.setTransactionSuccessful();
mDB.endTransaction();
Are there any ideas to avoid the out of memory?
Thanks you all, but the code above is just a simple example. In my program, it is more complicated. I must store something in a container(such as hashMap) and build the sql statement dynamically. Could I create 10 services and each service handle 1/10 jobs?
A few things:
See my answer here for general tips when doing bulk INSERTs.
There is no need to have a temporary container for your INSERT statements (in this case, the ArrayList<>). Simply use beginTransaction() and endTransaction() in a try...finally.
Utilize pre-compiled statements via SQLiteStatement vs building each INSERT statement as in your example. This is needless thrashing.
Quick and dirty example:
// note: untested code used for illustration!
private boolean bulkInsertData(SQLiteDatabase db, final String tableName) {
final int NUM_ROWS = 10000000;
Random random = new Random();
try {
SQLiteStatement insStmt = insStmt = db.compileStatement("INSERT INTO " + tableName + " (a, b, c) VALUES (?, ?, ?);");
db.beginTransaction();
try {
for(int i = 0; i < NUM_ROWS; i++) {
insStmt.bindLong(1, i);
insStmt.bindLong(2, random.nextInt(100000));
insStmt.bindString(3, String.valueOf(i));
insStmt.executeInsert(); // should really check value here!
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
} catch(SQLException se) {
return false;
}
return true;
}
Instead of creating an ArrayList which contains 10000000 number of sql queries (and might be the potential reason for OutOfMemory), you may simply start inserting records in the same loop where you are creating query strings. For example:
private void CreateInsertQueries(SQLiteDatabase mDB)
{
Random localRandom = new Random();
int i = 0;
String query;
try{
mDB.beginTransaction();
while (i < QUERIES_TIMES)
{
int j = localRandom.nextInt(100000);
query = "insert into " + TABLE + " (a,b,c) values (" + i + "," +
j + ",'" + String.valueOf(j) + "')";
++i;
mDB.execSQL(query);
}
mDB.setTransactionSuccessful();
}
catch (SQLException e) { e.printStackTrace(); }
finally{ mDB.endTransaction(); }
}
Doing so will help you to skip ArrayList which (i think) is the reason for OutOfMemory due to holding so so many records.
And make sure you do use External Memory to host your database file, otherwise not all phones have bigger internal memory.

saving an ArrayList<String> state in a SQLiteDatabase (Android)

i'm working on a android app that will display Strings to the user, and the user then has the option to add one to a favorite list. I have searched and searched and cannot find the proper way of doing this. I did get one open source project, everything worked until the user removed a favorite. The database would clear the row of data, but when a new row is added, it would behave as if the deleted row still had data, leaving blanks in the favorite list.
this is my insert method
public long insertString(String newString)
{
ContentValues newStringValue = new ContentValues();
newStringValue.put(KEY_STRING, newString);
return db.insert(DATABASE_TABLE, null, newStringValue);
}
the long returned will always increment even if i use the remove method:
public boolean removeString(long _rowIndex)
{
return db.delete(DATABASE_TABLE, KEY_ID + "=" + _rowIndex, null) > 0;
}
if i try to remove the third index, and the user removed a question at the third index, the method returns false, is there a way to completely remove all rows with no data?
You should use a CursorAdapter or ResourceCursorAdapter and when you modify the data call cursor.requery() to refresh everything.
Maybe just encode String List as something like JSON, then save as long string (blob / clob)? I would use Jackson JSON processor, but there are many alternatives to choose from (Guice, or XStream if you prefer XML). I mean, assuming you don't really need relational aspects of data (no need to find users with specific list entry by querying) but just need to persist lists.
public static class OrderManager
{
private MyDBOpenHelper _db_Orders;
private static final String GET_Orders = “SELECT * FROM “+Order_TABLE_NAME ;
public OrderManager(Context context)
{
_db_Orders = new MyDBOpenHelper(context);
}
public boolean insert(String orderName, String orderStatus)
{
try
{
SQLiteDatabase sqlite = _db_Orders.getWritableDatabase();
/*
sqlite.execSQL(“INSERT INTO “+ Order_TABLE_NAME +
” (” + KEY_NAME +”, “+ KEY_STATUS + “)” +
” VALUES (‘” + orderName + “‘, ‘” + orderStatus + “‘)”);
*/
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_NAME, orderName);
initialValues.put(KEY_STATUS, orderStatus);
sqlite.insert(Order_TABLE_NAME, null, initialValues);
}
catch(SQLException sqlerror)
{
Log.v(“Insert ERROR”, sqlerror.getMessage());
return false;
}
return true;
}
public ArrayList<Order> getOrders()
{
ArrayList<Order> orders = new ArrayList<Order>();
SQLiteDatabase sqliteDB = _db_Orders.getReadableDatabase();
Cursor crsr = sqliteDB.rawQuery(GET_Orders, null);
Log.v(“Select Query result”, String.valueOf(crsr.getCount()) );
crsr.moveToFirst();
for(int i=0; i < crsr.getCount(); i++)
{
orders.add(new Order(crsr.getString(0), crsr.getString(1)));
//Log.v(“DATA”, crsr.getString(0) + ” ” +crsr.getString(1));
crsr.moveToNext();
}
return orders;
}
}

Categories

Resources