How to Update/Delete with elements from two different tables SQLite - sqlite
I am working on a student grade submission program that accepts the following inputs: Student ID, Student First Name, Student Last Name, Class ID, Class Name, Grade Points, and Letter Grade. In order to prevent data redundancy I have created three different tables. However when attempting to "modify" or "delete" an entry with two values from distinct tables I am running into a problem. (For instance delete WHERE student.id is equal to the student.id in STUDENT_TABLE and WHERE class.id is equal to the class.id in the CLASS_TABLE)
With that being said, here is my current Modify code for Modifying a Student Class. I need to modify in a way in which the student.id and class.id are associated (Which are Located in two different Tables)
modifyclass.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(studentid.getText().toString().trim().length()==0 || classid.getText().toString().trim().length()==0 || classname.getText().toString().trim().length()==0)
{
showMessage("Error", "Please enter Student & Class ID to update class. \n\nAll other Field Entries will be ignored");
return;
}
Cursor c=db.rawQuery("SELECT * FROM CLASS_TABLE WHERE classid='"+classid.getText()+"'", null);
if(c.moveToFirst())
{
db.execSQL("UPDATE CLASS_TABLE SET classid='"+classid.getText()+"',classname='"+classname.getText()+"' WHERE studentid='"+studentid.getText()+"' AND classid='"+classid.getText()+"'");
showMessage("Success", "Class Record Modified");
}
else
{
showMessage("Error", "Invalid First and Last name or Class ID");
}
clearText();
}
});
EDIT:
Here are my tables for reference:
db=openOrCreateDatabase("STUDENTGRADES", Context.MODE_PRIVATE, null);
db.execSQL("CREATE TABLE IF NOT EXISTS STUDENT_TABLE (studentid TEXT, fname TEXT, lname TEXT)");
db.execSQL("CREATE TABLE IF NOT EXISTS CLASS_TABLE(classid TEXT PRIMARY KEY, classname TEXT UNIQUE)");
db.execSQL("CREATE TABLE IF NOT EXISTS GRADE_TABLE (studentid TEXT, classid TEXT, pointgrade INTEGER, lettergrade TEXT)");
You should never need to update multiple tables at once at least for a single change e.g. student's name has changed (student table would be changed) or say a grade changed (change the student's respective grade entry).
So I believe what would best suit are methods to update a Student's details (first or last name or both) and a method to alter the grades (again either or both).
As for deletion you could do this sequentially delete from the grades table and the from the student table or vice-versa.
As such I believe the following code includes methods deleteStudentInfo, changeStudentName, changeStudentFirstName, changeStudentLastName and changeStudentGrade and also includes example usage along with creating and populating the tables (you may wish to consider the revised schema):-
public class MainActivity extends AppCompatActivity {
public static final String DBNAME = "study";
public static final String STUDENT_TABLE_NAME = "STUDENT_TABLE";
public static final String COL_STUDENT_ID = "studentid";
public static final String COL_STUDENT_FIRSTNAME = "fname";
public static final String COL_STUDENT_LASTNAME = "lname";
public static final String CLASS_TABLE_NAME = "CLASS_TABLE";
public static final String COL_CLASS_ID = "classid";
public static final String COL_CLASS_NAME = "classname";
public static final String GRADE_TABLE_NAME = "GRADE_TABLE";
public static final String COL_GRADE_POINTGRADE = "pointgrade";
public static final String COL_GRADE_LETTERGRADE = "lettergrade";
public static final String BY_STUDENTID = COL_STUDENT_ID + "=?";
public static final String BY_CLASSID = COL_CLASS_ID + "=?";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SQLiteDatabase db = openOrCreateDatabase(DBNAME,Context.MODE_PRIVATE,null);
db.execSQL("CREATE TABLE IF NOT EXISTS " + STUDENT_TABLE_NAME + " (" +
COL_STUDENT_ID + " TEXT PRIMARY KEY, " +
COL_STUDENT_FIRSTNAME + " TEXT," +
COL_STUDENT_LASTNAME + " TEXT)"
);
db.execSQL("CREATE TABLE IF NOT EXISTS " + CLASS_TABLE_NAME + "(" +
COL_CLASS_ID + " TEXT PRIMARY KEY," +
COL_CLASS_NAME + " TEXT UNIQUE " +
")"
);
db.execSQL("CREATE TABLE IF NOT EXISTS " + GRADE_TABLE_NAME + "(" +
COL_STUDENT_ID + " TEXT, " +
COL_CLASS_ID + " TEXT, " +
COL_GRADE_POINTGRADE + " INTEGER, " +
COL_GRADE_LETTERGRADE + " TEXT" +
")"
);
db.execSQL("INSERT OR IGNORE INTO " + STUDENT_TABLE_NAME +
" VALUES" +
"('00001','Fred','Smith')," +
"('00010','Mary','Thomas')," +
"('00910','Angela','Jones')"
);
db.execSQL("INSERT OR IGNORE INTO " + CLASS_TABLE_NAME +
" VALUES" +
"('001','English')," +
"('101','Mathematics')," +
"('201','Chemistry')"
);
db.execSQL("INSERT OR IGNORE INTO " + GRADE_TABLE_NAME +
" VALUES" +
" ('00001','001',99,'A'), -- Fred Smith has 99 point grade as an A in English\n" +
" ('00001','101',25,'F'), -- Fred Smith has 25 point grade as an F on Mathematics\n" +
" ('00010','201',76,'B'), -- Angela Jones 76 a B in Chemistry\n" +
" ('00910','101',50,'C'), \n" +
" ('00910','201',63,'C'),\n" +
" ('00910','001',89,'A')\n" +
";"
);
changeStudentName(db,"00001","Joe","Bloggs");
changeStudentFirstName(db,"00001","Harry");
changeStudentLastName(db,"00001","Hoffmann");
// e.g. won't change due to -1 (skip pointsgrade) and null (skip lettergrade)
changeStudentGrade(db,"00001","001",-1,null);
// Change both
changeStudentGrade(db,"00001","001",25,"D");
changeStudentGrade(db,"00001","001",27,null);
// Ooops invalid student id
if (deleteStudentInfo(db,"001")) {
Log.d("DELETION","Student 001 deleted.");
} else {
Log.d("DELETION","Ooops Student 001 not deleted?????");
}
// Corrected Student ID
if (deleteStudentInfo(db,"00001")) {
Log.d("DELETION","Student 001 deleted.");
} else {
Log.d("DELETION","Ooops Student 001 not deleted?????");
}
}
private boolean deleteStudentInfo(SQLiteDatabase db, String studentid) {
String tag = "STUDENT_DELETE";
String student_table = "STUDENT_TABLE";
String grade_table = "GRADE_TABLE";
long pre_delete_student_count = DatabaseUtils.queryNumEntries(db,student_table);
long pre_delete_grade_count = DatabaseUtils.queryNumEntries(db,grade_table);
String whereclause = "studentid =?";
String[] whereargs = {studentid};
db.delete(student_table,whereclause,whereargs);
db.delete(grade_table,whereclause,whereargs);
long post_delete_student_count = DatabaseUtils.queryNumEntries(db,student_table);
long post_delete_grade_count = DatabaseUtils.queryNumEntries(db,grade_table);
Log.d(
tag,
"Number of Students deleted from " +
student_table + " is " +
String.valueOf(
pre_delete_student_count - post_delete_student_count
));
Log.d(
tag,
"Number of Grades deleted from " + grade_table + " is " +
String.valueOf(
pre_delete_grade_count - post_delete_grade_count
)
);
if ((pre_delete_student_count + pre_delete_grade_count) != (post_delete_student_count + post_delete_grade_count)) {
return true;
}
return false;
}
/**
* Flexible Student Name Change
*
* #param db The SQliteDatabase
* #param studentid The studentid (String)
* #param newfirstname The new firstname, null or blank to leave as is
* #param newlastname the new lastname, null or blank to leave as is
*/
private void changeStudentName(SQLiteDatabase db, String studentid, String newfirstname, String newlastname ) {
//Anything to do? if not do nothing
if ((newfirstname == null || newfirstname.length() < 1) && (newlastname == null || newlastname.length() < 1)) {
return;
}
ContentValues cv = new ContentValues();
if (newfirstname != null && newfirstname.length() > 0) {
cv.put(COL_STUDENT_FIRSTNAME,newfirstname);
}
if (newlastname != null && newlastname.length() > 0) {
cv.put(COL_STUDENT_LASTNAME,newlastname);
}
// Overcautious check
if (cv.size() < 1) {
return;
}
db.update(STUDENT_TABLE_NAME,cv,BY_STUDENTID,new String[]{studentid});
}
/**
* Change a Student's First Name (invokes changeStudentName method)
* #param db The SQLiteDatabase
* #param studentid The student's id (String)
* #param newfirstname The new first name to apply
*/
private void changeStudentFirstName(SQLiteDatabase db, String studentid, String newfirstname) {
changeStudentName(db,studentid,newfirstname,null);
}
/**
* Change a Student's Last Name (invokes changeStudentName method)
* #param db
* #param studentid
* #param newlastname
*/
private void changeStudentLastName(SQLiteDatabase db, String studentid, String newlastname) {
changeStudentName(db,studentid,null,newlastname);
}
/**
* Change a students grade (allowing just one (points/letter))
* #param db
* #param studentid
* #param classid
* #param newpointsgrade
* #param newlettergrade
*/
private void changeStudentGrade(SQLiteDatabase db, String studentid, String classid, int newpointsgrade, String newlettergrade) {
// Anything to do? if not do nothing
if (newpointsgrade < 0 && (newlettergrade == null || newlettergrade.length() < 1)) {
return;
}
ContentValues cv = new ContentValues();
if (newpointsgrade >= 0) {
cv.put(COL_GRADE_POINTGRADE,newpointsgrade);
}
if (newlettergrade != null && newlettergrade.length() > 0) {
cv.put(COL_GRADE_LETTERGRADE,newlettergrade);
}
String whereclause = COL_STUDENT_ID + "=? AND " + COL_CLASS_ID + "=?";
String[] whereargs = new String[]{studentid,classid};
db.update(GRADE_TABLE_NAME,cv,whereclause,whereargs);
}
}
Related
Retrieving Int Value from SQLite database
I am trying to retrieve an integer from my SQLite database and my current query crashes my program. This is what I have so far: */ public int getWin(String id){ SQLiteDatabase db = this.getWritableDatabase(); String query = "SELECT " + COL3 + " FROM " + TABLE_NAME + " WHERE " + COL2 + " = '" + id + "'"; Log.d(TAG, "updateName: query: " + query); db.execSQL(query); int win = Integer.parseInt(query); return win; } I am not sure why this will not work. Thanks in advance.
You are trying to convert the value SELECT ......... into a number as per int win = Integer.parseInt(query);. For a SELECT statment you need you need to retrieve a Cursor (result set), via either the query or rawQuery SQLiteDatabase method and then extract the value(s) from the method and to then access the respective column from the respective row(s). I believe that you would use something like :- public int getWin(String id){ SQLiteDatabase db = this.getWritableDatabase(); int rv = -1; //<<<<<<<<<< ADDED default value to return if no row found String query = "SELECT " + COL3 + " FROM " + TABLE_NAME + " WHERE " + COL2 + " = '" + id + "'"; Log.d(TAG, "updateName: query: " + query); Cursor csr = db.rawQuery(query,null); //<<<<<<<<<< CHANGED to get the Cursor returned // ADDED the following IF construct if (csr.moveToFirst()) { rv = csr.getInt(csr.getColumnIndex(COL3)); } //int win = Integer.parseInt(query); //<<<<<<<<<< DELETED (commented out) csr.close(); //<<<<<<<<<< ADDED should always close a Cursor when done with it return rv; //<<<<<<<<<< return the value (-1 if no row found) } This assumes that you just want the value from a single row as identified by the WHERE clause. If possible it is recommended to a) not build the query with direct values (makes it vulnerable to SQL Injection) and to b) utilise the convenience query method. Apply both a and b and your code could be :- public int getWin(String id){ SQLiteDatabase db = this.getWritableDatabase(); int rv = -1; String whereclause = COL2 + "=?"; //<<<<<<<<<< where clause without where and ? for value that will be passed String[] whereargs = new String[]{String.valueOf(id)}; //<<<<<<<<<< arguments used by the whereclause ? replaced on a 1 for 1 basis String[] columns = new String[]{COL3}; //<<<<<<<<<< the columns to extract as a String array Cursor csr = db.query(TABLE_NAME,columns,whereclause,whereargs,null,null,null); if (csr.moveToFirst()) { rv = csr.getInt(csr.getColumnIndex(COL3)); } csr.close(); return rv; }
Android Studio search existing sqlite db
So im developing an app and I want the user to search for a food item in my database and then to be returned with a list view of all food names that match the search criteria. I already have my slqite database created and added to the assets folder. The database is called foodDatabase.db I have created the Database Helper like so: package com.example.codebind.databasedemo; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; /** * Created by tom on 15/03/2018. */ public class FoodDatabaseHelper extends SQLiteOpenHelper{ public static final String DATABASE_NAME = "FoodDatabase.db"; public static final String TABLE_NAME = "dataset"; public static final String COL_1 = "ID"; public static final String COL_2 = "Food"; public static final String COL_3 = "Description"; public static final String COL_4 = "Protein"; public static final String COL_5 = "Fat"; public static final String COL_6 = "Carbohydrate"; public static final String COL_7 = "Energy"; public static final String COL_8 = "Starch"; public static final String COL_9 = "Sugar"; public static final String COL_10 = "Cholesterol"; public FoodDatabaseHelper(Context context) { super(context, DATABASE_NAME, null, 1); SQLiteDatabase sqLiteDatabase = this.getWritableDatabase(); } #Override public void onCreate(SQLiteDatabase sqLiteDatabase) { sqLiteDatabase.execSQL("create table " + TABLE_NAME +" (ID INTEGER PRIMARY KEY AUTOINCREMENT,FOOD TEXT,DESCRIPTION TEXT,PROTEIN BLOB,FAT BLOB,CARBOHYDRATE BLOB,ENERGY BLOB,STARCH BLOB,SUGAR BLOB,CHOLESTEROL BLOB) "); } #Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " +TABLE_NAME); onCreate(sqLiteDatabase); } } and currently my MainActivity.java is clean. I haven't touched it yet. I'm asking for guidance on how to add a listener so that when the user enters a food name the app will return all foods from the foodDatabase.db that meets the search query. Thanks
The basis of your search will be a query based upon the FOOD column (I believe). e.g. SELECT * FROM dataset WHERE FOOD LIKE '%your_food%' For example assume that your database has data such as (note only food and id columns have been populated with data) :- Then the query SELECT * FROM dataset WHERE FOOD LIKE '%mash%' would result in :- i.e. Foods with an id of 2 and 3 contain the food mash You could run this query using the SQLiteDatabase query method. The query method returns a Cursor with the extracted data. So a method in your DatabaseHelper could be :- public Cursor getFoodsWithProvidedFood(String provided_food) { return this.getWritableDatabase().query( TABLE_NAME, null, COL_2 + " LIKE '%" + provided_food + "%' ", null, null, null, null ); } Converting this into a complete but very basic App you could have :- The Database Helper - FoodDatabaseHelper.java public class FoodDatabaseHelper extends SQLiteOpenHelper { public static final String DATABASE_NAME = "FoodDatabase.db"; public static final String TABLE_NAME = "dataset"; public static final String COL_1 = "ID"; public static final String COL_2 = "Food"; public static final String COL_3 = "Description"; public static final String COL_4 = "Protein"; public static final String COL_5 = "Fat"; public static final String COL_6 = "Carbohydrate"; public static final String COL_7 = "Energy"; public static final String COL_8 = "Starch"; public static final String COL_9 = "Sugar"; public static final String COL_10 = "Cholesterol"; SQLiteDatabase sqLiteDatabase; //<<<< Added public FoodDatabaseHelper(Context context) { super(context, DATABASE_NAME, null, 1); sqLiteDatabase = this.getWritableDatabase(); //<<<< Amended } //#Override public void onNotRecommendedCreate(SQLiteDatabase sqLiteDatabase) { sqLiteDatabase.execSQL("create table " + TABLE_NAME + " (ID INTEGER PRIMARY KEY AUTOINCREMENT," + "FOOD TEXT," + "DESCRIPTION TEXT," + "PROTEIN BLOB," + "FAT BLOB," + "CARBOHYDRATE BLOB," + "ENERGY BLOB," + "STARCH BLOB," + "SUGAR BLOB," + "CHOLESTEROL BLOB)"); } #Override public void onCreate(SQLiteDatabase db) { String crtsql = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(" + COL_1 + " INTEGER PRIMARY KEY, " + COL_2 + " TEXT, " + COL_3 + " TEXT, " + COL_4 + " BLOB, " + COL_5 + " BLOB, " + COL_6 + " BLOB, " + COL_7 + " BLOB, " + COL_8 + " BLOB, " + COL_9 + " BLOB, " + COL_10 + " BLOB " + ")"; db.execSQL(crtsql); } #Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " +TABLE_NAME); onCreate(sqLiteDatabase); } public void insertFood( String food, String description, byte[] protien, byte[] fat, byte[] carbohydrate, byte[] energy, byte[] starch, byte[] sugar, byte[] cholesterol) { ContentValues cv = new ContentValues(); cv.put(COL_2,food); cv.put(COL_3,description); cv.put(COL_4,protien); cv.put(COL_5,fat); cv.put(COL_6,carbohydrate); cv.put(COL_7,energy); cv.put(COL_8,starch); cv.put(COL_9,sugar); cv.put(COL_10,cholesterol); SQLiteDatabase db = this.getWritableDatabase(); db.insert(TABLE_NAME,null,cv); } public Cursor getFoodsWithProvidedFood(String provided_food) { return this.getWritableDatabase().query( TABLE_NAME, null, COL_2 + " LIKE '%" + provided_food + "%' ", null, null, null, null ); } } Notes It will likely cause fewer issue if you have just one place where you define table and column names. hence the changed onCreate although column names in SQLite are case-insensitive the Cursor's getColumnIndex method (as used in the main activity) is case-sensitive (IMO a bug). AUTOINCREMENT doesn't do what it implies, rather INTEGER PRIMARY KEY itself makes a column one that increments adding AUTOINCREMENT is a special case that ensures that the id is greater at the expense of overheads. Hence AUTOINCREMENT has been removed. Two additional methods have been added insertFood to insert(add) data to the dataset table. getFoodsWithProvidedFood as described above. The Activity - MainActivity.java public class MainActivity extends AppCompatActivity { FoodDatabaseHelper foodDBHlpr; Cursor mCsr; #Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); foodDBHlpr = new FoodDatabaseHelper(this); byte[] dummy = new byte[]{0,1,2,3,4,5,6,7,8,9}; // Add some data oif none exists if (DatabaseUtils.queryNumEntries(foodDBHlpr.getWritableDatabase(),FoodDatabaseHelper.TABLE_NAME) < 1) { foodDBHlpr.insertFood("Fish and Chips", "The English Seaside meal", dummy, dummy, dummy, dummy, dummy, dummy, dummy); foodDBHlpr.insertFood("Bangers and Mash", "Yummy!!", dummy, dummy, dummy, dummy, dummy, dummy, dummy); foodDBHlpr.insertFood("Mashed Potatoe", "Boring", dummy, dummy, dummy, dummy, dummy, dummy, dummy); } // get a Cursor with the extracted foods mCsr = foodDBHlpr.getFoodsWithProvidedFood("Mash"); // Loop Through the Cursor while (mCsr.moveToNext()) { Log.d("FOODFOUND","You found the food called - " + mCsr.getString(mCsr.getColumnIndex(FoodDatabaseHelper.COL_2))); } if (mCsr.getCount() < 1) { Log.d("FOODFOUND","No foods found that match the search criteria."); } mCsr.close(); //<<<< Should always close Cursors when done with them } } Result in the Log :- 03-15 21:48:21.170 1702-1702/foodsdb.so49307874_foodsdb D/FOODFOUND: You found the food called - Bangers and Mash 03-15 21:48:21.170 1702-1702/foodsdb.so49307874_foodsdb D/FOODFOUND: You found the food called - Mashed Potatoe
how to write where clause with rawquery
Hi, I have some problem to fetch data from sqlite database. Here i am fetching data from select query but it is not responding. Please help me. public ArrayList<String> getStudentsByClass(String stud_info) { // Log.i("SKR", "GETTING STUDENTS by " +stud_class); ArrayList<String> arrayList = new ArrayList<>(); Cursor cursor = liteDatabase.rawQuery("SELECT * FROM " + DATABASE_TABLE2 + " WHERE ssg ='" + stud_info + "'", null); if (cursor != null) { cursor.moveToFirst(); while (cursor.isAfterLast() == false) { arrayList.add(cursor.getString(cursor.getColumnIndex(KEY_STUDENT_NAME))); cursor.moveToNext(); } } } return arrayList; }
Here is a raw query from a DBHelper Class that when called populates an ArrayList /* Retrive ALL data from database table named "TABLE_INFO" */ public List<DatabaseModel> getDataFromDB(){ List<DatabaseModel> modelList = new ArrayList<>(); String query = "SELECT * FROM " + TABLE_INFO; //String query = "SELECT * FROM " + TABLE_INFO + " WHERE " + Col_ID + " > 0 " + " ORDER BY " + Col_ID + " DESC "; /* Notice the SPACES before AND after the words WHERE ORDER BY ASC or DESC most of all the condition " > 0 "*/ /* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=*/ db = this.getWritableDatabase(); Cursor cursor = db.rawQuery(query,null); if (cursor.moveToFirst()){ do { DatabaseModel model = new DatabaseModel(); model.setID(cursor.getString(0)); model.setWebsite(cursor.getString(1)); model.setUsernane(cursor.getString(2)); model.setPassword(cursor.getString(3)); model.setQuestion(cursor.getString(4)); model.setAnswer(cursor.getString(5)); model.setNotes(cursor.getString(6)); modelList.add(model); }while (cursor.moveToNext()); } db.close(); return modelList; }
using rawQuery You may include ?s in where clause in the query, which will be replaced by the values from selectionArgs. The values will be bound as Strings. String selectQuery = "select * FROM settings where _id = ?"; String args[] = {"1"}; Cursor c = db.rawQuery(selectQuery, args); if (c.moveToFirst()) {
Failing to delete rows from a linked table
I have problems deleting the rows from a table. I have 2 tables with the following definition: private static final String DATABASE_TABLEELEMENTS = "elements"; public static final String KEY_ROWELEMENTID = "_id"; public static final String KEY_STUDYID = "idstudy"; public static final String KEY_ELEMENTCODE = "code_element"; public static final String KEY_ELEMENTNAME = "description_element"; private static final String DATABASE_TABLETIME = "times"; public static final String KEY_ROWTIME = "_id"; public static final String KEY_ELEMENTID = "idelement"; public static final String KEY_HOURDATE = "hour_date"; public static final String KEY_OBSERVEDYTIME = "observedtime"; public static final String KEY_OBSERVEDACTIVITY = "observedactivity"; both tables are related: elements._id = times.idelement I want to delete all rows in table "times" which has the "idstudy" from table "elements" that the user has selected: For this I created the following function: public void ResetDataStudies(String selectedid) { String querytimes = "DELETE FROM " + "times" + " WHERE " + "times.idelement" + " IN " + "(SELECT " + "elements._id" + " FROM " + "elements" + " WHERE " + "elements.idstudy = ?)"; ourDatabase.rawQuery(querytimes, new String[] { selectedid }); } I don't receive a specific error, but after executing it the data has not been deleted. See below the data type: db.execSQL(" CREATE TABLE " + DATABASE_TABLEELEMENTS + " (" + KEY_ROWELEMENTID + " INTEGER UNIQUE PRIMARY KEY AUTOINCREMENT, " + KEY_ELEMENTCODE + " INTEGER NOT NULL, " + KEY_ELEMENTNAME + " TEXT, " + KEY_STUDYID + " TEXT NOT NULL REFERENCES " + DATABASE_TABLEACOUNT + "("+ KEY_ROWSTUDYID +") ON DELETE CASCADE "); db.execSQL(" CREATE TABLE " + DATABASE_TABLETIME + " (" + KEY_ROWTIME + " INTEGER UNIQUE PRIMARY KEY AUTOINCREMENT, " + KEY_HOURDATE + " INTEGER NOT NULL, " + KEY_OBSERVEDYTIME + " TEXT NOT NULL, " + KEY_OBSERVEDACTIVITY + " TEXT NOT NULL, " + KEY_ELEMENTID + " TEXT NOT NULL REFERENCES " + DATABASE_TABLEELEMENTS + "("+ KEY_ROWELEMENTID +") ON DELETE CASCADE "); } I have updated my statements but now I receive an error while creating the tables: error near cascade statement
When you create the table, the foreign key needs to be ON DELETE CASCADE. e.g. FOREIGN KEY ("+KEY_ELEMENTID+") REFERENCES "+DATABASE_TABLEELEMENTS+" ("+KEY_ROWELEMENTID+") ON DELETE CASCADE); " You'll also have to tell SQLite to enforce foreign keys (otherwise they are ignored). PRAGMA foreign_keys = ON; See https://www.sqlite.org/foreignkeys.html.
Accessing records in Android using rawQuery and then displaying
I am working on several rawQueries to use to parse data from a table in Android. The below code works fine and returns the lowest rowid in the table. public void firstRecord(View v){ Cursor c = db.rawQuery("SELECT * FROM surveyDB WHERE rowid = (SELECT MIN(rowid) FROM surveyDB)",null); c.moveToFirst(); szList.add(c.getString(0)); Toast.makeText(getApplicationContext(), "Sucessful Event. szRowid is: " +szList +".", Toast.LENGTH_LONG).show(); } I have two questions, and they are both extremely basic: 1) what is the best way to expand the above code to create language to capture the contents of other columns in this table at that specific rowid, (rowid, sampler, species, place), and display this in my application? Something like this perhaps: ((EditText)findViewById(R.id.edSpecies)).setText(""); with the proper reference replacing "" in .setText()?
String TABLE_SURVEY = "surveyDB"; String COL_ROW_ID = "rowid"; String COL_SAMPLER = "sampler"; String COL_SPECIES = "species"; String COL_PLACE = "place"; public ArrayList<SurveyRecord> getSurveyRecords() { ArrayList<SurveyRecord> records = new ArrayList<SurveyRecord>(); String query = "SELECT * FROM " + TABLE_SURVEY; query += " WHERE " + COL_ROW_ID = " SELECT MIN (" query += COL_ROW_ID + ") FROM " + TABLE_SURVEY; Cursor c = db.rawQuery(query,null); if(Cursor.moveToFirst()) { do{ String sampler = c.getString(cursor.getColumnIndex(COL_SAMPLER)); String species= c.getString(cursor.getColumnIndex(COL_SPECIES)); String place = c.getString(cursor.getColumnIndex(COL_PLACE)); String rowId = c.getString(cursor.getColumnIndex(COL_ROW_ID)); records.add(new (rowId,species,place,sampler)); }while(c.moveToNext()) } c.close(); } public class SurveyRecord{ String mRowId; String mSpecies; String mPlace; String mSampler; public SurveyRecord(String rowId,String species,String place,String sampler) { this.mRowId = rowId; this.mSpecies = species; this.mPlace = place; this.mSampler = sampler; } }
//Goes to the first record in the dataset public void firstRecord(View v){ Cursor c = db.rawQuery("SELECT * FROM surveyDB WHERE rowid = (SELECT MIN(rowid) FROM surveyDB)",null); c.moveToFirst(); ((EditText)findViewById(R.id.edRowid)) .setText(c.getString(0)); ((EditText)findViewById(R.id.edSpecies)) .setText(c.getString(1)); ((EditText)findViewById(R.id.edArea)) .setText(c.getString(2)); ((EditText)findViewById(R.id.edSampler)) .setText(c.getString(3)); }