I have been trying to use the character wild card "_" in sqlite where conditions and am close to "jumping off a high place" I have tried both rawQuery and query with a variety of hard and soft coded parameters. It seems to ignores the character wild card "_"and returns all rows or none at all.
The data held is in several columns representing a features of an oblect for example a column may represent the colours of an object
("red,orange,yellow,green,blue,indego,violet,black")
and a row's colour could be "01001000" meaning that it is orange and blue but not red, yellow etc. other columns contain single characters ie size contains s,m or l (mapping small, medium, large ) the database holds several columns of each type, the idea to have as compact a database as possible.
My first intention was to code by passing the 'where' of my select as a string to the rawQuery(myselect,null) where the myselect was compiled in the code in response to several features selected by the user.
ie
the mywhere string is compiled to return :-
colour1 like "_1__10__" and colour2 like "___1_01__" and size ="l"
and passed to the rawQuery
db.rawQuery("SELECT _id , name FROM widgets WHERE " + mywhere , null);
The statement below works fine using Firefox's SQLite Manager
SELECT _id , name FROM widgets WHERE colour1 like "_1__10_" and colour2 like "__1_01___" and size ="m"
In order to investigate I have cut the query down to one column in the where clause
myselect ="SELECT _id ,name,FROM widgets where colour1 like \"1_______\"";
cursor = db.rawQuery(myselect,null);
returns no rows
myselect ="SELECT _id ,name,FROM widgets where colour1 like \"%1_______%\"";
cursor = db.rawQuery(myselect,null);
returns rows but not all have a 1 at the first char ( I expected this )
myselect ="SELECT _id ,name, FROM widgets where colour1 like ?";
String[] whereArguments = { "1_______" };
cursor = db.rawQuery(myselect,whereArguments);
returns no rows
myselect ="SELECT _id ,name, FROM widgets where colour1 like ?";
String[] whereArguments = { "%1_______%" };
cursor = db.rawQuery(myselect,whereArguments);
returns rows but not all have a 1 at the first char
But I dont get any rows from
myselect ="SELECT _id ,name, FROM widgets where colour1 like ?";
String[] whereArguments = { "10000000" };
cursor = db.rawQuery(myselect,whereArguments);
and there are rows containing "10000000"
Does any one have any solutions? I have tried searching but it seems that rawQuery and query have questionable functionality in Android.
Not sure if this is your main source of problems, but the string delimiter in SQLite is the single quote character (') not the double quote one ("). See this, for example.
Related
I am using an SQLite database that holds different messaging conversations in a thread id. To get the main conversation list I use the following code:
database.query(true, MessagesHelper.CONVERSATION_TABLE, inboxCols, null, null, MessagesHelper.THREAD_ID, null, "${MessagesHelper.DATE} DESC", null)
The issue is that I provide a function to load in older messages that are not showing, by which I use:
database.insert(MessagesHelper.CONVERSATION_TABLE, null, values)
The issue is that after inserting messages, which are older than the most recent one that the distinct list used to call, it now shows the older added messages in the inbox list, which makes the list all out of order and causes a lot of confusion.
Here is the create statement:
private const val CONVO_CREATE = "CREATE TABLE $CONVERSATION_TABLE($NAME VARCHAR(255), $THREAD_ID VARCHAR(255), $MESSAGE_ID VARCHAR(40), $ADDRESS VARCHAR(14), $BODY VARCHAR(500), $SUBJECT VARCHAR(100), $MMS VARCHAR(255), $MESSAGE_TYPE VARCHAR(7), $MMS_TYPE VARCHAR(20), $CONVERSATION_TYPE VARCHAR(20), $GROUP_ADDRESS VARCHAR(255), $GROUP_NAME VARCHAR(255), $READ VARCHAR(10), $WHO VARCHAR(3), $COUNT INTEGER, $DATE INTEGER);"
Inbox columns are:
val inboxCols = arrayOf(MessagesHelper.COUNT, MessagesHelper.GROUP_ADDRESS, MessagesHelper.NAME, MessagesHelper.ADDRESS, MessagesHelper.READ, MessagesHelper.GROUP_NAME, MessagesHelper.BODY, MessagesHelper.DATE, MessagesHelper.THREAD_ID, MessagesHelper.CONVERSATION_TYPE, MessagesHelper.MESSAGE_ID, MessagesHelper.WHO)
Is there any way to insert into the database but have the distinct query still sort by each thread_id by date as well?
Thanks!
I believe the issue is that DISTINCT considers the entire row being extracted, thus it is likely, based upon the column names, that both the COUNT column and the DATE column would or could likely be different when inserting a new message (e.g. perhaps count would initially be 0?) and thus cause them to be inserted as they make a new row DISTINCT (not a duplicate).
e.g. Consider this table :-
Then if DISTINCT is used just on the idbet column, the result is 2 rows 1 for where idbet is 3000 and another for where idbet is 1981 as per :-
However, if columns idbet and gamble are extracted then all 4 columns are extracted as there are now no duplicates, as per :-
If the row with _id 350 had WIN in the gamble column then 3 rows would be extracted as rows with _id's 349 and 350 would be a duplicate according to the idbet and gamble columns, as per :-
Perhaps rather than DISTINCT, or just DISTINCT you should use a WHERE condition or conditions (4th and 5th parameters of query). Perhaps "count < 1" as the 4th parameter (5th null) this does assume that count will initially be 0. An alternative would be to reduce the columns extracted but that may not be practical.
I am struggling to get more complicated queries to work with SimpleCursorAdapter and ViewBinder with a ListView. When I was just returning all entries in my table, that was no problem. However, I want to return a list of artist names from my tables in order of name. The big problem concerns the "rowid _id" field which SimplerCursorAdapter/ViewBinder expects.
My code worked fine when I had queries of the form SELECT rowid _id, Artist.NAME etc, but I want to use the DISTINCT keyword to return the unique set if artist names. I can't put "rowid _id" before "DISTINCT Artist.Name" and I can't put it after. What is the solution for this?
The query I want (A) is (shown without the "rowid _id"):
String sQuery = String.format( "SELECT DISTINCT Artist.Name, Artist.ID FROM Artist JOIN Tune ON Artist.ID=Tune.ArtistID AND Tune.Type=%d AND Tune.SubType=%d ORDER BY Artist.Name", nType, nSubtype );
To clarify, this works:
Cursor c = db.rawQuery( "SELECT rowid _id, Name, Rating FROM Tune ORDER BY Name", null );
Whenever I put rowid _id back into query (A), I get "no such column rowid" exceptions:
String sQuery = String.format( "SELECT rowid _id, Artist.Name, Artist.ID FROM Artist JOIN Tune ON Artist.ID=Tune.ArtistID AND Tune.Type=%d AND Tune.SubType=%d ORDER BY Artist.Name", nType, nSubtype );
What am I doing wrong?
EDIT: I don't even understand what the "rowid _id" does anyway - my SQLite Manager (test tool) doesn't like it either when I have a query with a join. It only seems to work on a simple 1 table query.. So if thats the case.. how do I make this query work without it for SimpleCursorAdapter & ViewBinder?
The answer was to forget about using rowid and use my own Artist.ID field instead. This will work as long as I alias the field name to _id which SimpleCursorAdapter expects in column 0.
String sQuery = String.format( "SELECT DISTINCT Artist.ID _id, Artist.Name FROM Artist JOIN Tune ON Artist.ID=Tune.ArtistID AND Tune.Type=%d AND Tune.SubType=%d ORDER BY Artist.Name", nType, nSubtype );
I followed advice in this question, but for my purposes I don't want a WHERE.
I don't know the value, so I cannot say rawQuery("... WHERE x = ?", y), I don't care what y is, it's just a cell I want, and it is known that there is a single row.
If it is not possible to lose the condition (perhaps because of causing an indeterminate number of results?) - then how can I say "from column z and row 0"?
I'm lacking either terminology, or outright understanding, because my searches are turning up nothing.
Edit: Eclipse doesn't complain at:
result = db.rawQuery("SELECT col FROM tbl", my_unused_string_array);
I'm not at a testing stage yet, and I can't enter this into the SQL db reader I was using to test SELECT col FROM tbl and ~ with WHERE.. will it work?
As per your edit, you don't need to specify WHERE clause, if you want to get all the records from a table:
result = db.rawQuery("SELECT col FROM tbl", new String[0]);
The SQL query "SELECT * FROM table" will return the entire table. "SELECT colX, colY FROM table" will return columns colX and colY for all the rows in the table. If your table contains just one row, "SELECT col FROM table" will return the value of col for that one row.
To use the SQLiteDatabase API to make that query, you would say:
result = db.rawQuery("SELECT col FROM tbl", null);
... because you are not supplying any query parameters.
Assuming that there is just one row seems dangerous to me. I would not use the "LIMIT" clause, because, while that will always get one row, it will hide the fact that there is more than one row, if that happens. Instead, I suggest that you assert that the cursor contains one row, like this:
if (1 != result.getCount()) {
throw Exception("something's busted");
}
Instead of Raw query use
Cursor cur = db.query(Table_name, null, null, null, null,
null, null);
and get the desired attributes from cursor.
where the query method has parameters in following manner:
public Cursor query (String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
Parameters:
table The table name to compile the query against.
columns A list of which columns to return. Passing null will return all columns, which is discouraged to prevent reading data from storage that isn't going to be used.
selection A filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). Passing null will return all rows for the given table.
selectionArgs You may include ?s in selection, which will be replaced by the values from selectionArgs, in order that they appear in the selection. The values will be bound as Strings.
groupBy A filter declaring how to group rows, formatted as an SQL GROUP BY clause (excluding the GROUP BY itself). Passing null will cause the rows to not be grouped.
having A filter declare which row groups to include in the cursor, if row grouping is being used, formatted as an SQL HAVING clause (excluding the HAVING itself).
Passing null will cause all row groups to be included, and is required when row grouping is not being used.
orderBy How to order the rows, formatted as an SQL ORDER BY clause (excluding the ORDER BY itself). Passing null will use the default sort order, which may be unordered.
Returns
A Cursor object, which is positioned before the first entry.
I am new to Android, and having some basic problems. One of them is the use of queries.
I store a boolean value as either 1 or 0 in the table (INTEGER field). However, when I select either on 1 or 0 using the query below I get no results. What am I doing wrong?
Cursor cursor = _db.query(_objectName, _fields.keySet().toArray(new String[0]), "parentId=? AND published=?", new String[] {String.valueOf(menuItem), String.valueOf(1)}, null, null, "level");
There is nothing wrong with your query. The problem must be elsewhere. Check your code and table structure. Maybe you are not sending the right values for parentId and published columns or the data in the table is not in the format you expected.
Use raw query
"Select * from "+TABLE_NAME+" where published = '"+String.valueOf(1)+"'";
You can put your integer value insted of 1
I want my rawQuery to populate my data according to these 2 conditions. But it is showing and empty listview. It is not comparing the second condition.
Cursor c = db.myDataBase.rawQuery("SELECT _id, word,definition,sentence,yourstory,isfavor FROM words WHERE word LIKE ? AND isfavor= ? ",new String[]{""+employeeId+"%",""+'1'});