I've been reading up on BaseColumns](https://developer.android.com/reference/android/provider/BaseColumns.html) in Android to help structure my database schema.
I know that _ID is a unique identifier for the row that you have to create yourself:
protected static final String SQL_CREATE = "CREATE TABLE " + TABLE_NAME + "( " +
_ID + " INTEGER PRIMARY KEY AUTOINCREMENT" + ...;
I also read that _COUNT is used to refer to the number of rows in a table.
However, when I tried using _COUNT, I got an error. Here is what I tried:
SQLiteDatabase db = TimetableDbHelper.getInstance(context).getReadableDatabase();
Cursor cursor = db.query(
SubjectsSchema.TABLE_NAME,
new String[] {SubjectsSchema._COUNT},
null, null, null, null, null);
cursor.moveToFirst();
int count = cursor.getInt(cursor.getColumnIndex(SubjectsSchema._COUNT));
cursor.close();
return count;
I'm not sure whether or not this is the correct way to use it, but I got this error:
android.database.sqlite.SQLiteException: no such column: _count (code 1): , while compiling: SELECT _count FROM subjects
How should I be using _COUNT?
In the database, there is nothing special about either _id or _count.
Your queries return an _id or _count column when the table is defined to have such a column, or when the query explicitly computes it.
Many objects of the Android framework expect a cursor to have a unique _id column, so many tables define it.
In most places, the _count is not expected to be present, so it is usually not implemented. And if it is actually needed, it can simply be computed with a subquery, like this:
SELECT _id,
[other fields],
(SELECT COUNT(*) FROM MyTable) AS _count
FROM MyTable
WHERE ...
If you want to find out the size of your own table, you are not required to use the _count name; you can execute a query like SELECT COUNT(*) FROM subjects, or, even simpler, use a helper function that does this for you.
Related
I'd like to do something like this:
public boolean containsKey(int primaryKey) {
SQLiteDatabase db = getReadableDatabase();
// what should i do here to determine if the db contains the primaryKey?
}
What is the most efficient way to check if the db contains the specified value?
You could try to read the row with that PK value:
public boolean containsKey(int primaryKey) {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query("TableName", null, "IDColumn = " + primaryKey,
null, null, null, null);
return cursor.moveToFirst();
}
However, it would be a better idea to use a helper function that allows you to avoid having to muck around with a cursor:
public boolean containsKey(int primaryKey) {
SQLiteDatabase db = getReadableDatabase();
return DatabaseUtils.queryNumEntries(db, "TableName", "IDColumn = " + primaryKey) > 0;
}
You should inspect sqlite scheme. You may try
"SELECT name FROM sqlite_master WHERE type='table'"
Second variant:
PRAGMA table_info(table-name);
If You are looking for getting the column names for a table:
PRAGMA table_info(your_table_name);
Example :
PRAGMA table_info(Login);
you will get pk value 1 if you have primary key in login table.
Check this tutorial on PRAGMA
This pragma returns one row for each column in the named table.
Columns in the result set include the column name, data type, whether
or not the column can be NULL, and the default value for the column.
The "pk" column in the result set is zero for columns that are not
part of the primary key, and is the index of the column in the primary
key for columns that are part of the primary key.
I have created a sqlite table for my android app, this table has 5 columns and multiple rows, the columns being: _id, column1, column2, column3, column4.
I want to delete a specific record, for instance the record stored in column3 corresponding to _id (in a different class are the getters and setters, for this I've named the class "TableHandler")
I guess that I'm a bit confused, following is what I was planning, but for column3 I'm not sure what should be the argument, I just want to delete whatever is in that column position corresponding to _id
public void deleteValueColumn3(TableHandler value){
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_NAME, KEY_ID + " = ? AND " + KEY_COLUMN3 + " = ?",
new String[] {String.valueOf(value.getID()), ?????????);
db.close();
}
The ???????? is that I'm stuck there, maybe the whole method needs to be rewritten, I would appreciate your input.
Thanks
If you want to delete the whole record, just use the _id of the record in delete method, because that is the primary key for your table and therefore is unique. If you'd rather keep the record, you con always use the SQLiteDatabase.update method, specifying null as the new value that will replace column3 value; check out that column3 declaration has no NOT NULL tag, otherwise that could easily throw exception at you.
SQLite does not allow you to delete columns for a specific row.
You can only delete ROWS of data (delete the row that has the column _ID = 1).
Here's a quick tutorial on SQL.
How about updating that column with a null value, rather than using delete()?
ContentValues cv = new ContentValues();
cv.putNull(KEY_COLUMN3);
db.getWritableDatabase().update(
TABLE_NAME,
cv,
KEY_ID + "=?",
new String[]{String.valueOf(keyIdValue)});
I'm making an Android app and using a SQLite database. In particular I'm using the rawQuery method on a database obtained through a SQLiteOpenHelper. The query I build makes use of the ? marks as placeholders for the real values, which are passed along as an array of objects (e.g., select * from table where id = ?).
The question is, is it possible to get the query with the marks already replaced, at least from the cursor returned from the rawQuery method? I mean something like select * from table where id = 56. This would be useful for debugging purposes.
It's not possible. The ? values are not bound at the SQL level but deeper, and there's no "result" SQL after binding the values.
Variable binding is a part of the sqlite3 C API, and the Android SQLite APIs just provide a thin wrapper on top. http://sqlite.org/c3ref/bind_blob.html
For debugging purposes you can log your SQL with the ?, and log the values of your bind arguments.
You could form it as a string like this
int id = 56;
String query = "select * from table where id = '" + id + "'";
and then use it as a rawQuery like this (if I understood your question properly)
Cursor mCursor = mDb.rawQuery(query, null);
You can also use the SQLiteQueryBuilder. Here is an example with a join query:
//Create new querybuilder
SQLiteQueryBuilder _QB = new SQLiteQueryBuilder();
//Specify books table and add join to categories table (use full_id for joining categories table)
_QB.setTables(BookColumns.TABLENAME +
" LEFT OUTER JOIN " + CategoryColumns.TABLENAME + " ON " +
BookColumns.CATEGORY + " = " + CategoryColumns.FULL_ID);
//Order by records by title
_OrderBy = BookColumns.BOOK_TITLE + " ASC";
//Open database connection
SQLiteDatabase _DB = fDatabaseHelper.getReadableDatabase();
//Get cursor
Cursor _Result = _QB.query(_DB, null, null, null, null, null, _OrderBy);
Okay, so I have a high score table. I have two columns, Player name and score..
Every time a new score is to be added to the table I delete the last row, put the new score and new player name in the last row and then sort the table according to the score.
I can't delete the row with minimum score because there might be multiple entries with the same score and I don't want to delete all of them.
You might want to rebuild your table and include an id column with integer primary key autoincrement. You can do quite a bit with that column in place (here's an SO question you can look into for that).
Anyway I don't know how your process goes and why you need to delete the last row but here's an example of using an ID column to get the last row ( which I assume would be the latest insert and is what usually happens if you declare an ID integer primary key autoincrement column):
public int LastInsert() {
SQLiteDatabase db = this.getReadableDatabase();
final String MY_QUERY = "SELECT MAX(" + colID + ") FROM " + myTable;
Cursor cur = db.rawQuery(MY_QUERY, null);
cur.moveToFirst();
int ID = cur.getInt(0);
cur.close();
return ID;
}
From here you can probably just get the result of LastInsert and use that to direct what your delete function should delete.
Imo you're better of maybe just updating the last row instead of deleting and reinserting in it's place though. Something like this :
public int UpdateAcc(Account acc) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(colName, acc.getName());
cv.put(colScore, acc.getScore());
return db.update(myTable, cv, colID + "=?", new String[]{params});
}
I don't remember rather android with sqlite supports multiple commands per statement, but if so this might work:
DELIMITER ;;
SET #LastId = (SELECT ROWID FROM yourTable ORDER BY ROWID DESC LIMIT 1);;
DELETE FROM yourTable WHERE ROWID=#LastId;;
Otherwise you can store this in a integer variable:
SELECT ROWID FROM yourtable ORDER BY ROWID DESC LIMIT 1;
Then use that variable to run the next line
DELETE FROM yourtable WHERE ROWID=#ThatIntegerHere;
Please let me know how to delete n-rows in android sqlite database. I used this code:
String ALTER_TBL ="delete from " + MYDATABASE_TABLE +
"where"+KEY_ID+"in (select top 3"+ KEY_ID +"from"+ MYDATABASE_TABLE+"order by _id );";
sqLiteDatabase.execSQL(ALTER_TBL);
But it shows an error.
03-21 13:19:39.217: INFO/Database(1616): sqlite returned: error code = 1, msg = near "in": syntax error
03-21 13:19:39.226: ERROR/Database(1616): Failure 1 (near "in": syntax error) on 0x23fed8 when preparing 'delete from detail1where_id in (select top 3_idfromdetail1order by _id );'.
String ALTER_TBL ="delete from " + MYDATABASE_TABLE +
" where "+KEY_ID+" in (select "+ KEY_ID +" from "+ MYDATABASE_TABLE+" order by _id LIMIT 3);";
there is no "top 3" command in sqlite I know of, you have to add a limit
watch out for spaces when you add strings together : "delete from" + TABLE + "where" = "delete frommytablewhere"
This approach uses two steps to delete the first N rows.
Find the first N rows:
SELECT id_column FROM table_name ORDER BY id_column LIMIT 3
The result is a list of ids that represent the first N (here: 3) rows. The ORDER BY part is important since SQLite does not guarantee any order without that clause. Without ORDER BY the statement could delete 3 random rows.
Delete any row from the table that matches the list of ids:
DELETE FROM table_name WHERE id_column IN ( {Result of step 1} )
If the result from step 1 is empty nothing will happen, if there are less than N rows just these will be deleted.
It is important to note that the id_column has to be unique, otherwise more than the intended rows will be deleted. In case the column that is used for ordering is not unique the whole statement can be changed to DELETE FROM table_name WHERE unique_column IN (SELECT unique_column FROM table_name ORDER BY sort_column LIMIT 3). Hint: SQLite's ROWID is a good candidate for unique_column when deleting on tables (may not work when deleting on views - not sure here).
To delete the last N rows the sort order has to be reversed to descending (DESC):
DELETE FROM table_name WHERE unique_column IN (
SELECT unique_column FROM table_name ORDER BY sort_column DESC LIMIT 3
)
To delete the Nth to Mth row the LIMIT clause can be extended by an OFFSET. Example below would skip the first 2 rows and return / delete the next 3.
SELECT unique_column FROM table_name ORDER BY sort_column LIMIT 3 OFFSET 2
Setting the LIMIT to a negative value (e.g. LIMIT -1 OFFSET 2) would return all rows besides the first 2 resulting in deletion of everything but the first 2 rows - that could also be accomplished by turning the SELECT .. WHERE .. IN () into SELECT .. WHERE .. NOT IN ()
SQLite has an option to enable the ORDER BY x LIMIT n part directly in the DELETE statement without a sub-query. That option is not enabled on Android and can't be activated but this might be of interest to people using SQLite on other systems:
DELETE FROM table_name ORDER BY sort_column LIMIT 3
It seems that you've missed some spaces:
"where"+KEY_ID+"in..
must be:
"where "+KEY_ID+" in...
Furthermore you need to use the limit statement instead of top:
I'll do:
db.delete(MYDATABASE_TABLE, "KEY_ID > "+ value, null);
you can try this code
int id;
public void deleteRow(int id) {
myDataBase.delete(TABLE_NAME, KEY_ID + "=" + id, null);
}
String id;
public void deleteRow(String id) {
myDataBase.delete(TABLE_NAME, KEY_ID + "=\" " + id+"\"", null);
}
It is a bit long procedure but you can do it like this
first get the ids column of table from which which you want to delete certain values
public Cursor KEY_IDS() {
Cursor mCursor = db.rawQuery("SELECT KEYID " +
" FROM MYDATABASE_TABLE ;", null);
if (mCursor != null)
{
mCursor.moveToFirst();
}
return mCursor;
}
Collect it in an array list
ArrayList<String> first = new ArrayList<String>();
cursor1 = db.KEY_IDS();
cursor1.moveToFirst();
startManagingCursor(cursor1);
for (int i = 0; i < cursor1.getCount(); i++) {
reciv1 = cursor1.getString(cursor1
.getColumnIndex(DBManager.Player_Name));
second.add(reciv1);
}
and the fire delete query
for(int i = 0 ;i<second.size(); i++)
{
db.delete(MYDATABASE_TABLE KEYID +"=" + second.get(i) , null);
}
Delete first N (100) rows in sqlite database
Delete from table WHERE id IN
(SELECT id FROM table limit 100)
You can make use of the following mode: (in addition to the response provided by "zapl").
**DELETE FROM {Table-X} WHERE _ID NOT IN
(SELECT _ID FROM {Table-X} ORDER BY _ID DESC/ASC LIMIT (SELECT {Limit-Column} FROM {SpecificationTable}) );**
Where {Table-X} refers to the table you want to delete, _ID is the main unique-column
DESC/ASC - Based on whether you want to delete the top records or the last records, and finally in the "LIMIT" clause, we provide the "n" factor using another query, which calls in the {Limit-Column} from {SpecificationTable}: Which holds the value against which you want to delete them.
Hope this helps out someone.
Happy Coding.