Database Helper class? - java

I am having trouble getting my database to effectively store information. I am using Android Studio and I am trying to create a sqlite db on the fly and insert information into it.
I am not able to insert information into my table ( I am returning a -1), however, I am not sure if the problem is the insert statement or the table/db creation.
Here is the code. Any help would be appreciated.. I have been banging my head on this for a while now.
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = "DatabaseHelper";
SQLiteDatabase database;
private static final String Database_Name = "CISP_340.db";
private static final String Table_Name = "ANIMALS";
private static final String col1 = "_ID";
private static final String col2 = "ANIMAL_TYPE_CD";
private static final String col3 = "COUNT_NO";
private static final String col4 = "SEENON_DTM";
private static final String col5 = "COMMENTS_TXT";
public DatabaseHelper(Context context){
super(context, Table_Name, null, 1);
database = getWritableDatabase();
}
#Override
public void onCreate(SQLiteDatabase db) {
String createTable = "CREATE TABLE " + Table_Name + " (ID INTEGER PRIMARY KEY AUTOINCREMENT, "+
col2 + " INTEGER DEFAULT 0, " +
col3 +" INTEGER, " +
col4 + " TEXT, " +
col5 + " TEXT)";
db.execSQL(createTable);
}
#Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
db.execSQL("DROP IF TABLE EXISTS " + Table_Name);
onCreate(db);
}
public boolean addData(Animal animal){
ContentValues contentValues = new ContentValues();
contentValues.put(col5, animal.getComments());
Log.d(TAG, "addData: Adding " + animal.toString() + " to " + Table_Name);
long result = database.insert(Table_Name, null, contentValues);
if (result == -1) {
return false;
}else{
return true;
}
}
public Cursor getData(){
SQLiteDatabase db = this.getWritableDatabase();
String query = "SELECT * FROM " + Table_Name;
Cursor data = db.rawQuery(query, null);
return data;
}
}
Here is my animal Class:
public class Animal {
Animal(){
//Blank
}
Animal(int animalType, int count, String seenOn, String comments){
this.animalType = animalType;
this.count = count;
this.seenOn = seenOn;
this.comments = comments;
}
private int animalType;
private int count;
private String seenOn;
private String comments;
public int getAnimalType() {
return animalType;
}
public void setAnimalType(int type){
this.animalType = type;
}
public int getCount() {
return count;
}
public void setCount(int count){
this.count = count;
}
public String getSeenOn() {
return seenOn;
}
public void setSeenOn(String seenOn){
this.seenOn = seenOn;
}
public String getComments() {
return comments;
}
public void setComments(String comments){
this.comments = comments;
}
#Override
public String toString(){
return "Animal type: " + animalType + ", Animal count: " + count + ", Animal was seen on: " + seenOn + ", Comments about encounter: " + comments;
}
}
Here is my MainActivity:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
DatabaseHelper dataBaseHelper;
private Button btnAdd, btnView;
private EditText editText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.editText);
btnAdd = (Button) findViewById(R.id.btnAdd);
btnView = (Button) findViewById(R.id.btnView);
dataBaseHelper = new DatabaseHelper(this);
Animal myAnimal = new Animal(1, 0, "Yes", "Raining");
Animal myAnimal2 = new Animal(1, 0, "No", "");
addAnimal(myAnimal);
addAnimal(myAnimal2);
btnAdd.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
Animal animal = new Animal();
animal.setComments(editText.getText().toString());
if (editText.length() != 0){
addAnimal(animal);
editText.setText("");
}else{
returnMessage("You must put something into this field");
}
}
});
btnView.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
Intent intent = new Intent(MainActivity.this, ListDataActivity.class);
startActivity(intent);
}
});
}
public void addAnimal( Animal animal ){
boolean insertData = dataBaseHelper.addData(animal);
if (insertData){
returnMessage("Success");
}else{
returnMessage("Fail");
}
}
private void returnMessage(String message){
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}
Output in LogCat when attempting to insert in the constructor:
12-02 17:20:23.624 4100-4100/edu.davenport.cisp340.animaltracker E/SQLiteDatabase: Error inserting COUNT_NO=0 ANIMAL_TYPE_CD=1 SEENON_DTM=Yes COMMENTS_TXT=Raining
android.database.sqlite.SQLiteException: table ANIMALS has no column named SEENON_DTM (code 1): , while compiling: INSERT INTO ANIMALS(COUNT_NO,ANIMAL_TYPE_CD,SEENON_DTM,COMMENTS_TXT) VALUES (?,?,?,?)
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:500)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1472)
at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1343)
at edu.davenport.cisp340.animaltracker.DatabaseHelper.addData(DatabaseHelper.java:59)
at edu.davenport.cisp340.animaltracker.MainActivity.addAnimal(MainActivity.java:65)
at edu.davenport.cisp340.animaltracker.MainActivity.onCreate(MainActivity.java:32)
at android.app.Activity.performCreate(Activity.java:6980)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6540)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

Edit
Now that you added the log. The issue is that column SEENON_DTM doesn't exist.
As per :-
table ANIMALS has no column named SEENON_DTM
You have probably added the column since running the App. Just amending the SQL used by the onCreate method isn't enough to change the structure of the database. That is onCreate is only run once when the database is created, the database is then saved to a file and hence how it stays around. Subequent instantation of the DatabaseHelper, find the file and doesn't call onCreate.
The fix, if losing any data (no useful data would likely exist) isn't an issue is to do one of the following;
delete the App's data (from settings), or
uninstall the App, or
increase the database version i.e. change super(context, Table_Name, null, 1); to super(context, Table_Name, null, 2); (1 to 2)
(this will result in the onUpgrade method running which should drop the table (see note below about using DROP TABLE IF EXISTS and not DROP IF TABLE EXISTS))
and then rerun the App.
I believe that you code is not an issue (the only issue in the code is with DROP IF TABLE EXISTS, it should be DROP TABLE IF EXISTS ).
Your code works as expected (see below), so the issue is either how you are checking the data or that the Animal class is the cause.
Below is code that uses you DatabaseHelper code and invokes it from an Activity (the Animal class may be different to yours).
I'd suggest trying the code below, suitably adjusted for your DatabaseHelper class (i.e. change AnimalDBhelper to DatabaseHelper) and then checking the log. The output should be as below (perhaps with more rows if you have added rows and the database hasn't been deleted).
Testing
Using a copy of your code (renaming the class to AnimalDBhelper to suit my testing environment) and then using the following code in an activity (the invoking code) :-
public class MainActivity extends AppCompatActivity {
AnimalDBhelper mADBHlpr;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
// Create two animals
mADBHlpr = new AnimalDBhelper(this);
Animal myanimal1 = new Animal(1,0,"Yes","Raining");
Animal myanimal2 = new Animal(1,0,"No","");
mADBHlpr.addData(myanimal1); // Add the first animal
Cursor csr = mADBHlpr.getData(); get the data
DatabaseUtils.dumpCursor(csr); dump the data (write it to the log)
mADBHlpr.addData(myanimal2); // Add the 2nd
csr = mADBHlpr.getData();
DatabaseUtils.dumpCursor(csr);
csr.close(); // Done with the cursor so close
}
}
Result :-
12-02 19:37:54.040 1172-1172/? D/DatabaseHelper: addData: Adding ?.Animal#534af570 to ANIMALS
12-02 19:37:54.044 1172-1172/? I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor#534a5df8
12-02 19:37:54.044 1172-1172/? I/System.out: 0 {
12-02 19:37:54.044 1172-1172/? I/System.out: ID=1
12-02 19:37:54.044 1172-1172/? I/System.out: ANIMAL_TYPE_CD=0
12-02 19:37:54.044 1172-1172/? I/System.out: COUNT_NO=null
12-02 19:37:54.044 1172-1172/? I/System.out: SEENON_DTM=null
12-02 19:37:54.044 1172-1172/? I/System.out: COMMENTS_TXT=Raining
12-02 19:37:54.044 1172-1172/? I/System.out: }
12-02 19:37:54.044 1172-1172/? I/System.out: <<<<<
12-02 19:37:54.044 1172-1172/? D/DatabaseHelper: addData: Adding ?.Animal#534af5c4 to ANIMALS
12-02 19:37:54.048 1172-1172/? I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor#534ab7d4
12-02 19:37:54.048 1172-1172/? I/System.out: 0 {
12-02 19:37:54.048 1172-1172/? I/System.out: ID=1
12-02 19:37:54.048 1172-1172/? I/System.out: ANIMAL_TYPE_CD=0
12-02 19:37:54.048 1172-1172/? I/System.out: COUNT_NO=null
12-02 19:37:54.048 1172-1172/? I/System.out: SEENON_DTM=null
12-02 19:37:54.048 1172-1172/? I/System.out: COMMENTS_TXT=Raining
12-02 19:37:54.048 1172-1172/? I/System.out: }
12-02 19:37:54.048 1172-1172/? I/System.out: 1 {
12-02 19:37:54.048 1172-1172/? I/System.out: ID=2
12-02 19:37:54.048 1172-1172/? I/System.out: ANIMAL_TYPE_CD=0
12-02 19:37:54.048 1172-1172/? I/System.out: COUNT_NO=null
12-02 19:37:54.048 1172-1172/? I/System.out: SEENON_DTM=null
12-02 19:37:54.048 1172-1172/? I/System.out: COMMENTS_TXT=
12-02 19:37:54.048 1172-1172/? I/System.out: }
12-02 19:37:54.048 1172-1172/? I/System.out: <<<<<

You haven't really described what's going wrong (are you querying the Cursor and not finding the data you expect?), but you need to close the cursor somewhere (see this answer), and you don't need to get the database in getComment() since you already have it. Here's a version that ought to work in your example class.
public String getComment(){
String query = "SELECT * FROM " + Table_Name;
String comments = "";
Cursor data = database.rawQuery(query, null);
if( data.moveToFirst() ) { // iterate all the rows of the table
do {
String val = data.getString(4); // pull out column 5
// String val = data.getString(data.getColumnIndex(col5)); // or this way if you prefer
comments += val; // do something with the data - e.g. rebuild Animal object
} while (data.moveToNext());
}
data.close();
return comments;
}

Related

Failed to read row 0, column -1 from a CursorWindow which has 1 rows, 9 columns

I'm trying to load data from my table in sqlite Database to my ExpandableListView inside my activity. I followed the answer from this question Android ExpandableListView and SQLite Database.
My parent list will show MVP_INDUSTRY_TYPE Column depends on date Selected,
My child list will show MVP_BRCH_CODE_NAME and MVP_BRCH_ADDRESS.
DatabaseHelper. java
package com.example.spmapp;
import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import androidx.annotation.Nullable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class DataBaseHelper extends SQLiteOpenHelper {
public static final String MVP_TBL = "MVP_tbl";
public static final String MVP_BRCH_CODE_NAME = "MVP_BRCH_CODE_NAME";
public static final String MVP_ID = "MVP_ID";
public static final String MVP_BRCH_ADDRESS = "MVP_BRCH_ADDRESS";
public static final String MVP_AREA = "AREA";
public static final String MVP_AREA_CODE = "AREA_CODE";
public static final String MVP_INDUSTRY_TYPE = "MVP_INDUSTRY_TYPE";
public static final String token = "TOKEN";
public static final String MVP_DATE = "SCHEDULED_DATE";
public static final String MVP_CLASS_ID = "MVP_CLASS_ID";
public DataBaseHelper(#Nullable Context context) {
super(context, "taggedList.db", null, 1);
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
String createMVPVirtualTableStatement = "CREATE VIRTUAL TABLE IF NOT EXISTS " + MVP_TBL + " USING FTS3(" + MVP_BRCH_CODE_NAME + ", " + MVP_ID + " , " + MVP_BRCH_ADDRESS + ", " + MVP_AREA + ", " + MVP_AREA_CODE + ", " + MVP_INDUSTRY_TYPE + ", " + token + ", " + MVP_DATE + ", " + MVP_CLASS_ID + ")";
sqLiteDatabase.execSQL(createMVPVirtualTableStatement);
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
onCreate(sqLiteDatabase);
}
public Cursor getSelectedParentMVPDate(String txtMVPDate){
SQLiteDatabase db = this.getWritableDatabase();
String query = "Select * from "+MVP_TBL+" WHERE " +MVP_DATE+ " LIKE '%"+txtMVPDate+"%' LIMIT 50";
return db.rawQuery(query, null);
}
public Cursor getSelectedChildMVPDate(String MVPIndustry){
SQLiteDatabase db = this.getWritableDatabase();
String query = "Select * from "+MVP_TBL+" WHERE " +MVP_INDUSTRY_TYPE+ " LIKE '%"+MVPIndustry+"%' LIMIT 50";
return db.rawQuery(query, null);
}
}
MasterVisitPlan.java
public class MasterVisitPlan extends AppCompatActivity implements AdapterView.OnItemSelectedListener,CalendarAdapter.OnItemListener {
private boolean isBackPressedOnce = false;
public static String email;
public static String VisitDate;
public static String ItemBrnchCodeName;
public static String mrCode;
public static String ClassID;
private static String token;
private static String bearerToken;
public static int counterVisit;
private RecyclerView calendarRecyclerView;
private LocalDate selectedDate;
private TextView monthYearText;
TextView empName, empPos, date;
GoogleSignInClient mGoogleSignInClient;
DrawerLayout drawerLayout;
ImageView gps, empPhoto;
ConstraintLayout calendar;
DataBaseHelper dataBaseHelper;
private Cursor mGroupsCursor; // cursor for list of groups (list top nodes)
private int mGroupIdColumnIndex;
private MyExpandableListAdapter mAdapter;
SimpleCursorAdapter sca;
Cursor csr;
SearchView searchView;
ListView Searchlstview;
#Override
protected void onCreate(Bundle savedIntanceState) {
super.onCreate(savedIntanceState);
setContentView(R.layout.activity_master_visit_plan);
initWidgets();
selectedDate = LocalDate.now();
setMonthView();
setOrRefreshListView();
getCurrentDate();
dataBaseHelper = new DataBaseHelper(MasterVisitPlan.this);
fillMVPdata();
}
private void fillMVPdata(){
mGroupsCursor = dataBaseHelper.getSelectedParentMVPDate(date.getText().toString());
startManagingCursor(mGroupsCursor);
mGroupsCursor.moveToFirst();
ExpandableListView Selectedlstview = (ExpandableListView) findViewById(R.id.MVPListitem);
mAdapter = new MyExpandableListAdapter(mGroupsCursor, this,
R.layout.mvp_list_parent,
R.layout.mvp_list_child,
new String[] {DataBaseHelper.MVP_INDUSTRY_TYPE},
new int[] {R.id.txtMVPParent},
new String[] {DataBaseHelper.MVP_BRCH_CODE_NAME, DataBaseHelper.MVP_BRCH_ADDRESS},
new int[] {R.id.txtviewBrnchCodeName, R.id.txtviewBrchAddr});
Selectedlstview.setAdapter(mAdapter);
}
public class MyExpandableListAdapter extends SimpleCursorTreeAdapter {
public MyExpandableListAdapter(Cursor cursor, Context context,int groupLayout, int childLayout, String[] groupFrom,
int[] groupTo, String[] childrenFrom, int[] childrenTo) {
super(context, cursor, groupLayout, groupFrom, groupTo,
childLayout, childrenFrom, childrenTo);
}
#Override
protected Cursor getChildrenCursor(Cursor cursor) {
#SuppressLint("Range") Cursor childCursor = dataBaseHelper.getSelectedChildMVPDate(cursor.getString(cursor.getColumnIndex("MVP_INDUSTRY_TYPE")));
startManagingCursor(childCursor);
childCursor.moveToFirst();
return childCursor;
}
}
}
Column -1 indicates that the column is not in the Cursor when using the getColumnIndex method.
As the only occurrence of the method, in the provided code, is in the getSelectedChildMVPDate method in the DatabaseHelper class, then that must be where the issue is taking place.
Replicating the essentials of your code with an additional method in DataBaseHelper class :-
public void insertMVPTBLRow(String branchCodeName, long id, String address, String area, String areacode, String industryType, String tkn, String date, String classId) {
ContentValues cv = new ContentValues();
cv.put(MVP_BRCH_CODE_NAME,branchCodeName);
cv.put(MVP_ID,id);
cv.put(MVP_BRCH_ADDRESS,address);
cv.put(MVP_AREA,area);
cv.put(MVP_AREA_CODE,areacode);
cv.put(MVP_INDUSTRY_TYPE,industryType);
cv.put(token,tkn);
cv.put(MVP_DATE,date);
cv.put(MVP_CLASS_ID,classId);
this.getWritableDatabase().insert(MVP_TBL,null,cv);
}
and then using the following code in an activity:-
dataBaseHelper = new DataBaseHelper(this);
dataBaseHelper.getWritableDatabase().delete(DataBaseHelper.MVP_TBL,null,null);
dataBaseHelper.insertMVPTBLRow("B1",100,"StreetX","Area1","A001","I001","tkn001",String.valueOf(System.currentTimeMillis()),"CLASS1");
dataBaseHelper.insertMVPTBLRow("B1",101,"StreetX","Area1","A001","I001","tkn002",String.valueOf(System.currentTimeMillis()),"CLASS1");
mGroupsCursor = dataBaseHelper.getSelectedParentMVPDate("");
startManagingCursor(mGroupsCursor);
mGroupsCursor.moveToFirst();
Cursor cursor = mGroupsCursor;
#SuppressLint("Range") Cursor childCursor = dataBaseHelper.getSelectedChildMVPDate(cursor.getString(cursor.getColumnIndex("MVP_INDUSTRY_TYPE")));
startManagingCursor(childCursor);
childCursor.moveToFirst();
DatabaseUtils.dumpCursor(mGroupsCursor);
DatabaseUtils.dumpCursor(childCursor);
Note empty string passed so all rows are extracted.
Results in a successful run with the Log including:-
2022-06-15 10:55:26.892 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor#2caa87e
2022-06-15 10:55:26.893 I/System.out: 0 {
2022-06-15 10:55:26.893 I/System.out: MVP_BRCH_CODE_NAME=B1
2022-06-15 10:55:26.893 I/System.out: MVP_ID=100
2022-06-15 10:55:26.893 I/System.out: MVP_BRCH_ADDRESS=StreetX
2022-06-15 10:55:26.893 I/System.out: AREA=Area1
2022-06-15 10:55:26.893 I/System.out: AREA_CODE=A001
2022-06-15 10:55:26.893 I/System.out: MVP_INDUSTRY_TYPE=I001
2022-06-15 10:55:26.893 I/System.out: TOKEN=tkn001
2022-06-15 10:55:26.893 I/System.out: SCHEDULED_DATE=1655254526888
2022-06-15 10:55:26.893 I/System.out: MVP_CLASS_ID=CLASS1
2022-06-15 10:55:26.893 I/System.out: }
2022-06-15 10:55:26.893 I/System.out: 1 {
2022-06-15 10:55:26.893 I/System.out: MVP_BRCH_CODE_NAME=B1
2022-06-15 10:55:26.893 I/System.out: MVP_ID=101
2022-06-15 10:55:26.893 I/System.out: MVP_BRCH_ADDRESS=StreetX
2022-06-15 10:55:26.894 I/System.out: AREA=Area1
2022-06-15 10:55:26.894 I/System.out: AREA_CODE=A001
2022-06-15 10:55:26.894 I/System.out: MVP_INDUSTRY_TYPE=I001
2022-06-15 10:55:26.894 I/System.out: TOKEN=tkn002
2022-06-15 10:55:26.895 I/System.out: SCHEDULED_DATE=1655254526889
2022-06-15 10:55:26.895 I/System.out: MVP_CLASS_ID=CLASS1
2022-06-15 10:55:26.895 I/System.out: }
2022-06-15 10:55:26.895 I/System.out: <<<<<
2022-06-15 10:55:26.895 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor#f1451df
2022-06-15 10:55:26.895 I/System.out: 0 {
2022-06-15 10:55:26.895 I/System.out: MVP_BRCH_CODE_NAME=B1
2022-06-15 10:55:26.895 I/System.out: MVP_ID=100
2022-06-15 10:55:26.895 I/System.out: MVP_BRCH_ADDRESS=StreetX
2022-06-15 10:55:26.895 I/System.out: AREA=Area1
2022-06-15 10:55:26.895 I/System.out: AREA_CODE=A001
2022-06-15 10:55:26.895 I/System.out: MVP_INDUSTRY_TYPE=I001
2022-06-15 10:55:26.895 I/System.out: TOKEN=tkn001
2022-06-15 10:55:26.896 I/System.out: SCHEDULED_DATE=1655254526888
2022-06-15 10:55:26.896 I/System.out: MVP_CLASS_ID=CLASS1
2022-06-15 10:55:26.896 I/System.out: }
2022-06-15 10:55:26.896 I/System.out: 1 {
2022-06-15 10:55:26.896 I/System.out: MVP_BRCH_CODE_NAME=B1
2022-06-15 10:55:26.896 I/System.out: MVP_ID=101
2022-06-15 10:55:26.896 I/System.out: MVP_BRCH_ADDRESS=StreetX
2022-06-15 10:55:26.896 I/System.out: AREA=Area1
2022-06-15 10:55:26.896 I/System.out: AREA_CODE=A001
2022-06-15 10:55:26.896 I/System.out: MVP_INDUSTRY_TYPE=I001
2022-06-15 10:55:26.896 I/System.out: TOKEN=tkn002
2022-06-15 10:55:26.896 I/System.out: SCHEDULED_DATE=1655254526889
2022-06-15 10:55:26.896 I/System.out: MVP_CLASS_ID=CLASS1
2022-06-15 10:55:26.896 I/System.out: }
2022-06-15 10:55:26.897 I/System.out: <<<<<
Now considering the message Failed to read row 0, column -1 from a CursorWindow which has 1 rows, 9 columns
Then
The Cursor is positioned at row 0 (not at row -1 which is before the first row)
Of the 9 columns the specified column has not been found.
From the dump of both cursors there are 9 columns.
getColumnIndex has a bug in that it is case sensitive
However, as the above works, this is not an issue with your code although I would strongly suggest changing your code to use cursor.getColumnIndex(/*"MVP_INDUSTRY_TYPE" <<<<< CHANGED*/ DataBaseHelper.MVP_INDUSTRY_TYPE) (obviously the comment could be omitted)
As such the issue is either:-
Elsewhere in your code, or
That the columns name coded/used in the onCreate method have been changed BUT that they have not been applied.
The onCreate method runs once and only once when the database is created.
The onCreate method will never automatically run again unless the database is deleted.
Uninstalling the App will delete the database BUT will lose any existing data.
If you need to retain existing data, then you need to rebuild the table with the correct column name, noting that virtual tables has restrictions. You would probably need to utilise the onOpen method and within the method:-
create the new table BUT with a different name
populate the newly created table with the data from the orginal table
drop the original table
rename the newly created table with the original/required name
However, as onOpen runs whenever the database is opened you would want to limit this to only do the above when required (i.e. when there is a naming discrepancy). The following onOPen method could be the basis
:-
#Override
public void onOpen(SQLiteDatabase db) {
super.onOpen(db);
Log.d("ONOPEN","ON OPEN INVOKED");
Cursor checkit = db.query(MVP_TBL,null,null,null,null,null,null,"1");
boolean needToProceed = false;
for (String s: new String[]{MVP_AREA,MVP_AREA_CODE,MVP_DATE,MVP_ID,MVP_BRCH_ADDRESS,MVP_BRCH_CODE_NAME,MVP_CLASS_ID,MVP_INDUSTRY_TYPE,token}) {
boolean found = false;
for (String cc: checkit.getColumnNames()) {
if (cc.equals(s)) {
Log.d("ONOPEN","Column " + cc + " matched " + s);
found = true;
break;
}
}
if (!found) {
Log.d("ONOPEN","!!!!COLUMN " + s + " NOT MATCHED.!!!!" );
needToProceed = true;
break;
}
}
if (!needToProceed) return;
Log.d("ONOPEN","PROCEEDING WITH RECREATION OF " + MVP_TBL +" TABLE.");
String renamed = "ORIGINAL_" + MVP_TBL;
db.execSQL("ALTER TABLE " + MVP_TBL + " RENAME TO " + renamed + ";");
onCreate(db);
db.execSQL("INSERT INTO " + renamed + " SELECT * FROM " + MVP_TBL);
db.execSQL("DROP TABLE IF EXISTS " + MVP_TBL);
db.execSQL("ALTER TABLE " + renamed + " RENAME TO " + MVP_TBL);
}
The Logging should be removed if distributing the App.

SQLite database not getting copied (No such a table exists error)

I think my database is not getting copied cause my database file in the assets folder is 32KB and the file that shows up in the device file explorer is 12KB. So I tried uploading database file from device file explorer then there was no errors. Please can somebody help me fix this?
This is the error I'm getting
This is my DatabaseHelper class
public class DatabaseAdapter {
DatabaseHelper helper;
SQLiteDatabase db;
List<Contacts> contactsList = new ArrayList<>();
List<Station> stationsList = new ArrayList<>();
List<Tip> tipsList = new ArrayList<>();
public DatabaseAdapter(Context context) {
helper = new DatabaseHelper(context);
db = helper.getWritableDatabase();
}
public List<Contacts> getAllContacts() {
String[] columns = {DatabaseHelper.KEY_NAME, DatabaseHelper.KEY_POSITION, DatabaseHelper.KEY_STATION, DatabaseHelper.KEY_PHONE_NUMBER, DatabaseHelper.KEY_EMAIL};
Cursor cursor = db.query(DatabaseHelper.TABLE_NAME1, columns, null, null, null, null, null, null);
while (cursor.moveToNext()) {
int index2 = cursor.getColumnIndex(DatabaseHelper.KEY_NAME);
String name = cursor.getString(index2);
int index3 = cursor.getColumnIndex(DatabaseHelper.KEY_POSITION);
String position = cursor.getString(index3);
int index4 = cursor.getColumnIndex(DatabaseHelper.KEY_STATION);
String station = cursor.getString(index4);
int index5 = cursor.getColumnIndex(DatabaseHelper.KEY_PHONE_NUMBER);
String phone_number = cursor.getString(index5);
int index6 = cursor.getColumnIndex(DatabaseHelper.KEY_EMAIL);
String email = cursor.getString(index6);
Contacts contact = new Contacts(name, position, station, phone_number, email);
contactsList.add(contact);
}
return contactsList;
}
public List<Station> getAllStations() {
String[] columns = {DatabaseHelper.KEY_S_NAME, DatabaseHelper.KEY_S_ADDRESS, DatabaseHelper.KEY_S_PHONE_NUMBER, DatabaseHelper.KEY_S_TOTAL_FIGHTERS, DatabaseHelper.KEY_S_TOTAL_VEHICLES, DatabaseHelper.KEY_S_LAT, DatabaseHelper.KEY_S_LON};
Cursor cursor = db.query(DatabaseHelper.TABLE_NAME2, columns, null, null, null, null, null, null);
while (cursor.moveToNext()) {
int index1 = cursor.getColumnIndex(DatabaseHelper.KEY_S_NAME);
String name = cursor.getString(index1);
int index2 = cursor.getColumnIndex(DatabaseHelper.KEY_S_ADDRESS);
String address = cursor.getString(index2);
int index3 = cursor.getColumnIndex(DatabaseHelper.KEY_S_PHONE_NUMBER);
String phone_number = cursor.getString(index3);
int index4 = cursor.getColumnIndex(DatabaseHelper.KEY_S_TOTAL_FIGHTERS);
int total_f = cursor.getInt(index4);
int index5 = cursor.getColumnIndex(DatabaseHelper.KEY_S_TOTAL_VEHICLES);
int total_v = cursor.getInt(index5);
int index6 = cursor.getColumnIndex(DatabaseHelper.KEY_S_LAT);
String lat = cursor.getString(index6);
int index7 = cursor.getColumnIndex(DatabaseHelper.KEY_S_LON);
String lon = cursor.getString(index7);
Station station = new Station(name, address, phone_number, total_f, total_v, lat, lon);
stationsList.add(station);
}
return stationsList;
}
public List<Tip> getAllTips() {
String[] columns = {DatabaseHelper.KEY_TIP_TOPIC, DatabaseHelper.KEY_TIP_SUB_TOPIC};
Cursor cursor = db.query(DatabaseHelper.TABLE_NAME3, columns, null, null, null, null, null, null);
while (cursor.moveToNext()) {
int index2 = cursor.getColumnIndex(DatabaseHelper.KEY_TIP_TOPIC);
String topic = cursor.getString(index2);
int index3 = cursor.getColumnIndex(DatabaseHelper.KEY_TIP_SUB_TOPIC);
String sub_topic = cursor.getString(index3);
Tip tip = new Tip(topic, sub_topic);
tipsList.add(tip);
}
return tipsList;
}
private static class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "Firefighters.db";
private static final String TABLE_NAME1 = "contact_list";
private static final String TABLE_NAME2 = "station_list";
private static final String TABLE_NAME3 = "tips";
private static final int DATABASE_VERSION = 2;
private static final String KEY_NAME = "name";
private static final String KEY_POSITION = "position";
private static final String KEY_STATION = "station";
private static final String KEY_PHONE_NUMBER = "phone_number";
private static final String KEY_EMAIL = "email";
private static final String KEY_S_NAME = "name";
private static final String KEY_S_ADDRESS = "address";
private static final String KEY_S_PHONE_NUMBER = "phone_number";
private static final String KEY_S_TOTAL_FIGHTERS = "total_fighters";
private static final String KEY_S_TOTAL_VEHICLES = "total_vehicles";
private static final String KEY_S_LAT = "lat";
private static final String KEY_S_LON = "long";
private static final String KEY_TIP_TOPIC = "tip_topic";
private static final String KEY_TIP_SUB_TOPIC = "tip_sub_topic";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onOpen(SQLiteDatabase db) {
super.onOpen(db);
db.disableWriteAheadLogging();
}
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
}
This is my database copy class
public class PreCreateDB {
public static void copyDB(Context context){
try{
String destPath = "/data/data/"+ context.getPackageName()
+ "/databases";
File f = new File(destPath);
if(!f.exists()){
f.mkdir();
rawCopy(context.getAssets().open("Firefighters.db"), new FileOutputStream(destPath + "/Firefighters.db"));
}
} catch (IOException e){
e.printStackTrace();
}
}
public static void rawCopy(InputStream inputStream, OutputStream outputStream) throws IOException{
byte[] buffer = new byte[1024];
int length;
while((length = inputStream.read(buffer)) > 0){
outputStream.write(buffer, 0, length);
}
inputStream.close();
outputStream.close();
}
}
And this is how I call them
PreCreateDB.copyDB(mContext);
databaseAdapter = new DatabaseAdapter(mContext);
stationsList = databaseAdapter.getAllStations();
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(mContext);
recyclerView.setLayoutManager(layoutManager);
stationsAdapter = new StationsAdapter(mContext, stationsList, recyclerView);
recyclerView.setAdapter(stationsAdapter);
-- Solution that worked for me --
I tried everything and none of them seem to work so then I tried this SQLiteAssetHelper library and it worked! All I did was extend Database helper with SQLiteAssetHelper. This is my Database helper now.
private static class DatabaseHelper extends SQLiteAssetHelper {
private static final String DATABASE_NAME = "Firefighters.db";
private static final String TABLE_NAME1 = "contact_list";
private static final String TABLE_NAME2 = "station_list";
private static final String TABLE_NAME3 = "tips";
private static final int DATABASE_VERSION = 2;
private static final String KEY_NAME = "name";
private static final String KEY_POSITION = "position";
private static final String KEY_STATION = "station";
private static final String KEY_PHONE_NUMBER = "phone_number";
private static final String KEY_EMAIL = "email";
private static final String KEY_S_NAME = "name";
private static final String KEY_S_ADDRESS = "address";
private static final String KEY_S_PHONE_NUMBER = "phone_number";
private static final String KEY_S_TOTAL_FIGHTERS = "total_fighters";
private static final String KEY_S_TOTAL_VEHICLES = "total_vehicles";
private static final String KEY_S_LAT = "lat";
private static final String KEY_S_LON = "long";
private static final String KEY_TIP_TOPIC = "tip_topic";
private static final String KEY_TIP_SUB_TOPIC = "tip_sub_topic";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
}
Correction
Your issue is that you have other databases/files (thanks to google stuff). So the database folder already exists and therefore it won't copy the file but instead it will open a new database with just the android_metadata table.
Try using :-
public static void copyDB(Context context){
String destPath = context.getDatabasePath("FireFighters.db").getAbsolutePath();
File f = new File(destPath);
if(!f.exists()){
if(!f.getParentFile().exists()) {
f.getParentFile().mkdirs();
}
try {
rawCopy(context.getAssets().open("Firefighters.db"), new FileOutputStream(destPath + "/Firefighters.db"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
So this checks to see if the database file (Firefighters.db) itself exists. If not then it will:-
create the database directory if it doesn't exists
irrespective of the databases directory existing then copy the Firefighters.db.
If Firefighters.db file exists then the file is not copied.
Previous Answer (probably not applicable)
I would suspect that what has been copied is not what you expect it to be. The 12KB along with message (table not found) indicates 2 things. A valid database exists and that it likely has a few components. i.e. (tables,views,indexes,triggers) (each would take up at least 4KB (1 page))
First thing to try is uninstalling the App and rerunning to eliminate an existing attempt leaving a valid but empty component wise (tables etc) database.
It that doesn't resolve the issue then I would suggest adding the following
DatabaseUtils.dumpCursor(databaseAdapter.db.rawQuery("SELECT * FROM sqlite_master",null));
before the line stationsList = databaseAdapter.getAllStations();
This will extract a list of all the components (tables, views triggers, indexes) in the database e.g. something like :-
2022-01-23 13:01:13.611 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor#45ef147
2022-01-23 13:01:13.611 I/System.out: 0 {
2022-01-23 13:01:13.612 I/System.out: type=table
2022-01-23 13:01:13.612 I/System.out: name=android_metadata
2022-01-23 13:01:13.612 I/System.out: tbl_name=android_metadata
2022-01-23 13:01:13.612 I/System.out: rootpage=3
2022-01-23 13:01:13.612 I/System.out: sql=CREATE TABLE android_metadata (locale TEXT)
2022-01-23 13:01:13.612 I/System.out: }
2022-01-23 13:01:13.612 I/System.out: <<<<<
i.e. the above has only the android_metadata table which the SQLiteOpenHelper creates.
Note the above was created using your helper without PreCreateDB,copyDB being called. And low and behold device Explorer shows:-
As such it doesn't look like the PreCreateDB.copyDB is copying the file OR if it is that perhaps it's corrupted in which case SQLiteOpenHelper will prsent you a brand spanking new but empty database bar the android_metadata table.
Additional
Doing a quick test of your code but with a database that contains other tables (for my convenience rather than create one after studying your code) and using outStream().flush.
Then using :-
PreCreateDB.copyDB(this);
databaseAdapter = new DatabaseAdapter(this);
DatabaseUtils.dumpCursor(databaseAdapter.db.rawQuery("SELECT * FROM sqlite_master",null));
results in :-
2022-01-23 13:25:25.439 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor#dda8d74
2022-01-23 13:25:25.440 I/System.out: 0 {
2022-01-23 13:25:25.440 I/System.out: type=table
2022-01-23 13:25:25.440 I/System.out: name=kmmAccounts
2022-01-23 13:25:25.440 I/System.out: tbl_name=kmmAccounts
2022-01-23 13:25:25.440 I/System.out: rootpage=2
2022-01-23 13:25:25.441 I/System.out: sql=CREATE TABLE kmmAccounts (id varchar(32) NOT NULL, institutionId varchar(32), parentId varchar(32), lastReconciled timestamp, lastModified timestamp, openingDate date, accountNumber mediumtext, accountType varchar(16) NOT NULL, accountTypeString mediumtext, isStockAccount char(1), accountName mediumtext, description mediumtext, currencyId varchar(32), balance mediumtext, balanceFormatted mediumtext, transactionCount bigint unsigned, PRIMARY KEY (id))
2022-01-23 13:25:25.441 I/System.out: }
2022-01-23 13:25:25.441 I/System.out: 1 {
2022-01-23 13:25:25.441 I/System.out: type=index
2022-01-23 13:25:25.441 I/System.out: name=sqlite_autoindex_kmmAccounts_1
2022-01-23 13:25:25.441 I/System.out: tbl_name=kmmAccounts
2022-01-23 13:25:25.441 I/System.out: rootpage=3
2022-01-23 13:25:25.441 I/System.out: sql=null
2022-01-23 13:25:25.441 I/System.out: }
2022-01-23 13:25:25.441 I/System.out: 2 {
2022-01-23 13:25:25.441 I/System.out: type=table
2022-01-23 13:25:25.441 I/System.out: name=kmmAccountsPayeeIdentifier
2022-01-23 13:25:25.441 I/System.out: tbl_name=kmmAccountsPayeeIdentifier
2022-01-23 13:25:25.442 I/System.out: rootpage=4
2022-01-23 13:25:25.442 I/System.out: sql=CREATE TABLE kmmAccountsPayeeIdentifier (accountId varchar(32) NOT NULL, userorder smallint unsigned NOT NULL, identifierId varchar(32) NOT NULL, PRIMARY KEY (accountId, userorder))
2022-01-23 13:25:25.442 I/System.out: }
....
Device explorer shows :-
So your code, with the flush added, works. So it's either excluding the flush or the asset file that is at fault and I would guess that the asset file is either not the correct file name, empty component wise or is corrupt.
Corrupt File
If it is corrupt the log should show as such e.g. (an image copied into asset as Firfighters.db) :-
2022-01-23 13:37:07.973 E/SQLiteLog: (26) file is not a database
2022-01-23 13:37:07.974 E/DefaultDatabaseErrorHandler: Corruption reported by sqlite on database: /data/user/0/a.a.so70599236javasqlitenorows/databases/Firefighters.db
2022-01-23 13:37:07.974 E/DefaultDatabaseErrorHandler: deleting the database file: /data/user/0/a.a.so70599236javasqlitenorows/databases/Firefighters.db
2022-01-23 13:37:08.013 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor#dda8d74
2022-01-23 13:37:08.014 I/System.out: 0 {
2022-01-23 13:37:08.014 I/System.out: type=table
2022-01-23 13:37:08.014 I/System.out: name=android_metadata
2022-01-23 13:37:08.014 I/System.out: tbl_name=android_metadata
2022-01-23 13:37:08.014 I/System.out: rootpage=3
2022-01-23 13:37:08.014 I/System.out: sql=CREATE TABLE android_metadata (locale TEXT)
2022-01-23 13:37:08.014 I/System.out: }
2022-01-23 13:37:08.014 I/System.out: <<<<<
Incorrect Named Asset File
renaming the asset to anything other than Firefighters.db (e.g. NotFirefighters.db) results in the log including:-
2022-01-23 13:43:18.204 W/System.err: java.io.FileNotFoundException: Firefighters.db
2022-01-23 13:43:18.204 W/System.err: at android.content.res.AssetManager.nativeOpenAsset(Native Method)
2022-01-23 13:43:18.204 W/System.err: at android.content.res.AssetManager.open(AssetManager.java:744)
2022-01-23 13:43:18.204 W/System.err: at android.content.res.AssetManager.open(AssetManager.java:721)
2022-01-23 13:43:18.204 W/System.err: at a.a.so70599236javasqlitenorows.PreCreateDB.copyDB(PreCreateDB.java:20)
2022-01-23 13:43:18.204 W/System.err: at a.a.so70599236javasqlitenorows.MainActivity.onCreate(MainActivity.java:27)
2022-01-23 13:43:18.204 W/System.err: at android.app.Activity.performCreate(Activity.java:7136)
2022-01-23 13:43:18.204 W/System.err: at android.app.Activity.performCreate(Activity.java:7127)
2022-01-23 13:43:18.205 W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
2022-01-23 13:43:18.205 W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
2022-01-23 13:43:18.205 W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
2022-01-23 13:43:18.205 W/System.err: at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
2022-01-23 13:43:18.205 W/System.err: at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
2022-01-23 13:43:18.205 W/System.err: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
2022-01-23 13:43:18.205 W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
2022-01-23 13:43:18.205 W/System.err: at android.os.Handler.dispatchMessage(Handler.java:106)
2022-01-23 13:43:18.205 W/System.err: at android.os.Looper.loop(Looper.java:193)
2022-01-23 13:43:18.205 W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6669)
2022-01-23 13:43:18.205 W/System.err: at java.lang.reflect.Method.invoke(Native Method)
2022-01-23 13:43:18.205 W/System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
2022-01-23 13:43:18.206 W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
2022-01-23 13:43:18.233 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor#dda8d74
2022-01-23 13:43:18.234 I/System.out: 0 {
2022-01-23 13:43:18.234 I/System.out: type=table
2022-01-23 13:43:18.234 I/System.out: name=android_metadata
2022-01-23 13:43:18.234 I/System.out: tbl_name=android_metadata
2022-01-23 13:43:18.234 I/System.out: rootpage=3
2022-01-23 13:43:18.234 I/System.out: sql=CREATE TABLE android_metadata (locale TEXT)
2022-01-23 13:43:18.234 I/System.out: }
2022-01-23 13:43:18.234 I/System.out: <<<<<
So by adding the sqlite extract and cursor dump, running after uninstalling the App and viewing the log should establish the cause.

SQLite Database Error Newbie

This is my first SQLite App and I found a lot of errors and I don't what to do.
Can anyone tell me what I need to do?
This is my log cat:
12-26 18:58:05.870 26185-26185/? I/art: Late-enabling -Xcheck:jni
12-26 18:58:05.889 26185-26185/? E/Environment: initForCurrentUser:userId= 0
12-26 18:58:05.889 26185-26185/? D/Environment: UserEnvironment current
userId IS : 0
12-26 18:58:05.889 26185-26185/? D/Environment: UserEnvironment PRIMARY
STORAGE IS : MEDIA_INTERNAL
12-26 18:58:05.982 26185-26185/com.example.acer.sqlitecrud I/LoadedApk: No
resource references to update in package com.hmct.hmcttheme
12-26 18:58:06.010 26185-26185/com.example.acer.sqlitecrud W/art: Before
Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
12-26 18:58:06.135 26185-26185/com.example.acer.sqlitecrud E/SQLiteLog: (1)
near "TABLEstudentTable": syntax error
12-26 18:58:06.136 26185-26185/com.example.acer.sqlitecrud D/AndroidRuntime:
Shutting down VM
12-26 18:58:06.138 26185-26185/com.example.acer.sqlitecrud E/AndroidRuntime:
FATAL EXCEPTION: main
Process: com.example.acer.sqlitecrud, PID: 26185
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.acer.sqlitecrud/com.example.acer.sqlitecrud.MainActivity}: android.database.sqlite.SQLiteException: near "TABLEstudentTable": syntax error (code 1): , while compiling: CREATE TABLEstudentTable(ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, MARKS INTEGER)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2328)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2394)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1306)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5270)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:913)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:708)
Caused by: android.database.sqlite.SQLiteException: near "TABLEstudentTable": syntax error (code 1): , while compiling: CREATE TABLEstudentTable(ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, MARKS INTEGER)
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:500)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1674)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1605)
at com.example.acer.sqlitecrud.DatabaseHelper.onCreate(DatabaseHelper.java:27)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:251)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
at com.example.acer.sqlitecrud.DatabaseHelper.<init>(DatabaseHelper.java:22)
at com.example.acer.sqlitecrud.MainActivity.onCreate(MainActivity.java:22)
at android.app.Activity.performCreate(Activity.java:6075)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2281)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2394) 
at android.app.ActivityThread.access$800(ActivityThread.java:151) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1306) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:135) 
at android.app.ActivityThread.main(ActivityThread.java:5270) 
at java.lang.reflect.Method.invoke(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:372) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:913) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:708) 
12-26 18:58:06.249 26185-26185/com.example.acer.sqlitecrud I/Process: Sending signal. PID: 26185 SIG: 9
This is my class:
DatabaseHelper.Java
public class DatabaseHelper extends SQLiteOpenHelper {
public static final String dbName = "Student.db";
public static final String tbName = "studentTable";
public static final String colID = "ID";
public static final String colName = "NAME";
public static final String colMarks = "MARKS";
public DatabaseHelper(Context context) {
super(context, dbName, null, 1);
SQLiteDatabase db = this.getWritableDatabase();
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE"+tbName+"(ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, MARKS INTEGER)");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS"+tbName);
onCreate(db);
}
public boolean insertData (String Name, String Marks){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(colName,Name);
contentValues.put(colMarks,Marks);
long result = db.insert(tbName,null,contentValues);
if (result == -1){
return false;
}else {
return true;
}
}
}
MainActivity.java:
package com.example.acer.sqlitecrud;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
DatabaseHelper myDb;
EditText Name, Marks;
Button addData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myDb = new DatabaseHelper(this);
Name = (EditText)findViewById(R.id.edtNama);
Marks = (EditText)findViewById(R.id.edtNilai);
addData = (Button)findViewById(R.id.btnInsert);
InsertData();
}
private void InsertData() {
addData.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
boolean isInserted = myDb.insertData(Name.getText().toString(),
Marks.getText().toString());
if (isInserted = true){
Toast.makeText(MainActivity.this,"Data Telah Di Inputkan !!",Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(MainActivity.this,"Data Gagal Di Inputkan !!",Toast.LENGTH_SHORT).show();
}
}
});
}
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE "+tbName+"(ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, MARKS INTEGER)");
}
note the space between the TABLE and tbName
Query syntax error, space is missing.
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE "+tbName+"(ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, MARKS INTEGER)");
}
You are missing space in syntax of create table
db.execSQL("CREATE TABLE "+tbName+"(ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, MARKS INTEGER)");
In drop table also you missed the space
"DROP TABLE IF EXISTS "+tbName
check below code
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE "+tbName+"(ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, MARKS INTEGER)"); //add space after TABLE
}

How to prevent duplicate rows when I run android program with sqlite

Hi I am struggling with these two:
i) I created sqlite database for my android app. And added rows through Main Activity. Now, whenever I am running my program, everytime the same rows getting added in database. How to ensure only one time database gets created with all these rows.
ii) I made id (int type) as primary key and made it auto-increment.I don't want primary ID to be auto-incremental and can be set manually for each row. How I can do it?
1. All database related functions have been in this code:
public class DataBaseHandlerActivity extends SQLiteOpenHelper {
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = "shopsManager";
// Shop table name
private static final String TABLE_SHOPS = "shops";
// Shop Table Columns names
private static final String KEY_ID = "shopid";
private static final String KEY_NAME = "shopname";
private static final String KEY_ADDRESS = "shopaddress";
private static final String KEY_CAT1="category1";
private static final String KEY_CAT2="category2";
private static final String KEY_CAT3="category3";
private static final String KEY_CAT4="category4";
private static final String KEY_IMAGE="shopimage";
public DataBaseHandlerActivity(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// Creating Tables
#Override
public void onCreate(SQLiteDatabase db) {
String CREATE_SHOPS_TABLE="CREATE TABLE "+TABLE_SHOPS+"("+KEY_ID+" INTEGER PRIMARY KEY,"+KEY_NAME+" TEXT,"+
KEY_IMAGE+" TEXT,"+
KEY_ADDRESS+" TEXT,"+KEY_CAT1+" TEXT,"+KEY_CAT2+" TEXT,"+KEY_CAT3+" TEXT,"+KEY_CAT4+" TEXT"+
")";
db.execSQL(CREATE_SHOPS_TABLE);
}
// Upgrading database
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Drop older table if existed
db.execSQL("DROP TABLE IF EXISTS"+TABLE_SHOPS);
//CREATE TABLE AGAIN
onCreate(db);
}
/**
* All CRUD(Create, Read, Update, Delete) Operations
*/
//Add a new shop row
void addShop(Shop shop){
SQLiteDatabase db=this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NAME,shop.getShopName());
values.put(KEY_IMAGE,shop.getShopImage());
values.put(KEY_ADDRESS,shop.getShopAddress());
values.put(KEY_CAT1,shop.getShopCat1());
values.put(KEY_CAT2,shop.getShopCat2());
values.put(KEY_CAT3,shop.getShopCat3());
values.put(KEY_CAT4,shop.getShopCat4());
//Inserting row
db.insert(TABLE_SHOPS,null,values);
db.close(); //Close db connection
}
//Get a shop items corresponding to a primary key
Shop getShop(int id){
SQLiteDatabase db=this.getReadableDatabase();
Cursor cursor=db.query(TABLE_SHOPS,new String[]{KEY_ID,KEY_NAME,KEY_IMAGE,KEY_ADDRESS,KEY_CAT1,KEY_CAT2,KEY_CAT3,KEY_CAT4},
KEY_ID +"=?",new String[] { String.valueOf(id) }, null, null, null, null);
if (cursor != null)
cursor.moveToFirst();
Shop shop = new Shop(Integer.parseInt(cursor.getString(0)),
cursor.getString(1), cursor.getString(2),cursor.getString(3),cursor.getString(4),cursor.getString(5),
cursor.getString(6),cursor.getString(7));
// return shop
return shop;
}
// Getting All Shops
public List<Shop> getAllShops() {
List<Shop> shopList = new ArrayList<Shop>();
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_SHOPS;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Shop shop = new Shop();
shop.setShopId(Integer.parseInt(cursor.getString(0)));
shop.setShopName(cursor.getString(1));
shop.setShopImage(cursor.getString(2));
shop.setShopAddress(cursor.getString(3));
shop.setShopCat1(cursor.getString(4));
shop.setShopCat2(cursor.getString(5));
shop.setShopCat3(cursor.getString(6));
shop.setShopCat4(cursor.getString(7));
// Adding contact to list
shopList.add(shop);
} while (cursor.moveToNext());
}
// return shop list
return shopList;
}
// Updating single shop
public int updateShop(Shop shop) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NAME,shop.getShopName());
values.put(KEY_IMAGE,shop.getShopImage());
values.put(KEY_ADDRESS,shop.getShopAddress());
values.put(KEY_CAT1,shop.getShopCat1());
values.put(KEY_CAT2,shop.getShopCat2());
values.put(KEY_CAT3,shop.getShopCat3());
values.put(KEY_CAT4,shop.getShopCat4());
// updating row
return db.update(TABLE_SHOPS, values, KEY_ID + " = ?",
new String[] { String.valueOf(shop.getShopId()) });
}
// Deleting single shop
public void deleteShop(Shop shop) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_SHOPS, KEY_ID + " = ?",
new String[] { String.valueOf(shop.getShopId()) });
db.close();
}
// Getting shops Count
public int getShopsCount() {
String countQuery = "SELECT * FROM " + TABLE_SHOPS;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(countQuery, null);
int count=cursor.getCount();
cursor.close();
db.close() ;
// return count
return count;
}
}
2. Main Activity where I pass data to create table:
package com.trillbit.databaseactivity;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.util.List;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DataBaseHandlerActivity db=new DataBaseHandlerActivity(this);
/**
* CRUD Operations
* */
// Inserting Shops
Log.d("Insert: ", "Inserting ..");
db.addShop(new Shop("Shoppers Stop","shopperstop","1st Floor,Forum Mall","Fashion","Clothes","Home","Shoes"));
db.addShop(new Shop("LifeStyle", "lifestyle", "2nd Floor, Forum Mall", "Fashion", "Clothes","Home", "Mobile"));
db.addShop(new Shop("Ezone", "ezone","3rd Floor, Forum Mall","Mobile","Electronics","Apppliances","Home"));
db.addShop(new Shop("Dominos", "dominos","1st Floor,Forum Mall","Food","Pizza","Cake","Pastery"));
// Reading all shops
Log.d("Reading: ", "Reading all shops..");
List<Shop> shops = db.getAllShops();
for (Shop shop : shops) {
String log = "Id: " + shop.getShopId() + " ,Name: " + shop.getShopName() + " ,Image: " + shop.getShopImage()
+ ",Address: " + shop.getShopAddress() + ",Categort1: " + shop.getShopCat1() + ", Category2: " + shop.getShopCat2()
+ ",Category3: " + shop.getShopCat3() + ",Catgeory4: " + shop.getShopCat4();
// Writing Shops to log
Log.d("Name: ", log);
}
}
}
3.Output in logcat:
D/Name:: Id: 5 ,Name: Shoppers Stop ,Image: shopperstop,Address: 1st Floor,Forunm Mall,Categort1: Fashion, Category2: Clothes,Category3: Home,Catgeory4: Shoes
01-14 16:07:49.687 7993-7993/com.trillbit.databaseactivity D/Name:: Id: 6 ,Name: LifeStyle ,Image: lifestyle,Address: 2nd Floor, Forum Mall,Categort1: Fashion, Category2: Clothes,Category3: Home,Catgeory4: Mobile
01-14 16:07:49.687 7993-7993/com.trillbit.databaseactivity D/Name:: Id: 7 ,Name: Ezone ,Image: ezone,Address: 3rd Floor, Forum Mall,Categort1: Mobile, Category2: Electronics,Category3: Apppliances,Catgeory4: Home
01-14 16:07:49.687 7993-7993/com.trillbit.databaseactivity D/Name:: Id: 8 ,Name: Dominos ,Image: dominos,Address: 1st Floor,Forum Mall,Categort1: Food, Category2: Pizza,Category3: Cake,Catgeory4: Pastery
01-14 16:07:49.687 7993-7993/com.trillbit.databaseactivity D/Name:: Id: 9 ,Name: Shoppers Stop ,Image: shopperstop,Address: 1st Floor,Forum Mall,Categort1: Fashion, Category2: Clothes,Category3: Home,Catgeory4: Shoes
01-14 16:07:49.687 7993-7993/com.trillbit.databaseactivity D/Name:: Id: 10 ,Name: LifeStyle ,Image: lifestyle,Address: 2nd Floor, Forum Mall,Categort1: Fashion, Category2: Clothes,Category3: Home,Catgeory4: Mobile
01-14 16:07:49.687 7993-7993/com.trillbit.databaseactivity D/Name:: Id: 11 ,Name: Ezone ,Image: ezone,Address: 3rd Floor, Forum Mall,Categort1: Mobile, Category2: Electronics,Category3: Apppliances,Catgeory4: Home
01-14 16:07:49.687 7993-7993/com.trillbit.databaseactivity D/Name:: Id: 12 ,Name: Dominos ,Image: dominos,Address: 1st Floor,Forum Mall,Categort1: Food, Category2: Pizza,Category3: Cake,Catgeory4: Pastery
You add the those rows every single time your Activity is created.
Use SharedPreferences to mark a boolean that says your app started once
Create a UNIQUE CONSTRAINT in the database table definition.
It will automatically prevent duplicate entries.
OR
Instead of
INSERT ...
do
INSERT OR IGNORE ...
This means that instead of returning an error code if you violate a constraint, SQLite just returns SQLITE_OK as if the command succeeded.
For others benefit, I am writing how I solved using shared preferences as suggested by cricket-007. At start of main activity, created database when application gets installed and run first time.
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if(!prefs.getBoolean("firstTime", false)) {
// run your one time code
// Inserting Shops
Log.d("Insert: ", "Inserting ..");
db.addShop(new Shop("01","Shoppers Stop","shopperstop","1st Floor,Forum Mall","Fashion","Clothes","Home","Shoes"));
db.addShop(new Shop("02","LifeStyle", "lifestyle", "2nd Floor, Forum Mall", "Fashion", "Clothes","Home", "Mobile"));
db.addShop(new Shop("03","Ezone", "ezone","3rd Floor, Forum Mall","Mobile","Electronics","Apppliances","Home"));
db.addShop(new Shop("04","Dominos", "dominos","1st Floor,Forum Mall","Food","Pizza","Cake","Pastery"));
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("firstTime", true);
editor.commit();
}

error inserting and executing query in android sqlite database

so in my app i am using get and set methods. when it executes the set method, the app doesnt crash but when it gets to the get method, it crashes. i worked out that it crashes when it gets to the db.query() line in the get method but i think the problem could also be in the set method since they both give error messages.
here is my code:
public class MyDBHandler extends SQLiteOpenHelper {
public static final int DATABASE_VERSION = 1;
public static final String COLUMN_ID = "_id";
public static final String TABLE_VALUES = "values";
public static final String COLUMN_TARGET = "target";
public static final String COLUMN_CURRENT = "current";
public MyDBHandler(Context context){
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
String query1 = "CREATE TABLE " + TABLE_VALUES + " (" +
COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
COLUMN_TARGET + " INT, " +
COLUMN_CURRENT + " INT);";
db.execSQL(query1);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldversion, int newversion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_VALUES);
onCreate(db);
}
public void setTarget(int tar){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COLUMN_TARGET, tar);
values.put(COLUMN_CURRENT, 0);
db.insert(TABLE_VALUES, null, values);
db.close();
}
public int getTarget() {
SQLiteDatabase db = this.getReadableDatabase();
int targetVal=0;
String[] columns = {COLUMN_TARGET};
Cursor c = db.query(TABLE_VALUES, columns, null, null, null, null, String.valueOf(1));
if(c.getCount()>0)
{
c.moveToFirst();
targetVal=c.getInt(0);
}
db.close();
c.close();
return targetVal;
}
}
the set function is used here:
public class home extends AppCompatActivity {
MyDBHandler db;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
db = new MyDBHandler(this);
}
public void enter(View view)
{
EditText target = (EditText) findViewById(R.id.target);
TextView warning = (TextView) findViewById(R.id.warning);
String check = target.getText().toString();
if(check.equals("")) {
// Intent a = new Intent(this, MainActivity.class);
//startActivity(a);
warning.setText("Please enter a value");
return;
}
else {
int input = Integer.parseInt(check);
Log.d("tag", "111\n");
db.setTarget(input);
Log.d("tag", "222\n");
//int i = db.getTarget();
//Log.d("tag","input is " + i );
Intent a = new Intent(this, MainActivity.class);
startActivity(a);
}
}
}
the get function is used here:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onTrack(View view){
Log.d("tag", "traaaack\n");
Intent i = new Intent(this, Track.class);
startActivity(i);
}
}
and here are the error messages parts from the log.
this is when the set method is called:
E/SQLiteLog: (1) near "values": syntax error
E/SQLiteDatabase: Error inserting current=0 target=2000
android.database.sqlite.SQLiteException: near "values": syntax error (code 1): , while compiling: INSERT INTO values(current,target) VALUES (?,?)
this is when the get method is called:
E/SQLiteLog: (1) near "values": syntax error
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.user.calorietracker/com.example.user.calorietracker.Track}: android.database.sqlite.SQLiteException: near "values": syntax error (code 1): , while compiling: SELECT target FROM values LIMIT 1
I have tried so many things to fix it but cant work out what i am doing wrong. literally any suggestion would be helpful! thanks
According to the list of SQLite Keywords - the word values is one of the words that you can't use for the name of your table (or column or many other things).
There are several ways to fix this:
Don't use this word. You can always use tbl_values for example.
You can quote that word:
'keyword' A keyword in single quotes is a string literal.
"keyword" A keyword in double-quotes is an identifier.
[keyword] A keyword enclosed in square brackets is an identifier. This is not standard SQL. This quoting mechanism is used by MS Access and SQL Server and is included in SQLite for compatibility.
`keyword` A keyword enclosed in grave accents (ASCII code 96) is an identifier. This is not standard SQL. This quoting mechanism is used by MySQL and is included in SQLite for compatibility.

Categories