I am trying to search on search database for user-input string. I would like to show any record that matches one or more input words.
I right now have following code/Query:
String sqlStr = "SELECT ID as _id, * FROM Had_Table
WHERE Collection_ID = " + CID + whereClause + "
AND ID IN (SELECT rowid FROM Had_Virtual_Table
WHERE Had_Virtual_Table MATCH ?
)";
String[] qStr = {query};
Cursor sHadCursor = sHadlistDB.rawQuery(sqlStr, qStr);
This returns results for a string, say, "Fat cat" only if they both exist in a record. I would like to get record even if it has only one of those words.
Also, I want records not be repeated twice(or more) if both words(fact cat) are found in a particular record.
Can anyone suggest anything?
Thank you
Related
I am building my first android app where I am trying to sync mysql data to sqlite in android. I have two tables in mysql and both gets synced properly into android sqlite. The first table is as follows:
id ProjectName
1 RA_Tesco
2 RA_Coors
3 RA_JWNT
The second table is as follows:
id pid Outlet Add1
1 1 Tesco XYZ
2 1 Tesco ABC
3 2 Coors NBC
The PID in second table references to id of first table. How can I subset the second table based on PID value derived from id of first table. I know it is pretty straight forward in php or mysql or even in Python or R. However, fetching the id based on string and referencing the same in the second table seems quite tricky in Android. My codes so far:
sqLiteDatabase = sqLiteHelper.getWritableDatabase();
clickedId = getIntent().getExtras().get("clickedId").toString();
When I toast clickedId, I get the correct string, for example, RA_Tesco.
cursor = sqLiteDatabase.rawQuery("SELECT * FROM "+SQLiteHelper.TABLE_NAME1+" where pid = 1"+"", null);
The above code also renders the correct set of records from the sqlite table. I am struggling with integrating them both. I tried the following:
String pid;
sqLiteDatabase = sqLiteHelper.getWritableDatabase();
clickedId = getIntent().getExtras().get("clickedId").toString();
pid = sqLiteDatabase.rawQuery( "select id from "+sqLiteHelper.TABLE_NAME+" where projectName = "+clickedId+"", null );
I am getting incompatible types error.
This is what worked for me:
clickedId = getIntent().getExtras().get("clickedId").toString();
cursor = sqLiteDatabase.rawQuery("SELECT * FROM "+SQLiteHelper.TABLE_NAME1+" where pid = (select id from "+SQLiteHelper.TABLE_NAME+ " where ProjectName = '"+clickedId+"'"+")", null);
I just followed the same MySQL principle of nesting queries. The above code roughly reads as follows:
select * from table2 where pid = (select id from table1 where projectname="xyz");
1) Try put your query to single quote
2) rawQuery returns Cursor, not String
So,
Cursor pidCursor = sqLiteDatabase.rawQuery( "select id from "+sqLiteHelper.TABLE_NAME+" where projectName = '"+clickedId+"'", null );
If you want to get the corresponding rows from the 2nd table when you pass as an argumnent the value of a ProjectName (I guess this is clickedId although its name is id?), create a statement like this:
String sql =
"select t2.* from " + SQLiteHelper.TABLE_NAME1 +
" t2 inner join " + SQLiteHelper.TABLE_NAME +
" t1 on t1.id = t2.pid where t1.ProjectName = ?";
This joins the 2 tables and returns all the columns of the 2nd table.
The execute rawQuery() by passing clickedId as a parameter, which is the proper way to avoid sql injection:
Cursor cursor = sqLiteDatabase.rawQuery(sql, new String[] {clickedId});
id| name |...
--------------
1 |Emmi blaa|..
2 |Emmi haa |..
3 |Emmi naa |..
I have SQLite database with table named contacts that contain id, name and other information. I'm trying to get name and id with name variable that I give in EditText.
String query = "SELECT name, id FROM contacts WHERE name LIKE \"%" + name + "%\"";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursorC = db.rawQuery(query, null);
while (cursorC.moveToNext()) {
System.out.println(cursorC.getString(0));
}
With the code above, I'm only able to get the names, but not the id so I tried GROUP_CONCAT
String query = "SELECT id, GROUP_CONCAT(name) FROM contacts WHERE name LIKE \"%" + name + "%\" GROUP BY id";
Now I get the ids only. How would I get both Id and name with name variable being "mm" for example?
I believe that your issue is not that the first query was not getting the id, rather that you weren't retrieving the id column from the cursor.
The following would work :-
String query = "SELECT name, id FROM contacts WHERE name LIKE \"%" + name + "%\"";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursorC = db.rawQuery(query, null);
while (cursorC.moveToNext()) {
System.out.println(cursorC.getString(0) + " : " + cursorC.getString(1));
}
However, ideally you should use the Cursor getLong method for retrieving id's as the id can be as large as a 64bit signed integer. So System.out.println(cursorC.getString(0) + " : " + String.valueOf(cursorC.getLong(1))); would be better.
Additionally an improvement would be to use the Cursor's getColumnIndex(the_column_name) method. This is more flexible as the index of the column is determined according to the column's name. As such System.out.println(cursorC.getString(cursorC.getColumnIndex("name")) + " : " + String.valueOf(cursorC.getLong(cursorC.getColumnIndex("id")))); would be recommended (it is also recommended that table and column names are defined as constants and then that those constants are used rather than hard coding the column/table names).
e.g. if the query were changed to SELECT id, name FROM contacts WHERE name LIKE \"%" + name + "%\"" then using hard-coded offsets 0 and 1 would transpose the results. However the results would be unchanged if using getColumnIndex.
If you wanted to use the 2nd query String query = "SELECT id, GROUP_CONCAT(name) FROM contacts WHERE name LIKE \"%" + name + "%\" GROUP BY id"; then note that the column names in the Cursor are id and GROUP_CONCAT(name), generally an alias would be given to the name using the AS keyword. e.g. String query = "SELECT id, GROUP_CONCAT(name) AS all_names FROM contacts WHERE name LIKE \"%" + name + "%\" GROUP BY id"; The column name in the resultant cursor would then be all_names.
Everything is ok with your first query. You are getting only name because you are getting only first column of the result: System.out.println(cursorC.getString(0));
To get other columns use similar methods cursor.getString() or cursor.getInteger() with 1 as parameter. Or even cursor.getInt(cursor.getColumnIndex("id"))
From the docs:
For each row, you can read a column's value by calling one of the Cursor get methods, such as getString() or getLong(). For each of the get methods, you must pass the index position of the column you desire, which you can get by calling getColumnIndex() or getColumnIndexOrThrow().
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.
I have a query with a subquery that returns multiple rows.
I have a table with lists and a table with users. I created a many-to-many table between these two tables, called list_user.
LIST
id INTEGER
list_name TEXT
list_description TEXT
USER
id INTEGER
user_name TEXT
LIST_USER
id INTEGER
list_id INTEGER
user_id INTEGER
My query with subquery
SELECT * FROM user WHERE id = (SELECT user_id FROM list_user WHERE list_id = 0);
The subquery works (and I use it in code so the 0 is actually a variable) and it returns multiple rows. But the upper query only returns one row, which is pretty logical; I check if the id equals something and it only checks against the first row of the subquery.
How do I change my statement so I get multiple rows in the upper query?
I'm surprised the = works in SQLite. It would return an error in most databases. In any case, you want the in statement:
SELECT *
FROM list
WHERE id in (SELECT user_id FROM list_user WHERE list_id = 0);
For a better performance, use this query:
SELECT LIST.ID,
LIST.LIST_NAME,
LIST.LIST_DESCRIPTION
FROM LIST,
USER,
LIST_USER
WHERE LIST.ID = LIST_USER.USER_ID = USER.ID AND
LIST.LIST_ID = 0
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.