sql lite, android - copy record into the same table - android

I am trying to copy a record from a sql lite database within a android application and then insert that same record into the same table but with two different ids in the first two columns. any ideas?
SQLiteDatabase db = dbs.getReadableDatabase();
String SQL = "SELECT * FROM table_1 a " +
"join table_2 b on a.ID = b.ID " +
"where table1_Id = '"+Id+"' And" +
"table_2_ID = 'one'";
Cursor cursor2 = db.rawQuery(SQL, null);
startManagingCursor(cursor2);
int m = cursor2.getColumnCount();
try{
while (cursor2.moveToNext()) {
for(int i=0; i<m; i++){
String id1 = cursor2.getString(i);
}
}
}
catch(Exception e){}

try {
while (cursor2.moveToNext()) {
dbs.ad(Id, Id, cursor2.getString(3), "",
cursor2.getString(5), cursor2.getString(6), cursor2.getString(7),
"", "");
}
}

Related

Cursor Exception during Async Task

I am running a background task that goes out and downloads a JSON file, pareses it, then adds it to the contents to a SQLite database.
I am getting a couple of errors when it runs.
Caused by: android.database.CursorWindowAllocationException: Cursor
window allocation of 2048 kb failed. # Open Cursors=728 (# cursors
opened by this proc=728)
E/CursorWindow: Could not allocate CursorWindow
'/data/data/com.mycompany.inventory/databases/dbInventory.sql' of size
2097152 due to error -12.
The JSON has about 1500 items in it.
Here is the method my async task calls:
public void addModelsToDB(JSONObject dict){
String insertQuery = "";
String deleteQuery = "DROP TABLE IF EXISTS 'tblModels'";
String createQuery = "CREATE TABLE 'tblModels' ('modelsID' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,'makeKey' INTEGER, 'modelName' TEXT, 'modelKey' INTEGER)";
Cursor cursor = dbLocals.executeRawQuery(deleteQuery, null);
cursor.moveToFirst();
cursor = dbLocals.executeRawQuery(createQuery, null);
cursor.moveToFirst();
try {
JSONArray dicRecordSet = dict.getJSONArray("Recordset");
JSONObject dicRecords = dicRecordSet.getJSONObject(0);
JSONArray arrRecords = dicRecords.getJSONArray("Record");
for (int i = 0; i < arrRecords.length(); i++) {
JSONObject record = arrRecords.getJSONObject(i);
insertQuery = "INSERT INTO 'tblModels' VALUES(" + null + ", "
+ record.getString("MODMAKlMakeKey") + ", '"
+ record.getString("MODvc50Name").replaceAll("'", "''") + "', "
+ record.getString("MODlModelKey")
+")";
cursor = dbLocals.executeRawQuery(insertQuery, null);
cursor.moveToFirst();
}
} catch (JSONException e) {
e.printStackTrace();
}
cursor.close();
}
My database a manager returns a cursor.
public Cursor executeRawQuery(String query, String[] selectionArgs) {
Cursor cursor = databaseConn.rawQuery(query, selectionArgs);
return cursor;
}
What am I doing wrong?
You can't reuse the cursor variable because it shadows the original one, and therefore you can't close it:
Cursor cursor = dbLocals.executeRawQuery(deleteQuery, null);
then
cursor = dbLocals.executeRawQuery(insertQuery, null);
this second assignment means you can't close the original cursor.
Also, why are you creating the table here?
Edit:
Use it like this:
public void addModelsToDB(JSONObject dict){
String insertQuery = "";
String deleteQuery = "DROP TABLE IF EXISTS 'tblModels'";
String createQuery = "CREATE TABLE 'tblModels' ('modelsID' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,'makeKey' INTEGER, 'modelName' TEXT, 'modelKey' INTEGER)";
Cursor cursor = dbLocals.executeRawQuery(deleteQuery, null);
try {
cursor.moveToFirst();
cursor = dbLocals.executeRawQuery(createQuery, null);
cursor.moveToFirst();
} finally {
cursor.close();
}
try {
JSONArray dicRecordSet = dict.getJSONArray("Recordset");
JSONObject dicRecords = dicRecordSet.getJSONObject(0);
JSONArray arrRecords = dicRecords.getJSONArray("Record");
for (int i = 0; i < arrRecords.length(); i++) {
JSONObject record = arrRecords.getJSONObject(i);
insertQuery = "INSERT INTO 'tblModels' VALUES(" + null + ", "
+ record.getString("MODMAKlMakeKey") + ", '"
+ record.getString("MODvc50Name").replaceAll("'", "''") + "', "
+ record.getString("MODlModelKey")
+")";
cursor = dbLocals.executeRawQuery(insertQuery, null);
try {
cursor.moveToFirst();
} finally {
cursor.close();
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
You should close cursors after using them. Inside the loop, you are creating a cursor every iteration, without ever closing it. Apparently there is a limit for the number of open cursors and you hit that limit.

Android copy values from table and insert in another

I'm trying to copy all the data in a database table, which correspond to the WHERE clause, and insert them into another table. I'm trying this code, but in the table prev there are only 2 records in the table Ver are inserted more than 100 records .... why?
private void Tras() {
String numero_ricevuto = (i.getStringExtra("numero"));
SQLiteDatabase db = mHelper.getWritableDatabase();
String sql = "SELECT data, unita_di_misura FROM prev WHERE numero ='"+numero_ricevuto+"'";
Cursor c = db.rawQuery(sql, null);
int count = c.getCount();
String[] data = new String[count];
String[] unita_di_misura = new String[count];
for(int i=0; i<count; i++) {
c.moveToNext();
data[i] = c.getString(0);
unita_di_misura[i] = c.getString(1);
}
for(int i=0 ;i < data.length;i++){
ContentValues cv = new ContentValues();
cv.put(VerTable.SI_NO, "0");
cv.put(VerTable .DATA, data[i]);
cv.put(VerTable .U_M, e.unita_di_misura[i]);
db.insert(VerTable .TABLE_NAME, null, cv);
}
c.close();
db.close();
}
Try this 3 line solution hope this will help you
private void Tras() {
String numero_ricevuto = (i.getStringExtra("numero"));
SQLiteDatabase db = mHelper.getWritableDatabase();
String sql = "INSERT INTO "+VerTable .TABLE_NAME+" SELECT 0,data, unita_di_misura FROM prev WHERE numero = '"+numero_ricevuto+"'";
db.execSQL(sql);
db.close();
}
but in the table prev there are only 2 records in the table Ver are inserted more than 100 records .... why?
Possibly you ran the code more than once.
Also, pulling data from db only to insert it back is not very efficient. It's better to let the database engine do the work for you, e.g.
db.execSQL("INSERT INTO " + VerTable.TABLE_NAME +
"(" + VerTable.SI_NO + "," VerTable.DATA + "," + VerTable.U_M + ") " +
"SELECT 0, data, unita_di_misura FROM prev WHERE numero=?",
new String[] { numero_ricevuto });
Using ? params also avoids the possiblity of string SQL injection.

Android: Get entire column data

Im trying to get the data of an entire column into a string array. My database contains two columns Id and Names. I want to read all the entries of the names column and put it into a array. Please help.
EDIT #1:
Im using the following code but i can get only one name with this code.
String query = "Select * FROM " + TABLE_APPS + " WHERE " + COLUMN_NAME + " = \"" + productname + "\"";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
if (cursor.moveToFirst()) {
cursor.moveToFirst();
name = cursor.getString(1);
cursor.close();
} else {
name = null;
}
db.close();
int total=0;
Cursor csr=sdb.query("tablename", null, null,null,null,null,null);
csr.moveToFirst();
while(!csr.isAfterLast())
{
total++;
csr.moveToNext();
}
String strarray[] = new String[total];
Cursor csrs=sdb.query("tablename", null, null,null,null,null,null);
csrs.moveToFirst();
int aray=0;
while(!csrs.isAfterLast())
{
strarray[aray]=csrs.getString(1);
aray++;
csrs.moveToNext();
}

Get all column value in Sqllite in android

I have saved product name in one column in Sqllite database .Lot of product name are already saved there now, I need to get all product name sent it to web service.For example egg, briyani, idly.
I have used it this code in Sqllite but String is not append.I have mention below this code:
public String fetchMyRowid(String column_name)
{
String query = "select "+column_name+" From " + TABLErestaurant;
mCursor =db.rawQuery(query, null);
StringBuffer buf = new StringBuffer();
if (mCursor.moveToFirst()) {
buf.append(mCursor.getString(0)+",");
}
return buf.toString();
}
if (mCursor.moveToFirst()) {
buf.append(mCursor.getString(0)+",");
}
The problem is you're not iterating through your results. Do this instead:
while(mCursor.moveToNext()) {
buf.append(mCursor.getString(mCursor.getColumnIndex(column_name))+",");
}
your code is fine but you forgate: db.getWritableDatabase(); or getreadableDatabase()
i have modify your code here DBController is my class public class DBController extends SQLiteOpenHelper
so your code ll be..
public String fetchMyRowid(String column_name, DBController db) {
String query = "SELECT " + column_name + " FROM " + TABLErestaurant;
SQLiteDatabase dd = db.getWritableDatabase();
cursor = dd.rawQuery(query, null);
StringBuffer buf = new StringBuffer();
if(cursor.getCount() > 0 || cursor != null){
do {
Log.e("name--->", "" + cursor.getString(0));
buf.append(cursor.getString(0) + ",");
} while (cursor.moveToNext());
Log.e("name---> buffeer-->", "" + buf);
}
return buf.toString();
}
Just make a small change here,
instead of this line ,
String query = "select "+column_name+" From " + TABLErestaurant;
try this line
String query = "select * From " + TABLErestaurant;

IN clause and placeholders

I'm attempting to do the following SQL query within Android:
String names = "'name1', 'name2"; // in the code this is dynamically generated
String query = "SELECT * FROM table WHERE name IN (?)";
Cursor cursor = mDb.rawQuery(query, new String[]{names});
However, Android does not replace the question mark with the correct values. I could do the following, however, this does not protect against SQL injection:
String query = "SELECT * FROM table WHERE name IN (" + names + ")";
Cursor cursor = mDb.rawQuery(query, null);
How can I get around this issue and be able to use the IN clause?
A string of the form "?, ?, ..., ?" can be a dynamically created string and safely put into the original SQL query (because it is a restricted form that does not contain external data) and then the placeholders can be used as normal.
Consider a function String makePlaceholders(int len) which returns len question-marks separated with commas, then:
String[] names = { "name1", "name2" }; // do whatever is needed first
String query = "SELECT * FROM table"
+ " WHERE name IN (" + makePlaceholders(names.length) + ")";
Cursor cursor = mDb.rawQuery(query, names);
Just make sure to pass exactly as many values as places. The default maximum limit of host parameters in SQLite is 999 - at least in a normal build, not sure about Android :)
Here is one implementation:
String makePlaceholders(int len) {
if (len < 1) {
// It will lead to an invalid query anyway ..
throw new RuntimeException("No placeholders");
} else {
StringBuilder sb = new StringBuilder(len * 2 - 1);
sb.append("?");
for (int i = 1; i < len; i++) {
sb.append(",?");
}
return sb.toString();
}
}
Short example, based on answer of user166390:
public Cursor selectRowsByCodes(String[] codes) {
try {
SQLiteDatabase db = getReadableDatabase();
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
String[] sqlSelect = {COLUMN_NAME_ID, COLUMN_NAME_CODE, COLUMN_NAME_NAME, COLUMN_NAME_PURPOSE, COLUMN_NAME_STATUS};
String sqlTables = "Enumbers";
qb.setTables(sqlTables);
Cursor c = qb.query(db, sqlSelect, COLUMN_NAME_CODE+" IN (" +
TextUtils.join(",", Collections.nCopies(codes.length, "?")) +
")", codes,
null, null, null);
c.moveToFirst();
return c;
} catch (Exception e) {
Log.e(this.getClass().getCanonicalName(), e.getMessage() + e.getStackTrace().toString());
}
return null;
}
Sadly there's no way of doing that (obviously 'name1', 'name2' is not a single value and can therefore not be used in a prepared statement).
So you will have to lower your sights (e.g. by creating very specific, not reusable queries like WHERE name IN (?, ?, ?)) or not using stored procedures and try to prevent SQL injections with some other techniques...
As suggest in accepted answer but without using custom function to generate comma-separated '?'. Please check code below.
String[] names = { "name1", "name2" }; // do whatever is needed first
String query = "SELECT * FROM table"
+ " WHERE name IN (" + TextUtils.join(",", Collections.nCopies(names.length, "?")) + ")";
Cursor cursor = mDb.rawQuery(query, names);
You can use TextUtils.join(",", parameters) to take advantage of sqlite binding parameters, where parameters is a list with "?" placeholders and the result string is something like "?,?,..,?".
Here is a little example:
Set<Integer> positionsSet = membersListCursorAdapter.getCurrentCheckedPosition();
List<String> ids = new ArrayList<>();
List<String> parameters = new ArrayList<>();
for (Integer position : positionsSet) {
ids.add(String.valueOf(membersListCursorAdapter.getItemId(position)));
parameters.add("?");
}
getActivity().getContentResolver().delete(
SharedUserTable.CONTENT_URI,
SharedUserTable._ID + " in (" + TextUtils.join(",", parameters) + ")",
ids.toArray(new String[ids.size()])
);
Actually you could use android's native way of querying instead of rawQuery:
public int updateContactsByServerIds(ArrayList<Integer> serverIds, final long groupId) {
final int serverIdsCount = serverIds.size()-1; // 0 for one and only id, -1 if empty list
final StringBuilder ids = new StringBuilder("");
if (serverIdsCount>0) // ambiguous "if" but -1 leads to endless cycle
for (int i = 0; i < serverIdsCount; i++)
ids.append(String.valueOf(serverIds.get(i))).append(",");
// add last (or one and only) id without comma
ids.append(String.valueOf(serverIds.get(serverIdsCount))); //-1 throws exception
// remove last comma
Log.i(this,"whereIdsList: "+ids);
final String whereClause = Tables.Contacts.USER_ID + " IN ("+ids+")";
final ContentValues args = new ContentValues();
args.put(Tables.Contacts.GROUP_ID, groupId);
int numberOfRowsAffected = 0;
SQLiteDatabase db = dbAdapter.getWritableDatabase());
try {
numberOfRowsAffected = db.update(Tables.Contacts.TABLE_NAME, args, whereClause, null);
} catch (Exception e) {
e.printStackTrace();
}
dbAdapter.closeWritableDB();
Log.d(TAG, "updateContactsByServerIds() numberOfRowsAffected: " + numberOfRowsAffected);
return numberOfRowsAffected;
}
This is not Valid
String subQuery = "SELECT _id FROM tnl_partofspeech where part_of_speech = 'noun'";
Cursor cursor = SQLDataBase.rawQuery(
"SELECT * FROM table_main where part_of_speech_id IN (" +
"?" +
")",
new String[]{subQuery}););
This is Valid
String subQuery = "SELECT _id FROM tbl_partofspeech where part_of_speech = 'noun'";
Cursor cursor = SQLDataBase.rawQuery(
"SELECT * FROM table_main where part_of_speech_id IN (" +
subQuery +
")",
null);
Using ContentResolver
String subQuery = "SELECT _id FROM tbl_partofspeech where part_of_speech = 'noun' ";
final String[] selectionArgs = new String[]{"1","2"};
final String selection = "_id IN ( ?,? )) AND part_of_speech_id IN (( " + subQuery + ") ";
SQLiteDatabase SQLDataBase = DataBaseManage.getReadableDatabase(this);
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables("tableName");
Cursor cursor = queryBuilder.query(SQLDataBase, null, selection, selectionArgs, null,
null, null);
In Kotlin you can use joinToString
val query = "SELECT * FROM table WHERE name IN (${names.joinToString(separator = ",") { "?" }})"
val cursor = mDb.rawQuery(query, names.toTypedArray())
I use the Stream API for this:
final String[] args = Stream.of("some","data","for","args").toArray(String[]::new);
final String placeholders = Stream.generate(() -> "?").limit(args.length).collect(Collectors.joining(","));
final String selection = String.format("SELECT * FROM table WHERE name IN(%s)", placeholders);
db.rawQuery(selection, args);

Categories

Resources