Android - How to store html string in SQLite Database - android

I have an html string I would like to store in my SQLite db "as is". The special characters in the html string prevent my INSERT statement from storing it:
INSERT INTO myTable VALUES ('" + htmlString + "')
On iOS I used parameterized queries to accomplish this and it worked fine. How can I accomplish this on Android? I've Google parameterized queries for Android but the results were varied and unclear.

in Android you have parameterized queries too ... are few way to achive this:
ContentValues vals = new ContentValues();
vals.putString("ColumnName", htmlString);
db.insert("myTable", null, vals);
or
final SQLiteStatement insert = db.compileStatement("INSERT INTO myTable VALUES (?)");
insert.bindString(1, htmlString);
//edit: hehe forgot about most important thing
insert.executeInsert();
or
db.rawQuery("INSERT INTO myTable VALUES (?)", new String[] {htmlString});
EDIT: (inserting multiple rows)
if you wana insert more than 1 row then do it in transaction (it should be quicker)
and prefer 2nd solution:
db.beginTransaction();
try {
final SQLiteStatement insert = db.compileStatement("INSERT INTO myTable VALUES (?)");
for(...){
insert.clearBindings();
insert.bindString(1, htmlString[N]);
//edit: hehe forgot about most important thing
insert.executeInsert();
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}

Related

How to properly format queries while inserting Commas to Separate Strings in SQLITE

I need to insert coordinates in SQLLIte Table in Android
My Query is as below .
Its gives a Syntax error due to cordinates which contain string by comma separated information .
INSERT INTO "tableNonOilFarmer" ("farmerId","FirstName","MiddleName","LastName","FatherName","DOB","CategoryId","MobileNo","LandlineNo","StateId","DistrictId","TalukaMandalId","ClusterId","VillageId","Pincode","RsNumber","Area","LocationId","BorewellAvailable","BorewellDepth","SoilType","Flood","CurrentCropId","CurrentCropStatusId","CurrentCropAge","CurrentCropRating","Awareness","Interested","ContactDate","NextCrop","OverallRating","CreatedOn","Latitude","Longitude","Coordinates","Converted","Status","StatusBy","StatusDate","Comments","UserId","Sync") VALUES (3,test,test,test,test,2017-12-27,6,64,58,1,01,02,01,04,96559,1,1,1,false,353,kdf,1,1,1,5555,3,true,true,2017-12-27,,5,2017-12-27,16.868542,81.306554,81.30682,16.8682,0 81.306309,16.86842,0 81.306607,16.869098,0 81.307039,16.868813,0 81.30682,16.8682,0,false,0,null,1,null,167,S)
You can Use PreparedStatement for inserting the Data with commas
SQLiteDatabase db = dbHelper.getWritableDatabase();
SQLiteStatement stmt = db.compileStatement("INSERT INTO tableNonOilFarmer (FirstName,Adress) VALUES (?,?)");
stmt.bindString(1, "First");
stmt.bindString(2, "No 1, 1st street, MyCity");
stmt.execute();

How to bind values to SQLiteStatement for insert query?

Insertion code using SQLiteStatement usually looks like this,
String sql = "INSERT INTO table_name (column_1, column_2, column_3) VALUES (?, ?, ?)";
SQLiteStatement statement = db.compileStatement(sql);
int intValue = 57;
String stringValue1 = "hello";
String stringValue2 = "world";
// corresponding to each question mark in the query
statement.bindLong(1, intValue);
statement.bindString(2, stringValue1);
statement.bindString(3, stringValue2);
long rowId = statement.executeInsert();
Now this works perfectly fine but the issue I find here is that I have to be very careful about binding correct data to corresponding indexes. A simple swap of index will give me an error.
Also let's say in future my column_2 gets dropped from the table, then I would have to change all the indexes after the column_2 index otherwise the statement won't work. This seems trivial if I just have 3 columns. Imagine if a table has 10-12 (or even more) columns and column 2 gets dropped. I'll have to update the index of all the subsequent columns. This whole process seems inefficient and error prone.
Is there an elegant way to handle all this?
Edit : Why would I want to use SQLiteStatement ? Check this :Improve INSERT-per-second performance of SQLite?
Insertions can be done with ContentValues:
ContentValues cv = new ContentValues();
cv.put("column_1", 57);
cv.put("column_2", "hello");
cv.put("column_3", "world");
long rowId = db.insertOrThrow("table_name", null, cv);
But in the general case, the most correct way would be to use named parameters. However, these are not supported by the Android database API.
If you really want to use SQLiteStatement, write your own helper function that constructs it from a list of columns and takes care of matching it with the actual data. You also could write your own bindXxx() wrapper that maps previously-saved column names to parameter indexes.
You can use ContentValues with beginTransaction into SQLite that is quite easy as well as faster then prepared statements
For this you have to create ContentValues Array previously or create Content values object into your loop. and pass into insert method .this solution solve your both of problem in one.
mDatabase.beginTransaction();
try {
for (ContentValues cv : values) {
long rowID = mDatabase.insert(table, " ", cv);
if (rowID <= 0) {
throw new SQLException("Failed to insert row into ");
}
}
mDatabase.setTransactionSuccessful();
count = values.length;
} finally {
mDatabase.endTransaction();
}

Delete specific record in sqlite table based on two criteria: _id and column

I have created a sqlite table for my android app, this table has 5 columns and multiple rows, the columns being: _id, column1, column2, column3, column4.
I want to delete a specific record, for instance the record stored in column3 corresponding to _id (in a different class are the getters and setters, for this I've named the class "TableHandler")
I guess that I'm a bit confused, following is what I was planning, but for column3 I'm not sure what should be the argument, I just want to delete whatever is in that column position corresponding to _id
public void deleteValueColumn3(TableHandler value){
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_NAME, KEY_ID + " = ? AND " + KEY_COLUMN3 + " = ?",
new String[] {String.valueOf(value.getID()), ?????????);
db.close();
}
The ???????? is that I'm stuck there, maybe the whole method needs to be rewritten, I would appreciate your input.
Thanks
If you want to delete the whole record, just use the _id of the record in delete method, because that is the primary key for your table and therefore is unique. If you'd rather keep the record, you con always use the SQLiteDatabase.update method, specifying null as the new value that will replace column3 value; check out that column3 declaration has no NOT NULL tag, otherwise that could easily throw exception at you.
SQLite does not allow you to delete columns for a specific row.
You can only delete ROWS of data (delete the row that has the column _ID = 1).
Here's a quick tutorial on SQL.
How about updating that column with a null value, rather than using delete()?
ContentValues cv = new ContentValues();
cv.putNull(KEY_COLUMN3);
db.getWritableDatabase().update(
TABLE_NAME,
cv,
KEY_ID + "=?",
new String[]{String.valueOf(keyIdValue)});

insert string using sqlite in android containing single and double quotes in it

I am having trouble with inserting a string using sqlite in an android app,
I tried,
query = "INSERT OR REPLACE into table(_id, text) VALUES ("+data.get(i).id+", '"+data.get(i).text+"')";
MyClass.db.execSQL(query);
If my string looks like,
'I'm an android developer'
App crashes here, here is logcat result,
Caused by: android.database.sqlite.SQLiteException: near "m": syntax error: , while compiling: INSERT OR REPLACE into table (_id, text) VALUES (4, '"I'm an android developer"' )
I think it assumes that, my query ends here
'"I'
please help me to insert any case of string, either it contains single or double quotes like,
"I'm an "android" developer"
Without any hardcoding or anything you can directly insert with using ContentValues like below..
ContentValues values = new ContentValues();
long retvalue = 0;
values.put("_id", id_here);
values.put("text", your_text_here);
retvalue = MyClass.db.insertWithOnConflict(table, null, values, CONFLICT_REPLACE);
If you are using normal insert statement and if you have any value which contains single quote in it, then you might face a weird issue like this. So,try this..
String insert_info = "INSERT OR REPLACE INTO table(_id,text) VALUES (?,?)";
SQLiteStatement stmt = db.compileStatement(insert_info);
stmt.bindString(1, ""+data.get(i).id);
stmt.bindString(2, ""+data.get(i).text);
stmt.execute();
Multiple options:
Use ContentValues with SQLiteDatabase.insert()
Use variable binding, e.g.
db.execSQL("INSERT INTO table(_id, text) VALUES(?,?)", new String[] { idValue, textValue });
Escape the ' in strings. The SQL way to escape it is '' and you can use DatabaseUtils helpers to do the escaping.
To escape the " in Java strings, use \".
you must replace \' with \'\' in query string:
String getQuery(){
query = "INSERT OR REPLACE into table(_id, text) VALUES ("+data.get(i).id+", '"+getSqlValue(data.get(i).text)+"')";
MyClass.db.execSQL(query);
return query;
}
String getSqlValue(String input){
return input.replace("\'","\'\'");
}
You can use " for skipping " in a string

How do I use prepared statements in SQlite in Android?

How do I use prepared statements in SQlite in Android?
For prepared SQLite statements in Android there is SQLiteStatement. Prepared statements help you speed up performance (especially for statements that need to be executed multiple times) and also help avoid against injection attacks. See this article for a general discussion on prepared statements.
SQLiteStatement is meant to be used with SQL statements that do not return multiple values. (That means you wouldn't use them for most queries.) Below are some examples:
Create a table
String sql = "CREATE TABLE table_name (column_1 INTEGER PRIMARY KEY, column_2 TEXT)";
SQLiteStatement stmt = db.compileStatement(sql);
stmt.execute();
The execute() method does not return a value so it is appropriate to use with CREATE and DROP but not intended to be used with SELECT, INSERT, DELETE, and UPDATE because these return values. (But see this question.)
Insert values
String sql = "INSERT INTO table_name (column_1, column_2) VALUES (57, 'hello')";
SQLiteStatement statement = db.compileStatement(sql);
long rowId = statement.executeInsert();
Note that the executeInsert() method is used rather than execute(). Of course, you wouldn't want to always enter the same things in every row. For that you can use bindings.
String sql = "INSERT INTO table_name (column_1, column_2) VALUES (?, ?)";
SQLiteStatement statement = db.compileStatement(sql);
int intValue = 57;
String stringValue = "hello";
statement.bindLong(1, intValue); // 1-based: matches first '?' in sql string
statement.bindString(2, stringValue); // matches second '?' in sql string
long rowId = statement.executeInsert();
Usually you use prepared statements when you want to quickly repeat something (like an INSERT) many times. The prepared statement makes it so that the SQL statement doesn't have to be parsed and compiled every time. You can speed things up even more by using transactions. This allows all the changes to be applied at once. Here is an example:
String stringValue = "hello";
try {
db.beginTransaction();
String sql = "INSERT INTO table_name (column_1, column_2) VALUES (?, ?)";
SQLiteStatement statement = db.compileStatement(sql);
for (int i = 0; i < 1000; i++) {
statement.clearBindings();
statement.bindLong(1, i);
statement.bindString(2, stringValue + i);
statement.executeInsert();
}
db.setTransactionSuccessful(); // This commits the transaction if there were no exceptions
} catch (Exception e) {
Log.w("Exception:", e);
} finally {
db.endTransaction();
}
Check out these links for some more good info on transactions and speeding up database inserts.
Atomic Commit In SQLite (Great in depth explanation, go to Part 3)
Database transactions
Android SQLite bulk insert and update example
Android SQLite Transaction Example with INSERT Prepared Statement
Turbocharge your SQLite inserts on Android
https://stackoverflow.com/a/8163179/3681880
Update rows
This is a basic example. You can also apply the concepts from the section above.
String sql = "UPDATE table_name SET column_2=? WHERE column_1=?";
SQLiteStatement statement = db.compileStatement(sql);
int id = 7;
String stringValue = "hi there";
statement.bindString(1, stringValue);
statement.bindLong(2, id);
int numberOfRowsAffected = statement.executeUpdateDelete();
Delete rows
The executeUpdateDelete() method can also be used for DELETE statements and was introduced in API 11. See this Q&A.
Here is an example.
try {
db.beginTransaction();
String sql = "DELETE FROM " + table_name +
" WHERE " + column_1 + " = ?";
SQLiteStatement statement = db.compileStatement(sql);
for (Long id : words) {
statement.clearBindings();
statement.bindLong(1, id);
statement.executeUpdateDelete();
}
db.setTransactionSuccessful();
} catch (SQLException e) {
Log.w("Exception:", e);
} finally {
db.endTransaction();
}
Query
Normally when you run a query, you want to get a cursor back with lots of rows. That's not what SQLiteStatement is for, though. You don't run a query with it unless you only need a simple result, like the number of rows in the database, which you can do with simpleQueryForLong()
String sql = "SELECT COUNT(*) FROM table_name";
SQLiteStatement statement = db.compileStatement(sql);
long result = statement.simpleQueryForLong();
Usually you will run the query() method of SQLiteDatabase to get a cursor.
SQLiteDatabase db = dbHelper.getReadableDatabase();
String table = "table_name";
String[] columnsToReturn = { "column_1", "column_2" };
String selection = "column_1 =?";
String[] selectionArgs = { someValue }; // matched to "?" in selection
Cursor dbCursor = db.query(table, columnsToReturn, selection, selectionArgs, null, null, null);
See this answer for better details about queries.
I use prepared statements in Android all the time, it's quite simple:
SQLiteDatabase db = dbHelper.getWritableDatabase();
SQLiteStatement stmt = db.compileStatement("INSERT INTO Country (code) VALUES (?)");
stmt.bindString(1, "US");
stmt.executeInsert();
If you want a cursor on return, then you might consider something like this:
SQLiteDatabase db = dbHelper.getWritableDatabase();
public Cursor fetchByCountryCode(String strCountryCode)
{
/**
* SELECT * FROM Country
* WHERE code = US
*/
return cursor = db.query(true,
"Country", /**< Table name. */
null, /**< All the fields that you want the
cursor to contain; null means all.*/
"code=?", /**< WHERE statement without the WHERE clause. */
new String[] { strCountryCode }, /**< Selection arguments. */
null, null, null, null);
}
/** Fill a cursor with the results. */
Cursor c = fetchByCountryCode("US");
/** Retrieve data from the fields. */
String strCountryCode = c.getString(cursor.getColumnIndex("code"));
/** Assuming that you have a field/column with the name "country_name" */
String strCountryName = c.getString(cursor.getColumnIndex("country_name"));
See this snippet Genscripts in case you want a more complete one. Note that this is a parameterized SQL query, so in essence, it's a prepared statement.
jasonhudgins example won't work. You can't execute a query with stmt.execute() and get a value (or a Cursor) back.
You can only precompile statements that either returns no rows at all (such as an insert, or create table statement) or a single row and column, (and use simpleQueryForLong() or simpleQueryForString()).
To get a cursor, you can't use a compiledStatement. However, if you want to use a full prepared SQL statement, I recommend an adaptation of jbaez's method... Using db.rawQuery() instead of db.query().

Categories

Resources