As my title question, I want to delete some rows of table on SQLite where contains specific string.
Here are my methods I tried but there are no any row is deleted. I checked table of SQLite database by get it out and put in to DB Browser for SQLite which is downloaded from https://sqlitebrowser.org/
public void delete1(String table,String COLUMN,String link) {
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL("DELETE FROM "+table+" WHERE "+COLUMN+" LIKE "+link+"%");
}
public void delete2(String table,String name){
SQLiteDatabase db = this.getWritableDatabase();
db.delete(table, "PRODUCTNAME" + "LIKE ?", new String[]{name+"%"}) ;
}
Could you tell me how to do it or how have i to correct code ?
using db.delete(table, "PRODUCTNAME " + "LIKE ?", new String[]{name+"%"}) ; will only delete rows that start with the value in name.
Perhpas you want :-
db.delete(table, "PRODUCTNAME " + "LIKE ?", new String[]{"%"+name+"%"}) ;
Then it would delete rows that contain the value rather than start with the value.
With db.execSQL("DELETE FROM "+table+" WHERE "+COLUMN+" LIKE "+link+"%"); you need to enclose the string in single quotes and assuming that you want to delete a row that contains the value then use :-
db.execSQL("DELETE FROM "+table+" WHERE "+COLUMN+" LIKE '%"+link+"%'");
Using the delete convenience method (the first part) is the better option as it protects against SQL Injection, it properly encloses the value, builds the underlying SQL and also returns the number of affected (deleted) rows.
If you use the following, this will write dome debugging information that may assist in debugging :-
public void delete2(String table,String name){
SQLiteDatabase db = this.getWritableDatabase();
Log.d("DELETEINFO","Attempting to delete rows with \n\t->" + name);
int deletedCount = db.delete(table, "PRODUCTNAME " + "LIKE ?", new String[]{"%"+name+"%"}) >0) ;
Log.d("DELETEINFO","Deleted " + deletedCount + " rows.");
}
I want to insert tables in Android SQLite database and then want to show that table names in a listView but after creating tables in database I am unable to retrieve table names from database.
My code of retrieving table names is as follows:
public void updateBranchList()
{
//this method will open database
openDatabase();
String sql = "SELECT name FROM sqlite_temp_master WHERE type='table' ORDER BY name";
Cursor c = db.rawQuery(sql,null);
//branchList is an ArrayList<String>
branchList.clear();
if(c.moveToFirst())
while(!c.isAfterLast())
{
String s = c.getString(c.getColumnIndex("name"));
branchList.add(s);
c.moveToNext();
}
db.close();
}
public void openDatabase()
{
db = openOrCreateDatabase("studentinfo", Context.MODE_PRIVATE,null);
}
The sqlite_temp_master table contains information about tables in the temporary database. For information about tables in the main database, you have to use sqlite_master instead.
I have an android app that needs to check if there's already a record in the database, and if not, process some things and eventually insert it, and simply read the data from the database if the data does exist. I'm using a subclass of SQLiteOpenHelper to create and get a rewritable instance of SQLiteDatabase, which I thought automatically took care of creating the table if it didn't already exist (since the code to do that is in the onCreate(...) method).
However, when the table does NOT yet exist, and the first method ran upon the SQLiteDatabase object I have is a call to query(...), my logcat shows an error of "I/Database(26434): sqlite returned: error code = 1, msg = no such table: appdata", and sure enough, the appdata table isn't being created.
Any ideas on why?
I'm looking for either a method to test if the table exists (because if it doesn't, the data's certainly not in it, and I don't need to read it until I write to it, which seems to create the table properly), or a way to make sure that it gets created, and is just empty, in time for that first call to query(...)
EDIT
This was posted after the two answers below:
I think I may have found the problem. I for some reason decided that a different SQLiteOpenHelper was supposed to be created for each table, even though both access the same database file. I think refactoring that code to only use one OpenHelper, and creating both tables inside it's onCreate may work better...
Try this one:
public boolean isTableExists(String tableName, boolean openDb) {
if(openDb) {
if(mDatabase == null || !mDatabase.isOpen()) {
mDatabase = getReadableDatabase();
}
if(!mDatabase.isReadOnly()) {
mDatabase.close();
mDatabase = getReadableDatabase();
}
}
String query = "select DISTINCT tbl_name from sqlite_master where tbl_name = '"+tableName+"'";
try (Cursor cursor = mDatabase.rawQuery(query, null)) {
if(cursor!=null) {
if(cursor.getCount()>0) {
return true;
}
}
return false;
}
}
I know nothing about the Android SQLite API, but if you're able to talk to it in SQL directly, you can do this:
create table if not exists mytable (col1 type, col2 type);
Which will ensure that the table is always created and not throw any errors if it already existed.
Although there are already a lot of good answers to this question, I came up with another solution that I think is more simple. Surround your query with a try block and the following catch:
catch (SQLiteException e){
if (e.getMessage().contains("no such table")){
Log.e(TAG, "Creating table " + TABLE_NAME + "because it doesn't exist!" );
// create table
// re-run query, etc.
}
}
It worked for me!
This is what I did:
/* open database, if doesn't exist, create it */
SQLiteDatabase mDatabase = openOrCreateDatabase("exampleDb.db", SQLiteDatabase.CREATE_IF_NECESSARY,null);
Cursor c = null;
boolean tableExists = false;
/* get cursor on it */
try
{
c = mDatabase.query("tbl_example", null,
null, null, null, null, null);
tableExists = true;
}
catch (Exception e) {
/* fail */
Log.d(TAG, tblNameIn+" doesn't exist :(((");
}
return tableExists;
Yep, turns out the theory in my edit was right: the problem that was causing the onCreate method not to run, was the fact that SQLiteOpenHelper objects should refer to databases, and not have a separate one for each table. Packing both tables into one SQLiteOpenHelper solved the problem.
// #param db, readable database from SQLiteOpenHelper
public boolean doesTableExist(SQLiteDatabase db, String tableName) {
Cursor cursor = db.rawQuery("select DISTINCT tbl_name from sqlite_master where tbl_name = '" + tableName + "'", null);
if (cursor != null) {
if (cursor.getCount() > 0) {
cursor.close();
return true;
}
cursor.close();
}
return false;
}
sqlite maintains sqlite_master table containing information of all tables and indexes in database.
So here we are simply running SELECT command on it, we'll get cursor having count 1 if table exists.
You mentioned that you've created an class that extends SQLiteOpenHelper and implemented the onCreate method. Are you making sure that you're performing all your database acquire calls with that class? You should only be getting SQLiteDatabase objects via the SQLiteOpenHelper#getWritableDatabase and getReadableDatabase otherwise the onCreate method will not be called when necessary. If you are doing that already check and see if th SQLiteOpenHelper#onUpgrade method is being called instead. If so, then the database version number was changed at some point in time but the table was never created properly when that happened.
As an aside, you can force the recreation of the database by making sure all connections to it are closed and calling Context#deleteDatabase and then using the SQLiteOpenHelper to give you a new db object.
Kotlin solution, based on what others wrote here:
fun isTableExists(database: SQLiteDatabase, tableName: String): Boolean {
database.rawQuery("select DISTINCT tbl_name from sqlite_master where tbl_name = '$tableName'", null)?.use {
return it.count > 0
} ?: return false
}
public boolean isTableExists(String tableName) {
boolean isExist = false;
Cursor cursor = db.rawQuery("select DISTINCT tbl_name from sqlite_master where tbl_name = '" + tableName + "'", null);
if (cursor != null) {
if (cursor.getCount() > 0) {
isExist = true;
}
cursor.close();
}
return isExist;
}
no such table exists: error is coming because once you create database with one table after that whenever you create table in same database it gives this error.
To solve this error you must have to create new database and inside the onCreate() method you can create multiple table in same database.
Important condition is IF NOT EXISTS to check table is already exist or not in database
like...
String query = "CREATE TABLE IF NOT EXISTS " + TABLE_PLAYER_PHOTO + "("
+ KEY_PLAYER_ID + " TEXT,"
+ KEY_PLAYER_IMAGE + " TEXT)";
db.execSQL(query);
i faced that and deal with it by try catch as simple as that i do what i want in table if it not exist will cause error so catch it by exceptions and create it :)
SQLiteDatabase db=this.getWritableDatabase();
try{
db.execSQL("INSERT INTO o_vacations SELECT * FROM vacations");
db.execSQL("DELETE FROM vacations");
}catch (SQLiteException e){
db.execSQL("create table o_vacations (id integer primary key ,name text ,vacation text,date text,MONTH text)");
db.execSQL("INSERT INTO o_vacations SELECT * FROM vacations");
db.execSQL("DELETE FROM vacations");
}
.....
Toast t = Toast.makeText(context, "try... " , Toast.LENGTH_SHORT);
t.show();
Cursor callInitCheck = db.rawQuery("select count(*) from call", null);
Toast t2a = Toast.makeText(context, "count rows " + callInitCheck.getCount() , Toast.LENGTH_SHORT);
t2a.show();
callInitCheck.moveToNext();
if( Integer.parseInt( callInitCheck.getString(0)) == 0) // if no rows then do
{
// if empty then insert into call
.....
this is my code :
SQLiteDatabase.loadLibs(this);
File databaseFile = getDatabasePath("db");
SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(databaseFile, "Ab61", null);
database.execSQL("drop table comments");
database.execSQL("CREATE TABLE IF NOT EXISTS comments(_id INTEGER PRIMARY KEY,spot_id INTEGER,server_id INTEGER" +
",description TEXT,uid TEXT ,dates TEXT,name TEXT)");
database.execSQL("insert into comments values (null, 34, 3, 'asdasd', 'asdsad', 'asda', 'asds');");
Cursor ss=db.rawQuery("SELECT * from comments", null);
Log.v("this",Integer.toString(ss.getCount()));
I've db database ,it's an sqlite database . this is a test code so , I remove the whole database ,create it again and insert a new row .
It doesn't get any error .
the cursor getCount return 0 , it means there is nothing added to database .
It driving me crazy :(
could you help me ?
You are inserting the data into a different database (database) than that which you are querying (db).
private void InitializeSQLCipher(){
try {
SQLiteDatabase.loadLibs(getApplicationContext());
}
catch (Exception e) {
e.printStackTrace();
}
File databaseFile = getDatabasePath("demo.db");
databaseFile.mkdirs();
databaseFile.delete();
database = SQLiteDatabase.openOrCreateDatabase(databaseFile, "test123", null);
database.execSQL("create table t1(a, b)");
database.execSQL("insert into t1(a, b) values(?, ?)", new Object[]{"one for the money","two for the show"});
}
Cursor c = null;
c = database.rawQuery("SELECT a,b from t1", null);
if (c != null){
if(c.moveToFirst()){
while(!c.isAfterLast()){
//Log.e("xlcx", c.getString(c.getColumnIndex("a")));
Log.d("xlcx", c.getString(c.getColumnIndex("b")));
c.moveToNext();
}
}
}
please refer
http://androidjug.blogspot.in/2014/07/sqlcipher-for-android-application.html
I am getting inconsistent results between two methods of reading the columns in an Android SQLite database.
First, this is part of a database upgrade routine as per the accepted answer here: Upgrade SQLite database from one version to another?
The technique involves moving the current table away with a temporary name, creating a new table with the new schema, and then copying relevant data from the old table into the new one before deleting the old temporary table.
The particular problem I have is when I remove a column from the schema. So, a particular column exists in the old version of the table, but not the new one.
That answer suggests using a method like this to list the columns in the table:
/**
* Returns a list of the table's column names.
*/
private List<String> getColumns(SQLiteDatabase db, final String tableName) {
List<String> ar = null;
Cursor c = null;
try {
c = db.rawQuery("SELECT * FROM " + tableName + " LIMIT 1", null);
if (c != null) {
ar = new ArrayList<String>(Arrays.asList(c.getColumnNames()));
}
} finally {
if (c != null)
c.close();
}
return ar;
}
That works fine on the old table, before I move it away with a temporary name and replace it. When I run the same query again later, on the newly-created empty table, it still lists the old table schema with the name of the column which no longer exists. It looks as if it's reusing stale cached results for that query.
If I read the columns a different way, using this instead, then it returns the new column list as expected:
private void listColumns(SQLiteDatabase db, final String tableName) {
final String query = "PRAGMA table_info(" + tableName + ");";
Cursor c = db.rawQuery(query, null);
while (c.moveToNext()) {
Log.v("MyApp", "Column: " + c.getString(1));
}
c.close();
}
The complete sequence is:
final String tempTableName = "temp_" + tableName;
table.addToDb(db); // ensure it exists to start with
// get column names of existing table
final List<String> columns = getColumns(db, tableName);
// backup table
db.execSQL("ALTER TABLE " + tableName + " RENAME TO " + tempTableName);
// create new table
table.addToDb(db);
// delete old columns which aren't in the new schema
columns.retainAll(getColumns(db, tableName));
// restore data from old into new table
String columnList = TextUtils.join(",", columns);
db.execSQL(String.format("INSERT INTO %s (%s) SELECT %s from %s", tableName, columnList, columnList,
tempTableName));
// remove backup
db.execSQL(DROP_TABLE + tempTableName);
What's the reason for the different results?
I assume you have done something similar to this:
ALTER TABLE "main"."mytable" RENAME TO "newtable";
CREATE TABLE "main"."mytable" ("key1" text PRIMARY KEY,"key2" text,"key3" text);
INSERT INTO "main"."mytable" SELECT "key1","key2","key3" FROM "main"."newtable";
DROP TABLE "main"."newtable";
If you have, please share the equivalent code, just to rule out any errors with this part.
I never got to the bottom of this. I just ended up using the second method I mentioned, which doesn't exhibit the problem.