Android SQLITE : Get Id value based on column value - android

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});

Related

SQLite get ids and names WHERE name LIKE

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().

SQLite: FTS search user-input string in my app

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

FTS4 sqlite MATCH not working

I've tried several methods from here:
SQLite FTS example doesn't work
and here:
Full text search example in Android (best tutorial so far i think)
However, my search returns 0 results!
Here is what I've tried:
String key = "a";
Cursor c = db.query(true, "texts_virtual",
new String[]{"id","title_normalized"},
"title_normalized MATCH '"+key+"'",
null, null, null, null, null);
= 0 Results;
String query = "a";
String[] params = {"%" +query+ "%"};
Cursor c = db.rawQuery("SELECT * FROM texts_virtual WHERE title_normalized MATCH ?", params);
= 0 Results too
I know that the virtual table is correctly working because I can do this:
String queryText = "a"; //here i test other texts and they worked too
String query = "select * from texts_virtual where title_normalized like ? order by number";
String[] params = {"%" + queryText + "%"};
Cursor c = db.rawQuery(query, params);
so this prove that the texts_virtual is working, what is not working are the queries, but I don't know why, not error, nothing, just 0 results.
Also after I make it work, I'm planning to use multiple terms search in 2 columns
user type "WordA WordB WordC"
it search for each word in the 2columns and return the results, but this if for a future task....
Edit
Table Code Creation:
CREATE TABLE texts (id INTEGER PRIMARY KEY AUTOINCREMENT, title_normalized....);
INSERT INTO texts (id, titulo_normalized...) VALUES (1, 'aaaaaa', ...);
and go on for more inserts, and at the end the virtual creation
CREATE VIRTUAL TABLE texts_virtual USING fts4(content="texts", id, title_normalized, ..other fields);
i can query texts_virtual using LIKE but not MATCH, match return 0 results =/
Edit 2 how the table looks:
Table: texts_virtual
----------------------------
id --- title_normalized
--------------------------
1 --- aaaaaaaaab
2 --- abbbbbbbbb
3 --- bbbbbabbbb
4 --- bbbbbbbbbb
The FTS module searches for words (where the exact definition depends on the tokenizer used), or at best for words with a prefix.
MATCH words as designed; it does not find "a" because there is no word "a" in your data.
If you want to find substrings inside words, you must use LIKE.
You are using % as a joker. In FTS requests, You have to use * instead.
LIKE "%word%"
MATCH "*word*"
I've noticed that for very short words (less than 3 letters), LIKE is faster than MATCH. For longer words, MATCH is faster.

Getting raw SQL query after a prepared statement is built on android

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);

What is the correct syntax for SELECT statement and WHERE clause?

I am trying to explore android and I just started using SQLite database. I'm wondering on what is the right syntax for selecting a single row from a table, where the row I want to select is from the value entered from a user using editText. Thanks in advance.
I'm going to disagree with both of the answers above. What if the user enters this query:
Bobby Tables'; drop table yourTable;
See: http://xkcd.com/327/
I believe you should do this instead:
String query = "select * from TABLE_NAME WHERE column_name=?";
String[] selection = new String[1];
selection[0] = users_entered_value;
Cursor c = db.rawQuery(query, selection);
ETA: Actually, the more I think about it, the more I think you're going in the wrong direction. If your app depends on a database query returning exactly one unique match to an arbitrary string entered by the user, it's probably going to be broken a great deal of the time.
What you should probably do is something like this:
String query = "select * from TABLE_NAME WHERE column_name LIKE ?";
String[] selection = new String[1];
selection[0] = "%" + users_entered_value + "%";
Cursor c = db.rawQuery(query, selection);
and then iterate through the results and pick a "best" match according to your own criteria.
Also, you should create the table with case-insensitive matching for the column(s) you're going to be searching.
SQLiteDatabase db;
db.rawQuery("select * from yourTable where your_column_name = 'users_entered_value' limit 1", null);
SQLiteDatabase db;
// make connection to your database ;
Cursor c = null ;
String SQL = "select * from TABLE_NAME where column_name='VALUE'";
c = db.rawQuery(SQL);
c contains your result array of query you fired.
You can retrieve values using loop.

Categories

Resources