I am trying to insert 1120 records (records=questions since it is trivia game) in my database but it is taking around 20secs i can't even work with insertHelper because it has been deprecated in android.
i searched a lot and used beginTransaction(),setTransactionSuccessful() & db.endTransaction(); but nothing helped. maybe i haven't used them correct so please correct me if it's wrong
HelperClass
private void addingeachquestions(Questions question) {
SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction();
try {
ContentValues values = new ContentValues();
values.put(QUESTION, question.getQUESTION());
values.put(OPTION1, question.getOPT1());
values.put(ANSWER, question.getANSWER());
values.put(ANSWER2, question.getANSWER2());
db = this.getWritableDatabase();
db.insert(TABLE_NAME, null, values);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
public void addquestions() {
//famous people
Questions q1 = new Questions("Who was the first African American to have served as president of United States of America ?", "BAROBAACKMAQCAEMBD", "BARACK", "OBAMA");
this.addingeachquestions(q1);
Questions q2 = new Questions("Who co-founded Apple company with Steve Wozniak, Ronald Wayne ?", "TSOVWIBYUBZRGOEJSE", "STEVE", "JOBS");
this.addingeachquestions(q2);
MainActivityClass
demoHelperClass = new DemoHelperClass(this);
SQLiteDatabase sqLiteDatabase = demoHelperClass.getWritableDatabase();
demoHelperClass.addquestions();
I have used below method for around 1,00,000 rows insert and definitely faster than other. You can try it.
Instead of one bye one data insert, directly beginTransaction and insert all data and complete transaction.
Add below code(function) in DatabaseHelper(/DbHelper) class and call that function with arraylist of custom class(DataModel class).
Make some adding/changes as per your requirement:-
public void insertBigDataQuickly(ArrayList<DataModel> arrayList) {
SQLiteDatabase db = this.getWritableDatabase(); //db is instance of DatabaseHelper(/DBHelper) class
db.beginTransaction();
try {
String sql = "Insert or Replace into table_name (column1, column2, column3) values(?,?,?)";
SQLiteStatement statement = db.compileStatement(sql);
for (int i = 0; i < arrayList.size(); i++) { //Loop to insert all data one-by-one with Arraylist data
DataModel singleData = arrayList.get(i);
statement.bindString(1, singleData.getValue1()); //1 - Index value of column
statement.bindLong(2, singleData.getValue2()); //2 - Index value of column
statement.bindDouble(3, singleData.getValue3()); //3 - Index value of column
statement.executeInsert();
}
db.setTransactionSuccessful(); // This commits the transaction
}catch (Exception e) {
e.printStackTrace();
Log.d("Database error: ",e.getMessage());
}
finally {
db.endTransaction();
}
db.close();
}
You can collect your data, put it in a list, then iterate through the list inside a transaction like so:
private void addAllQuestions(Arraylist<Questions> allQuestions) {
SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction();
try {
ContentValues values = new ContentValues();
for (Questions question: allQuestions) {
values.put(QUESTION, question.getQUESTION());
values.put(OPTION1, question.getOPT1());
values.put(ANSWER, question.getANSWER());
values.put(ANSWER2, question.getANSWER2());
db = this.getWritableDatabase();
db.insert(TABLE_NAME, null, values);
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
public void addquestions() {
//famous people
ArrayList<Questions> allQuestions = new ArrayList<Questions>();
allQuestions.append(new Questions("Who was the first African American to have served as president of United States of America ?", "BAROBAACKMAQCAEMBD", "BARACK", "OBAMA"));
allQuestions.append(new Questions("Who co-founded Apple company with Steve Wozniak, Ronald Wayne ?", "TSOVWIBYUBZRGOEJSE", "STEVE", "JOBS"));
this.addAllQuestions(allQuestions);
}
Based on this: https://stackoverflow.com/a/32088155/4268599
Related
I am facing challenge where i am unable to insert new record into table, rather it overwrites the first record in the table.
This happens in the physical device where as it is working fine in the emulator.
Following is the code used to insert the record:
Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss", Locale.getDefault());
String strDate = formatter.format(date);
//SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING);
SQLiteDatabase db = this.getWritableDatabase();
/*ContentValues values = new ContentValues();
//values.put("UserId",1);
values.put("NoQPassed", scoreValues.get("NoPassed"));
values.put("NoQFailed", scoreValues.get("NoFailed"));
values.put("NoQSkipped", scoreValues.get("NoSkipped"));
values.put("SubjectName", scoreValues.get("strSubjectName"));
values.put("CompletedDateTime", strDate);
intRetVal= db.insert(score_Table_Name, null, values);*/
String strQuery="insert into "+score_Table_Name+" values ('"+strDate+"','"+scoreValues.get("NoPassed")+
"','"+scoreValues.get("NoFailed")+"','"+scoreValues.get("NoSkipped")+"','"+scoreValues.get("strSubjectName")+"')";
db.execSQL(strQuery);
db.close();
Tried inserting using db.insert and db.executeSQL, but none help. Can someone help me where i am going wrong?
I didnt add any primary key or autoincrement key to make sure the conflict is not because of that column. Do we always need to have primary key to insert new record?
you can use below getCount() method to count occurrences. if getCount(name)== 0 then do inserting. otherwise not inserting and try to log.
public int getCount(String name) {
Cursor c = null;
try {
db = Dbhelper.getReadableDatabase();
String query = "select count(*) from TableName where name = ?";
c = db.rawQuery(query, new String[] {name});
if (c.moveToFirst()) {
return c.getInt(0);
}
return 0;
}
finally {
if (c != null) {
c.close();
}
if (db != null) {
db.close();
}
}
}
But this logic may not be valid if you say you override it. I think there is no override possibilities in that android sqlite. Please check you might be drop your database any where before inserting new record. It may seems like override data
I'm creating a forum application and I currently if I delete a thread I'm deleting all threads.
Is there a good method or query to check if the UserId == ThreadId?
My current code:
public void deleteThread() {
SQLiteDatabase db = this.getWritableDatabase();
// Delete All Rows
db.delete(TABLE_THREAD, null, null);
db.close();
Log.d(TAG, "Deleted all Thread info from sqlite");
}
You need to pass correct value to the well-documented delete method to narrow down the scope of deletion to a subset of all entries in the DB table.
public void deleteThreadById(String threadId) {
SQLiteDatabase db = this.getWritableDatabase();
String whereClause = "threadId = " + threadId;
db.delete(TABLE_THREAD, whereClause, null);
db.close();
}
Deleting all threads of a given user via their userId would be similar but probably doesn't make sense in a forum software.
This is how SQL works in general and it's a bit scary you started development without familiarising yourself with the very basics.
Something like this;
public void deleteThread(String threadName) {
SQLiteDatabase db = this.getWritableDatabase();
try {
db.delete(MYDATABASE_TABLE, "name = ?", new String[]{threadName});
} catch (Exception e) {
e.printStackTrace();
} finally {
db.close();
}
}
Something long these lines, querying database to find the specific row that has column which matches the parameter.
For example to delete a row which the name column is "Hello World";
deleteThread("Hello World");
How can i get the autoincrement value in thansaction body?
Code
public void insertAllStudents(List<Student> students) {
String sql = "INSERT INTO "+ StudentEntry.TABLE_NAME +" VALUES (?,?,?,?,?);";
SQLiteDatabase db = this.getWritableDatabase();
SQLiteStatement statement = db.compileStatement(sql);
db.beginTransaction();
for (Student student: students) {
statement.clearBindings();
statement.bindString(2, student.getId());
statement.bindString(3, student.getFirstName());
statement.bindString(4, student.getLastName());
statement.bindLong(5, student.getBirthday());
statement.execute();
}
db.setTransactionSuccessful();
db.endTransaction();
}
The first column (_ID) is autoincrement field. Is it opportunity to get this value?
student.getId() -that's not id from database, that's different id.
If you change your code to use db.insert(), this method returns the id of the inserted row - see Get generated id after insert.
There is also a specialised SQLite function to get the last inserted row if you'd prefer to keep compiling statements, see Best way to get the ID of the last inserted row on SQLite
edit: example using db.insert(). This isn't tested but should be pretty close to functional.
db.beginTransaction();
boolean success = true;
final ContentValues values = new ContentValues();
for (final Student student: students) {
values.put("student_id", student.getId());
values.put("first_name", student.getFirstName());
values.put("last_name", student.getLastName());
values.put("birthday", student.getBirthday());
final long id = db.insert("my_table", null, values);
if (id == -1) {
success = false;
break;
}
// TODO do your thing with id here.
}
if (success) {
db.setTransactionSuccessful();
}
db.endTransaction();
Instead of statement.execute(), you can do statement.executeInsert(). This returns the row ID of the inserted row. Or, as #Tom suggested, you can use db.insert() instead, and it will also return the inserted row ID. Using a compiled statement like you are doing now is faster though.
If you want to try the db.insert() approach, it would look something like this:
ContentValues values = new ContentValues();
for (Student student: students) {
// use whatever constants you have for column names instead of these:
values.put(COLUMN_STUDENT_ID, student.getId());
values.put(COLUMN_STUDENT_FIRSTNAME, student.getFirstName());
values.put(COLUMN_STUDENT_LASTNAME, student.getLastName());
values.put(COLUMN_STUDENT_BIRTHDAY, student.getBirthday());
db.insert(StudentEntry.TABLE_NAME, null, values);
}
I saw in the SQLite documentation that you can not insert multiple records at the same time. For example, I have 2 TEXT fields and at the same time I want to insert in filed1 10 records with the date that goes from today to 10 days, and in the field2 value of 50 was added in the 10 record. I hope I explained.
Now normally I insert the record in this way:
public void insertDb(View v) {
ContentValues cv = new ContentValues();
cv.put(Table.ONE, mNe.getText().toString());
cv.put(Table.ONE, mNel.getText().toString());
...
for that you have to use for loop or anything
like below code
public void add_device(String data,
ArrayList<HashMap<String, String>> jsonlist) {
try {
database = this.getWritableDatabase();
for (HashMap<String, String> map : jsonlist) {
ContentValues values = new ContentValues();
values.put(SAVE_COLUMN_NAME, data);
values.put(SAVE_COLUMN_KEY, map.get(SAVE_COLUMN_KEY));
values.put(SAVE_COLUMN_VALUE, map.get(SAVE_COLUMN_VALUE));
Long int1 = database.insertOrThrow(SAVE_TABLE_NAME, null,
values);
Log.i("inserted value", values + "");
Log.i("insserted value ", int1 + "");
}
}
catch (Exception e) {
}
}
you can use loop like i have used
In my application I am saving a bill number in SQLite database. Before I add a new bill number how to check if the bill number exists in the DB.
My main class code is,
String bill_no_excist_or_not = db.billno_exist_or_not(""+et_bill_number.getText().toString());
Log.v("Bill No", ""+bill_no_excist_or_not);
My DB Code,
String billno_exist_or_not(String bill_number){
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_BILL_DETAILS, new String[] { KEY_BILL_NUMBER }, KEY_BILL_NUMBER + "=?"
+ new String[] { bill_number }, null, null, null, null);
//after this i don't know how to return the values
return bill_number;
}
I don't know how to check the values which is already available or not in DB. Can any one know please help me to solve this problem.
Here is the function that helps you to find whether the value is available in database or not.
Here please replace your query with my query..
public int isUserAvailable(int userId)
{
int number = 0;
Cursor c = null;
try
{
c = db.rawQuery("select user_id from user_table where user_id = ?", new String[] {String.valueOf(userId)});
if(c.getCount() != 0)
number = c.getCount();
}
catch(Exception e) {
e.printStackTrace();
} finally {
if(c!=null) c.close();
}
return number;
}
Make your KEY_BILL_NUMBER column in your table UNIQUE and you can just insert using insertWithOnConflict with the flag SQLiteDatabase.CONFLICT_IGNORE