I'm working on Android application that uses SQLite as a local storage. I need to use parameters in sql query but all examples I have found contain unamed parameters, like so:
INSERT INTO SomeTable(ColA, ColB, ColC) VALUES (?,?,?);
I'm wondering - does SQLite on Android supports named parameters? Something like this instead of question marks..
INSERT INTO SomeTable(ColA, ColB, ColC) VALUES (#paramA, #paramB, #paramC);
SQLite itself supports this (according to the documentation https://www.sqlite.org/lang_expr.html).
Thanks in advance
The Android database API allows parameter binding only by index.
This does not prevent you from using named parameters in SQL, but you still have to use the correct index to bind them.
This is pretty much useless, except for documentation, or for reusing a parameter:
db.rawQuery("SELECT * FROM Tab WHERE A = #search OR B = #search",
new String[]{ search });
A more android SQLite specific way is to use a ContentValues for sql insert. In the example below. values is a ContentValues and it contains the column name and the value for the column. Columns not in the ContentValues are set to their default value on the insert.
id = sqlDB.insertOrThrow(RidesDatabaseHandler.TABLE_RIDES,
null, values);
Related
I want to use SQLite's built-in function datetime('now','localtime') in my Android code to save date in a database field of TEXT type. I am already able to do this in sqlite3 terminal as follows:
sqlite> INSERT INTO test (Name, NO, date) VALUES('John', 1151, datetime('now','localtime'));
sqlite> SELECT * FROM test;
John|1151|2017-06-23 17:38:29
This is fine, until I want to use the datetime() function with Android's ContentValues. I use it like this:
ContentValues values=new ContentValues();
values.put(Entry.NAME,nameString);
values.put(Entry.NO,noInt);
values.put(Entry.DATE,"datetime('now','localtime')");
/// ....
getContentResolver().insert(Entry.CONTENT_URI,values);
Then, my listview shows everything fine, but for the date's textview I exactly see the text datetime('now','localtime') instead of the date that I expected to be saved in the database e.g. 2017-06-23 17:38:29. How can I solve this problem? Is there a way I can use built-in SQLite functions with ContentValue objects for inserting data?
How can I solve this problem?
Do not use insert(). Use execSQL().
Is there a way I can use built-in SQLite functions with ContentValue objects for inserting data?
No, sorry.
Is it possible to use ContentValues.put() to update a column in a SQLiteDatabse to be the sum of other columns?
I have searched on here and on the web and the closest answer I have found is: Update one column as sum of other two columns. This doesn't quite answer my question because it requires a raw database command, which I would prefer to avoid (if possible).
I have a fairly static database that I have generated unique permutations in (long setup, fast queries). I am attempting to set a total column at the end for even faster sorting on the permutations. I am currently attempting to use:
ContentValues values = new ContentValues();
values.put(totalVal, sumString);
where I have tried to set sumString to both:
=val_1+val_2+val_3...
and
val_1+val_2+val3...
When I look at my database in adb shell, sqlite3 I see:
Which looks... correct? Except when I query my database after this has been set, I get this in the log:
My val_* columns show values in the same adb shell, sqlite3 dump. Also, I do not set the totalVal column to this sumString until the val_* columns are all populated with their values.
Is it just not possible to use ContentValues.put()? Does it do some sort of internal escaping?
The reason it seems like it should work to me is the totalVal column is set to REAL so if ContentValues.put() does do internal escaping I thought I would get an error since I would essentially be putting a String value in a column that should only accept REAL.
Like I said earlier, my database is pretty static and only there for fast queries and sorting. It would be possible for me to loop through all the val_* columns and manually sum them up. Although, there are thousands of rows in my database so I was hoping to avoid this and was looking for a more elegant way to do this.
Thanks for the help.
SQLiteDatabase.update() is just a convenience method for updating rows in the database, so in your case you are just overcomplicating things trying to use ContentValues instead of SQLiteStatement and binding arguments which is what SQLiteDatabase.update() uses internally but preventing that column names were considered Strings.
It's not very clear from your example but if you are trying to update some values and at the same time calculate the totalVal do something like this
SQLiteStatement stmt = db.compileStatement("UPDATE mytable SET val_1=?, val_2=?, val_3=?, totalVal=val_1+val_2+val_3 WHERE expr");
stmt.bindLong(1, 1);
stmt.bindLong(2, 3);
stmt.bindLong(3, 5);
stmt.executeUpdateDelete();
EDIT
So as mentioned in your comment you don't need to bind values, it's even simpler
final int rows = db.compileStatement("UPDATE mytable SET totalVal=val_1+val_2+val_3").executeUpdateDelete();
and regarding your comment about "raw" SQL, ContentValues are not an option so this is the only way (AFAIK).
This is SQLite for Android...
I am inserting a new column using ALTER TABLE tablename ADD COLUMN.
I have 2 questions:
Is there a way I can just copy values from existing columnA to this newly inserted/added columnB?
I need to add another columnC, the value of which is MD5 hash output of columnA. Is there a way SQLite can add columnC and set its value to MD5 hash (either using an existing SQLite internal function or my custom function)
UPDATE MyTable SET NewCol = columnA
The Android DB API does not expose a mechanism for registering custom functions.
You have to read all the columnA values, compute the hash in your code, and update the records one by one.
I am currently studying SQLite and I have found that it uses various classes like ContentValues for insertion and updation... I was wondering whether I have to follow the given way or can I write a normal SQL query and use db.execSQL() method to execute them?
Will it bring any inconsistency to my database because with these all "extra" steps doesnt it stop the flow of the query and I feel it would be faster if we use a query directly.
You can do any SQL command you want with db.execSQL except select command or any other SQL command that return data (you use db.rawQuery() for this). The classes used are helper classes that make it easy for you to manipulate DBs (try inserting 100 rows with 20 columns each using ContentValues and db.execSQL and you will get the point). For small tables it will not differ much (and you will not cause inconsistecies), however, for large tables with inputs that depend on user interface or use calculations, it might be useful to have a class like ContentValues with its helper methods.
Yes you can definitely use this way like using
myDB.execSQL("INSERT INTO MyTable VALUES ('fffff', 'numb', 20)");
to insert values but only when you are using database for small queries.
Also there are some flaws using direct methods which gets removed using ContentValues
For example,try to insert a blob into the database using this method ,you will get a null bitmap while converting the retrieved data to bitmap.But when you insert using ContentValues,you will get the correct data i.e you will be able to convert that into Bitmap.
The Android SDK has some convenience methods for manipulating data with SQLite. However both the insert and replace methods use some nullColumnHack parameter which usage I don't understand.
The documentation explains it with the following, but what if a table has multiple columns that allow NULL? I really don't get it :/
SQL doesn't allow inserting a completely empty row, so if initialValues is empty, this column [/row for replace] will explicitly be assigned a NULL value.
Let's suppose you have a table named foo where all columns either allow NULL values or have defaults.
In some SQL implementations, this would be valid SQL:
INSERT INTO foo;
That's not valid in SQLite. You have to have at least one column specified:
INSERT INTO foo (somecol) VALUES (NULL);
Hence, in the case where you pass an empty ContentValues to insert(), Android and SQLite need some column that is safe to assign NULL to. If you have several such columns to choose from, pick one via the selection mechanism of your choice: roll of the dice, Magic 8-Ball(TM), coin flip, cubicle mate flip, etc.
Personally, I'd've just made it illegal to pass an empty ContentValues to insert(), but they didn't ask me... :-)