Delete the last row in a table SQLite android - android

I am developing an android app where I want to delete the last row in one of my database table. I have tried the code below, but its throwing a syntax error.
public void deletelatestprofilefromsystemsettings()
{
String maxid = System_id + "="+"SELECT MAX ("+System_id+") FROM" +TABLE_SYSTEM_SETTINGS;
getWritableDatabase().delete(TABLE_SYSTEM_SETTINGS, maxid ,null);
}
Please help! Thanks!

You are lacking a space after the FROM, and subqueries must be written in parentheses:
String maxid = System_id + "=" +
"(SELECT MAX("+System_id+") FROM " + TABLE_SYSTEM_SETTINGS + ")";

You are trying to execute a DELETE with a SELECT in the same query. AFAIK you shouldn't do it. You have to execute the SELECT query first, in order to retrieve the desired id, then execute the deletion. In other words, execute Cursor c = getWritableDatabase().query(), read the id from the cursor, then use it in getWritableDatabase().delete().
Also, add a space after ") FROM", so it becomes ") FROM " in order to avoid a syntax error.

Related

SQLite Statement in Android Studio 3.5.3

I'm a newbie with Android Studio so please be patient... This forum often leads me with suggestions and examples (as a reader), but today I decided to ask for help:
Since hours, I try to build an SQLite statement in Android Studio: There is a column COLUMN_LAST_ATTEMPT with date and time as String, e.g. 2020-01-09 17:23, see screenshot, and I want to get the newest date (without time) from the table, e.g. 2020-09-01. I tried various options but I can't get it to run.
What I need is an Android SQLite Statement for
SELECT MAX(SUBSTR(last_attempt,11,20)) FROM quiz_questions
(which runs on DBBrowser), where 'last attempt' is a column of table 'quiz_questions', screenshot of that column in table 'quiz_questions'
I tried the following rawQueries, none of them works:
In QuizDBHelper-Class
//...
final QuizDbHelper dbHelper = QuizDbHelper.getInstance(this);
//...
public String newestQuiz(){
db = getReadableDatabase();
String result = null;
Cursor cursor = db.rawQuery("SELECT MAX(" + QuizContract.QuestionsTable.COLUMN_LAST_ATTEMPT + ") FROM "
+ QuizContract.QuestionsTable.TABLE_NAME, null);
//Cursor cursor = db.rawQuery("SELECT MAX(SUBSTR(" + QuizContract.QuestionsTable.COLUMN_LAST_ATTEMPT +
// ",11,20)) FROM " + QuizContract.QuestionsTable.TABLE_NAME, null);
//Cursor cursor = db.rawQuery("SELECT " + QuizContract.QuestionsTable.COLUMN_LAST_ATTEMPT + " FROM " +
// QuizContract.QuestionsTable.TABLE_NAME, null);
if(cursor.moveToFirst()){
do {
result = cursor.getString(c.getColumnIndex(QuizContract.QuestionsTable.COLUMN_LAST_ATTEMPT));
} while (cursor.moveToNext());
}
cursor.close();
return result;
}
In Statistics-Class
String LastUse = dbHelper.newestQuiz();
LastUsage.setText("Letzte Challenge: " + LastUse);
//LastUsage is a TextView in activity_Statistics.xml
//attached with LastUsage = findViewById(R.id.text_lastUsage);
Either the SQLite statements are totally wrong or I make (basic?) mistakes in statistics class. I need ...newbie help!
I need something like Select column from table where substring of date-Entry == newest
Your issue appear to be column names. That is a Cursor only contains the columns extracted, not all the columns from the table. Although you are basing your query on the column as per QuizContract.QuestionsTable.COLUMN_LAST_ATTEMPT that will not be the column name in the cursor.
Rather it will will MAX(SUBSTR(" + QuizContract.QuestionsTable.COLUMN_LAST_ATTEMPT +
// ",11,20))
The simplest way of managing this is to give the column in the Cursor a specific name using AS. As such perhaps use :-
Cursor cursor = db.rawQuery("SELECT MAX(" + QuizContract.QuestionsTable.COLUMN_LAST_ATTEMPT + ") AS " + QuizContract.QuestionsTable.COLUMN_LAST_ATTEMPT + " FROM "
+ QuizContract.QuestionsTable.TABLE_NAME, null);
However, you may prefere to use a column name (AS ????) specififc to the situation e.g.
........ AS max_" + QuizContract.QuestionsTable.COLUMN_LAST_ATTEMPT + ........
You would then have to use :-
result = cursor.getString(c.getColumnIndex("max_" + QuizContract.QuestionsTable.COLUMN_LAST_ATTEMPT));
Alternately, as it's just a single value/column that is returned in the cursor you could use the column offset of 0, in which case the column name is irrelevant as long as it is valid. However, using offsets is not typically recommended due to the lack of validation of the column being accessed.
re the comment :-
I just need the date part
As the date is a recognised DateTime format (and also that such formats are directly sortable/orderable), use max(date(column_name)) or even max(column_name).

SQLite - Match results based on string value issue

I'm currently having an issue with my SQL Lite code with regards to counting matching results. In my application the user will have the ability to add a new folder and give it a name. Before the folder is added to the application my code will check to see if a folder with the same name already exists if so it will prompt the user.
When using my code below I receive an error informing me the column doesn't exist. If I remove everything past WHERE then it works perfectly and counts every record within the table.
I've reinstalled the application and changed the database version so that its completely clean, just to make sure. I'm certain its only something very minor I'm missing.
public int countMatchingFolders (String folderName){
String countQuery = "SELECT * FROM " + Primary_Table + " WHERE " + Col_FolderName + " = " + folderName;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(countQuery, null);
int cnt = cursor.getCount();
cursor.close();
return cnt;
}
Error message I'm receiving
android.database.sqlite.SQLiteException: no such column: testFolder (code 1): , while compiling: SELECT * FROM Folder_Table WHERE Col_FolderName = testFolder
Any assistance to help with the issue would be greatly appreciated.
The error is because the string value doesn't have quotes around it, so it is treated as a table name instead of a string. You should use a bound query argument to fix this. Bound arguments also prevent SQL injection attacks:
String countQuery = "SELECT * FROM " + Primary_Table + " WHERE " + Col_FolderName + " = ?";
Cursor cursor = db.rawQuery(countQuery, new String[]{folderName});
Note that you can do "SELECT COUNT(*) as row_count" ... to let the database engine count the number of records more efficiently.

How to write SQL statement containing 2 conditions in android

I am trying to delete a row from my table if 2 columns equal to what the user entered.
E.g. I have 2 textfields in which the user entered something in both e.g. "chicken" and in the other textfield "car". I want to delete the row in which those 2 values are in a row. I think it will be something like: delete from ~tablename~ where food = chicken AND vehicle = car.
Im not sure how to write that in sqlite in android.
I have my SQLitedatabase object and have called the delete method on it, but not sure what to put in the parameters
EDIT = I've managed to do it. Thanks for the below answers but this is how I've done it:
sqlitedb.delete("Random", "food =? AND vehicle=? ", new String[]{tv.getText.toString(),tv1.getText.toString()});
tv and tv1 are textfields in my case. Random is my table's name.
The sql query will look like -
String sqlQuery = "DELETE FROM <table_name> WHERE food = '"+ <food_name> + "' AND vehicle = '" + <vehicle_name> + "'";
You want something like:
String table_name=~tablename~;
String table_column_one=food;
String table_column_two=vehicle;
database.delete(table_name,
table_column_one + " = ? AND " + table_column_two + " = ?",
new String[] {"chicken", "car"});
Check SQLiteDatabase's documentation on delete function for more info.
SQLite accepts conditionals in the WHERE clause as regular SQL.

android second column returns no value

I have a problem to create a table. If I try to get a value from the second column, android writes a empty space in the toast. But if I try to get a value from the first column, android writes the value of the column correctly. The query functions to write the first column and to write the second column are equal. So I think the Creation of the Table is the problem. But look yourself:
public SQLiteDatabase tabelleerstellen(){
SQLiteDatabase leveldatabase = openOrCreateDatabase("leveldata.db",SQLiteDatabase.CREATE_IF_NECESSARY, null);
leveldatabase.setVersion(1);
final String CREATE_TABLE_LEVEL =
"CREATE TABLE IF NOT EXISTS tbl_level ("
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "ME1 TEXT, "
+ "ME2 TEXT, "
+ "ME3 TEXT, "
+ "ME4 TEXT, "
+ "ME5 TEXT, "
+ "ME6 TEXT, "
+ "ME8 TEXT, "
+ "GESCHAFFT INTEGER);";
leveldatabase.execSQL(CREATE_TABLE_LEVEL);
return leveldatabase;
}
public void tester(SQLiteDatabase leveldata){
ContentValues cursortester = new ContentValues();
cursortester.put("ME2","25");
leveldata.insert("tbl_level",null,cursortester);
String[] testerpr = {"ME2"};
Cursor testerprüfen = leveldata.query("tbl_level",testerpr,null,null, null, null,null,null);
testerprüfen.moveToFirst();
String dada = testerprüfen.getString(testerprüfen.getColumnIndex("ME2"));
Toast testertoast = Toast.makeText(getApplicationContext(),dada,Toast.LENGTH_SHORT);
testertoast.show();
}
Please check the following things:
Please make sure the table is up to date .. so try to call DROP TABLE IF EXISTS tbl_level; and recreate the table.
If you run a test make sure the table is completely empty ... so delete everything at the beggining of the test.
If the table can contain elements during the test then make sure you check the last inserted element. Please note that calling testerprüfen.moveToFirst(); moves the cursor to the first row in the table so checking that row every time is even if the table contains 50 elements is not a good thing. In this case you either use a sorting option in your query of uese while (testerprüfen != null && testerprüfen.moveToNext()) {// Your code here}
All in all I think your problem is that you already inserted more that one element in the able but you always check only the first element (with testerprüfen.moveToFirst();). Please not that there is a cursor.moveToLast() method that you can also call. This method moves the cursor to the last row in the table.

Query doesnt work on android, column '_id' does not exist?

I hope anyone can help me with this.
I'm using sqlite3 on my android app. I'm trying to do this query:
mCursor = conexion.getDatabase().rawQuery("SELECT employee.name, company.name FROM employee "
+ " INNER JOIN company "
+ " ON (employee.idCompany=company._id) ORDER BY employee.name", null);
This is my schema:
CREATE table company ("_id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "name TEXT NOT NULL);";
CREATE table employee ("_id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "name TEXT NOT NULL, "
+ "fullName TEXT NOT NULL, "
+ "idCompany INTEGER NOT NULL, "
+ "FOREIGN KEY(idCompany) REFERENCES company (_id));";
When I run this query on my android app I get the following error:
05-09 22:35:23.170: E/AndroidRuntime(10920): FATAL EXCEPTION: main
05-09 22:35:23.170: E/AndroidRuntime(10920): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ej.ej/com.ej.ej.controlador.AplicacionActivity}: java.lang.IllegalArgumentException: column '_id' does not exist
If I run the same query but with select *:
mCursor = conexion.getDatabase().rawQuery("SELECT * FROM employee "
+ " INNER JOIN company "
+ " ON (employee.idEmployee=company._id) ORDER BY employee.name", null);
No problem I get, it works fine. But since in my schema I have name for company and name for employee I need to differentiate both.
I tried doing this query using cmd and adb commands and it works. I really don't get why the error!!
EDITED: I made it work, as #HalR suggested in the query (dont know why) I have to retrieve the ids. So now I have:
mCursor = conexion.getDatabase().rawQuery("SELECT company._id, employee.name as employee, company.name as company FROM employee "
+ " INNER JOIN company "
+ " ON (employee.idCompany=company._id) ORDER BY employee.name", null);
But I had one more issue and it wasnt in the query, it was on my ActivityFragment (thanks to #Hoan Nguyen, he made me see this part of the code again):
Listing my employees, I was getting the name of my employee and the idCompany. Don't know why, but this was looking for the _id of Company instead of idCompany of Employee.
String[] from = new String[] { "name", "idCompany"};
int[] to = new int[] { R.id.textViewNombreIzq, R.id.textViewNombreCent };
ListView lvEmployee = (ListView) view.findViewById (android.R.id.list);
ListClientsCursorAdapter notes = new ListClientsCursorAdapter(context, R.layout.activity_file_client, mCursorEmployee, from, to, 0);
lvEmployee .setAdapter(notes);
I just changed:
String[] from = new String[] { "name", "idCompany"};
For:
String[] from = new String[] { "employee", "company"};
And now is fine. Thanks to all, for your help I really apreciated :).
first, I in your CREATE TABLE employee statement you used the lable full name as a column label. If it is not a typo here, please change it to something like full_name. you can't just use spaces in column labels this way.
second, use this query string:
SELECT employee.name, company.name FROM employee INNER JOIN company ON (employee.idCompany=company._id) ORDER BY employee.name. Notice the ON expression. it's employee.idCompany not employee.idEmployee.
fix those first, and let me know if the error still exists.
I think you want this:
mCursor = conexion.getDatabase().rawQuery("SELECT employee.idCompany, employee.name, company.name FROM employee "
+ " INNER JOIN company "
+ " ON (employee.idCompany=company._id) ORDER BY employee.name", null);
Note: You need to make sure you specify the column name you are comparing in the section just after the SELECT.
Actually you don't need to name your column as _id in your table. for a example, you can create column as company_id in your company table and when you write your query, you can specify this column as below.
select company_id as _id, name from company.

Categories

Resources