I'm making an Android app and I have used an SQLite database. But I found out if you type characters like single quotes ('), (also for using as the primary key) the data won't be saved/retrieved correctly.
Is it a problem with me or is it true? If its true are there any more characters like that?
Thanks.
#bdares and #mu Thanks for the tips, but can you please tell me how to use placeholders and/or prepared statements in SQLite?
I have always used direct String concatenation before but now, as it appears that's a bad practice, I would like to use prepared statements and/or placeholders.
Possibly you'll have problems with characters like ASCII STOP and such non-printing characters, but if you use prepared statements and parameter binding, you won't have any trouble even with characters like '.
If you don't want to use parameter binding and prepared statements, you can replace all of your input ' with \' and you'll be fine.
SQL typically uses ' as its special character to tell when a string literal starts or stops. If your input has this character, it will stop treating the current line as a string and start treating it as commands. This is not a good thing, security wise. It also keeps you from inputting that character unless you "escape" it by placing a backslash in front of it, which tells SQL to ignore the ' and continue treating the following characters as a string until an unescaped ' is met. Of course, backslash literals are also escaped as double-backslashes.
Prepared statements typically look like this:
String sql = "INSERT INTO MYTABLE (NAME, EMP_NO, DATE_HIRED) VALUES (?, ?, ?)";
PreparedStatement ps = sqlite.prepareStatement(sql);
ps.setString(1, myString);
ps.setInt(2, myInt);
ps.setDate(3, myDate);
ps.executeUpdate();
Unfortunately, I don't know exactly what library you'd be using to access sqlite from Android, so I can't give you more details at this time.
SQLite statements use quotes -- single or double -- for strings. If you need to INSERT a string with (') for example, you can use double quotes (") to wrap the string:
INSERT INTO my_table (some_column) VALUES("'a string'");
Or the other way around:
INSERT INTO my_table (some_column) VALUES('"a string"');
(Of course, you will need to escape any (") in your Java code.)
An alternative is to use a SQLiteStatment (Prepared statement) and bindString()
As for the "characters allowed", SQLite internally stores strings (type TEXT) as UTF-8 or UTF-16. Android's build uses the default of UTF-8. Therefor, you can store any string you like.
SQLite supports the data types TEXT (similar to String in Java), INTEGER (similar to long in Java) and REAL (similar to double in Java). All other types must be converted into on of these fields before saving them in the database. SQLight itself does not validate if the types written to the columns are actually of the defined type, you can write an integer into a string column.
Related
I am creating a notes app. The user can input a note, and it will get saved to the database/displayed on the screen.
I have a DatabaseHelper class which includes all the CRUD methods(Create, Read, Update, Delete).
When I update a specific note in a table, I have to do it like this:
db.update("Note", contentValues, "id='"+id+"'", null)
with '' surrounding the user's id.
However, when I am querying to read a note, I don't have to include the '':
String fetchOneNote = "SELECT * FROM Note WHERE id="+id;
Is there a specific reason for this? It seems like in both, I am referring to the database, so why do I need the ''?
Thanks!
There is no need to enclose a numeric literal in single quotes but single quotes are required for a string literal.
So IF id is numeric there is no need to enclose it in single quotes. However, it doesn't hurt to enclose a numeric literal in quotes.
As such ASSUMING that id is numeric then:-
db.update("Note",contentValues,"id=" + id,null)
will effectively work the same as :-
db.update("Note", contentValues, "id='"+id+"'", null)
However, the recommended use of the SQLiteDatabase update method is to utilise the 4th parameter for the where clause parameters which protects against SQLite injection. As such it would be better to use :-
db.update("Note",contentValues,"id=?",new String[]{id});
The SQLite parser then handles the id appropriately, replacing the ? with the value and protects against SQLite injection.
See https://sqlite.org/lang_expr.html#literal_values_constants_ and also https://sqlite.org/lang_expr.html#parameters
Although the explanation regarding binding parameters includes:-
But because it is easy to miscount the question marks, the use of this parameter format is discouraged. Programmers are encouraged to use one of the symbolic formats below or the ?NNN format above instead.
The ? is commonly used. This is what the update method (and other methods) expect.
It does mean that on occasions you may have to code the same parameterised (bound) parameter twice along with ?'s (as you would if not using bound parameters).
Interesting issue while using SQLite in Android. I am seeing an inconsistency in the string length and quoting of a string between what is stored in the database and the materialized value seen in Java.
We are using an ORM called SugarORM to query the DB, but I've traced the offending code to the internal android.database.sqlite.SQLiteCursor class used within SugarORM, specifically the cursor.getString(columnIndex) method.
I have a string in the database that is an ISO data string 2019-03-25T19:19:39.664Z and is stored in a VARCHAR column . I have confirmed using DB Browser for SQLite that the length of the string as its stored in the database is indeed 24 characters. SELECT LENGTH(MyStringColumn) FROM MyTable WHERE ...
When I get the value of this string via cursor.getString(columnIndex), it is returning the string "2019-03-25T19:19:39.664Z". Notice the leading and trailing quotes. Java reports to me that the string is 26 characters long.
Any value that I store in this column that is not an ISO data does not have this behavior. I tried tracing the SQLiteCursor source back, but ultimately it ends up being a Native method and that's where my skill set stops.
Can anyone explain what might be going on here? I am probably just going to write a wrapper around my queries to get rid of the quotes, but its all very perplexing. The date string is being fed to a JavaScript interpreter and causing it to fail when creating a JavaScript Date object.
If it helps, I have replicated the behavior on both my S7 physical device and a Pixel 6 emulator.
As a quick get around you could use :-
SELECT length(replace(mystringcolumn,'"','')) FROM mytable;
or before using the original SELECT use :-
UPDATE mytable SET mystringcolumn = replace(mystringcolumn,'"','');
If this doesn't fix the issue, then for some reason it is the code that retrieves the data that is at fault.
e.g. consider :-
DROP TABLE IF EXISTS mytable;
CREATE TABLE IF NOT EXISTS mytable (mystringcolumn VARCHAR);
INSERT INTO mytable VALUES('2019-03-25T19:19:39.664Z'),('"2019-03-25T19:19:39.664Z"');
SELECT length(mystringcolumn), length(replace(mystringcolumn,'"','')) FROM mytable;
which results in :-
i.e. The 2nd row, 2nd column retrieves the appropriate value by using the replace function to strip of the quotes, if they exist.
As to why the quotes exist could depend upon either the way that the data is inserted (perhaps you have inadvertenly coded the quotes but the db being looked at isn't the actual database as copied from the App) or the way in which the data is being retrieved that for some reason adds them.
I don't believe it likely that the Cursor getString method has a bug in which the quotes are added, otherwise such an issue would likely be a recurring issue.
I'm trying to store Regular Expressions-like values in Sqllite Database (most of them are special characters like regex) but i'm getting this error
android.database.sqlite.SQLiteException: near "com":
syntax error (code 1): , while compiling:
insert into sample (indexId,tag) values (1,'dfvfdv/ ;''e;g=[;''''/.'';.')
I am trying to parse escape sequence using this:
public String escapeSequence(String s){
return DatabaseUtils.sqlEscapeString(s);
}
but it's not helping, is there something i'm doing wrong? or is there any way to do this properly?
even tried
public String escapeSequence(String s){
String a=s.replaceAll("'", "''");
String b=DatabaseUtils.sqlEscapeString(a);
return b;
}
I'm trying to create a messenger kind of app, where i have to store Messages where message can be anything... (most of the time i don't have any control over that)
I've checked Is there a database that can store regex as values? but doesn't really answer my question...
The only char you have to escape is ' into double ''
that is, I'm using this wrapper:
mystring.replaceAll("'", "''")
http://www.sqlite.org/lang_expr.html
A string constant is formed by enclosing the string in single quotes ('). A single quote within the string can be encoded by putting two single quotes in a row - as in Pascal. C-style escapes using the backslash character are not supported because they are not standard SQL.
I've tested your code here: http://sqliteonline.com/
this doesn't work:
CREATE TABLE regexp (name VARCHAR2(20), regexp VARCHAR2(50));
insert into regexp (name,regexp) values {'test','dfvfdv/ ;''e;g=[;''''/.'';.'}
select * from regexp
but this works:
CREATE TABLE regexp (name VARCHAR2(20), regexp VARCHAR2(50));
insert into regexp (name,regexp) values ('test','dfvfdv/ ;''e;g=[;''''/.'';.')
select * from regexp
Just replace this figured parenthesis {} to those ()
Constructing SQL strings from values obtained from untrusted sources (such as user input) opens your app for SQL injection problems, and the kind of syntax issues you are seeing now.
Syntax issues and SQL injection can be avoided by using ? variables and binding the values.
On Android SQLite, you can use variable binding by using ContentValues with SQLiteDatabase methods that accept it such as insert() or update(). For selection or raw SQL, supply variables as ? in the SQL expression and the values in the selectionArgs or bindArgs array param.
I have the following problem:
I try to query from the database the names that contain characters with diacritics.
The selection is:
String like = "ë";
String selection = "LOWER(name) LIKE \"%" + like + "%\"";
The problem is even if i have rows that contain "Ë" the query is empty. Any ideas?
And I do not want to build a separate column for normalized names.
From SQLite DOC :-
(A bug: SQLite only understands upper/lower case for ASCII characters by default. The LIKE operator is case sensitive by default for unicode characters that are beyond the ASCII range. For example, the expression 'a' LIKE 'A' is TRUE but 'æ' LIKE 'Æ' is FALSE.)
So, you should replace diacritics before using with like. Remove diacritics from string in Java is good SO to do that. Or to use lower and either cases separate.
try this
String selection = "LOWER(name) LIKE \"'%" + like + "%'\"";
I need to search a particular name from ma contacts... for that i gave the selection criteria like this
ContactsContract.Contacts.DISPLAY_NAME + " LIKE '"+constraint+"%'"
But for apostrophe(')... means ...when i gave apostrophe as constraint an (SQL error )exception is thrown.. for all other special characters , the search is working..
How can we handle constraint apostrophe(')... in search criteria.. boz we can have contact names having apostrophe in it (Eg: Jennifer'lo'pe_z)
How do I use a string literal that contains an embedded single-quote (') character?
The SQL standard specifies that single-quotes in strings are escaped by putting two single quotes in a row. SQL works like the Pascal programming language in the regard. SQLite follows this standard.
Example:
INSERT INTO xyz VALUES('5 O''clock');
SO, simply for your solution, use '' at the place of '. like
if(constraint.contains("'"))
constraint = constraint.replace("'", "''");
And then execute your query. This must help you.
Happy coding :)