Insert and select in Android - android

I have very strange problem.
After a lot of debugging I come to following line of code:
db.db.rawQuery("INSERT INTO goal_calendar(timestamp) VALUES(1)", null);
db.cursor = db.db.rawQuery("SELECT * FROM goal_calendar", null);
Log.e("SIZE", String.valueOf(db.cursor.getCount()));
The result is "Size 0".
There is no any errors at all. Everything worked just fine and suddenly it didn't want to store nothing in my table. It just stopped. What could be wrong?
According to me the result after these three lines of code SHOULD ALWAYS be error(exception) or SIZE should be greater than 0.

Because this
"INSERT INTO goal_calendar(timestamp) VALUES(1)"
is not a QUERY (SELECT),but a COMMAND.
For commands (INSERT, UPDATE, DELETE, ...), use this:
db.execSQL("INSERT INTO goal_calendar (timestamp) VALUES (1)", null);
I also have some doubts on why do you double "db."
I'd use "db.rawQuery" and "db.execSQL", instead of "db.db.rawQuery" and "db.db.execSQL".
Now two words of explanation:
Your INSERT statement doesn't work. That's why your query correctly returns a zero count.

Related

SQLiteStatement.simpleQueryForLong() is behaving differently compared to what the documentation says

I'm using the simpleQueryForLong() method in the following way:
mResuableStatment = DatabaseHandler.database.compileStatement(
"SELECT MIN(timestamp) FROM " + TABLE_LOCAITON_LOGGING);
long oldestTimestamp = mResuableStatment.simpleQueryForLong();
timestamp is the name of the column within the table TABLE_LOCAITON_LOGGING.
the database is open for read and write at that point.
according to the documentation - if there are no rows at all, then this code suppose to throw SQLiteDoneException, but what really happening is that when there are no rows - the simpleQueryForLong() returns zero (without throwing excpetion)
What was even more strange and unexpected, when I actually wrap this code in try/catch block, it will throw SQLiteDoneException every time, even when there are rows in the table:
try {
long oldestTimestamp = mResuableStatment.simpleQueryForLong();
} catch (SQLiteDoneException e) {
e.printStackTrace()
}
This behavior was seen on Nexus 5, Galaxy Nexus, LG G2, HTC One X, all running Android KitKat.
I'm a little confused because this forced me not to use the try/catch block, since if it's used - the exception is always thrown regardless if there are rows or not, and vice versa to what the documentation says.
Seems like in every device I tested - without the try/catch block, when there are no columns - it returns zero.
Please help me to understand what is the right way, and what I'm doing wrong, or if simply the documentation is wrong.
Actually, I think you'll find you have it the wrong way around.
select min(something) ...
will never return zero rows. It will either return the minimum value (if the table has rows) or null if the table has no rows. If your query was just select something when the table was empty, that could return zero rows so that might be worth testing.
I've tested this with SqlFiddle, entering the commands:
create table xyzzy(a int);
select a from xyzzy;
select min(a) from xyzzy;
The first select returns zero rows, the second returns one row with a (null) value.
So I don't believe it's the empty table causing the exception. It may be the attempted conversion of (null) into a long.
How you "fix" this depends entirely on what you want to use the data for. Relying on a null row being converted to zero may or may not be what you want. For example, if there was a zero timestamp in the table, you would not be able to tell the difference between that and an empty table.
That may be acceptable, it depends on your business requirements.
If you need to distinguish, I would run two queries. The first would return count(*) from the table. That's guaranteed to be a single row containing a numeric value (no nulls). If that's zero, it means the table is empty.
If non-zero, then do the min(column_name) and you'll get a single row with the minimum timestamp. If you get zero at that point, you know it's because the minimum timestamp was zero. Unless of course there's a NULL timestamp in there in which case you may have to do more checks. But I think that unlikely if you've structured your schema correctly.
Note that I wouldn't normally suggest this in a multi-user database since it may lead to race conditions. But I think it's probably okay since there should only be one "user" of this database, your application.

android: SQLite query returns no results

I am building an Android app that uses a SQLite database.
For this one task I have to run a query that looks like this:
SELECT item.id, item.price, t1.quantity
FROM item, (SELECT id, price
FROM list
WHERE list.state = 'sold') t1
WHERE item.id = t1.id
So far, I have tried:
Cursor c = resolver.query(uriRawQuery, null, selection, null, null)
where uriRawQuery is used to tell the ContentProvider that it should perform a db.rawQuery(selection, null) and selection is a string similar to the query above.
The problem is no data is returned into the Cursor. When I call c.moveToFirst() I get false.
The weird thing is that if I open the database file in SQLite Manager and run the exact same query I get results.
I know I can modify the query to make a join between the original list and item tables but I find it to be less efficient that way.
Any ideas would be very appreciated as I have spent too man hours on this already.
EDIT
I know what a join is, what I said is that it is a lot more efficient if I do it like this instead of using the entire list table.
I forgot a very important aspect
The WHERE clause looks like
" WHERE list.state = 'sold' and list.name like '" + arg + "%'"
where arg is a string.
I managed to solve the problem, I still don't know why this was happening but at least I got the Cursor to actually select the rows.
After many trials I thought about ditching the syntax above and write this instead:
" WHERE list.state = 'sold' and list.name like ? "
and move the argument in
selectionArgs = new String[]{arg + "%"}
I am going to wait a while before accepting the answer, in case someone provides an explanation as to why even though both queries look exactly the same they get different results.

Android SQLite "random" rows seem inaccessible

I have a database with 4 columns. Everything works fine except for the fact that random rows remain inaccessible. I cannot seem to update or delete them. I've used the right code:
DELETION CODE:
boolean deleted=db.delete(TABLE_NAME, KEY_BLAH + "=" + alarm, null) > 0;
CODE FOR UPDATE:
db.update(TABLE_NAME, args, KEY_BLAH + "=" + blah, null)
The deletion code returns false and the update code returns 0 for some rows, which are arbitrary. The rows are implemented into a ListView. Any changes on the ListView elements should be reflected in the SQLite Database. Most of the times the code works. It doesn't seem to work for random rows at random points though. I do not think this is SDK related. I've tried it on ICS, GB and JB.
I've also tried deleting the row and inserting it. Obviously this wouldn't work because my delete statement doesn't seem to work. The logic for this was, if the update wasn't possible it would delete the row and insert the row with the same row id and different data. So, the deleted variable was the condition for an if-block which didn't get executed.
EDIT
Example:
1 1414 000 off
When I click on a few buttons in the list item.
It should become
1 1414 064 off
Now, this works most of the times except for some random rows as I said before.
If you (indirectly) execute an SQL statement like this:
UPDATE MyTable SET x = '064' WHERE blah = 1414
then the values in the blah column are compared with the number 1414.
When using strings in SQL statements, you should always use parameters to avoid formatting problems like this (and SQL injection attacks):
db.update(TABLE_NAME, args, KEY_BLAH + "= ?", new String[] { blah })

rawQuery on "count(*)" return no row

I'm trying to fix a DB issue I had in Ankidroid. The following statement was executed:
SELECT count(*) FROM cards c WHERE type = 1 AND combinedDue <
1335153600.000000
It was generated there. The code executed is the following (github link):
cursor = mDatabase.rawQuery(query, null);
if (!cursor.moveToNext()) {
throw new SQLException("No result for query: " + query);
}
I can't understand how I can get no record, I should get either 1 or 0. The call stack in the log was the following:
at com.ichi2.anki.Deck.rebuildRevCount(Deck.java:1351)
Caused by: android.database.SQLException: No result for query: ……
at com.ichi2.anki.AnkiDb.queryScalar(AnkiDb.java:129)
at com.ichi2.anki.Deck._rebuildRevCount(Deck.java:1621)
Any idea?
In fact, I was more looking at a similar case. We have a table «Stats» with a column "global", in which there can be one global record and many daily records. If we don't find (a simple select) the global record, we create it. On my phone, it seems that sometime the global record is not found, so we create an additional one, which break things.
It really look like the case I showed above.
Edit:
I found why. In another thread, an AsyncTask closes the DB at the same time the query is being made (because a lot of processing triggered by the GUI is done asynchronously). And it returns a cursor with no record.
I saw that by adding traces to a file.
Try if (cursor.moveToFirst == false) instead of using the ! operator. I think that the way you are currently doing it is always going to.pass you into the body of the if. And the cursor isn' t properly initialized.without a.moveToFirst.

Problem while updating table in android

I created a table in the database that has the data like this:
Now i have written a query that updates the contact field by concatinating name and email fields:
UPDATE MyContacts SET contact=(SELECT name||'--'||email FROM MyContacts);
Here the problem is after executing the query the table is as below:
Why is it happening like this? In oracle i never faced this problem. Please help me. Thank you
Right now you're not specifying the correct row to retrieve the values from. Try something like this:
UPDATE MyContacts SET contact = name||'--'||email;
EDIT: Glad it worked. Your first issue was that your sub-select uses a SELECT statement with no WHERE clause (SELECT name||'--'||email FROM MyContacts will return 3 rows). One possible solution would be for SQLite to throw an error and say You've tried to set a column to the result of an expression that returns more than 1 row: I've seen this with MySQL and SQL Server. However, in this case SQLite appears to just use only the very first value returned. However, your second error then kicks in: since you don't narrow your UPDATE statement with a WHERE clause, it uses that first value returned to update EVERY single row, which is what you see.

Categories

Resources