I have a database full of tweets. When the user clicks refresh, I want to grab tweets newer than an ID (which I know how to do). After I grab the tweets, I want to insert them before ID 0, so tweet with ID 0 is no longer the first tweet, and instead replaced with the newer tweets.
I have searched and I have no idea how to do this.
Here is the code I am using to add the user's timeline on first launch:
public void addTimemline(Timeline timeline){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COL_TEXT, timeline.getText());
values.put(COL_TWEET_ID, timeline.getTweetId());
values.put(COL_SCREEN_NAME, timeline.getTwitterScreenName());
values.put(COL_REAL_NAME, timeline.getRealName());
values.put(COL_FAVORITE_COUNT, timeline.getFavoriteCount());
values.put(COL_RETWEET_COUNT, timeline.getRetweetedCount());
values.put(COL_HASHTAG_ENTITIES, timeline.getHashtagEntities());
values.put(COL_USER_MENTION_ENTITIES, timeline.getUserMentionEntities());
values.put(COL_URL_ENTITIES, timeline.getUrlEntities());
values.put(COL_MEDIA_ENTITIES, timeline.getMediaEntities());
db.insertOrThrow(TABLE_TWEETS, null, values);
db.close();
}
Create statement:
private static final String TABLE_TWEETS_CREATE = "create table "+TABLE_TWEETS+" ("
+ Tweets.COL_ROW_ID + " integer primary key autoincrement not null, "
+ Tweets.COL_TEXT + " text not null, "
+ Tweets.COL_TWEET_ID + " text,"
+ Tweets.COL_SCREEN_NAME + " text,"
+ Tweets.COL_REAL_NAME + " text,"
+ Tweets.COL_FAVORITE_COUNT + " text,"
+ Tweets.COL_RETWEET_COUNT + " text,"
+ Tweets.COL_HASHTAG_ENTITIES + " text,"
+ Tweets.COL_USER_MENTION_ENTITIES + " text,"
+ Tweets.COL_URL_ENTITIES + " text,"
+ Tweets.COL_MEDIA_ENTITIES + " text);";
As you have it set up, you cannot do that. You are telling the DB to autoincrement the key, so it will give you the next available slot that has not been used yet. Meaning if you have four records and delete the last one, you will still get the fifth slot the next time you insert a record. It will not allow you tot set the id yourself or insert a record before the last one inserted.
You could change to manually managing the IDs but that is much more work and prone to errors, and I would strenuously recommend you avoid doing so.
You should really investigate the ORDER BY keyword for SQLite. That will sort the cursor into the order you define in your query rather than relying on the id order of the records. If you put a time stamp of some kind in your data structure you could then sort in reverse order on that when you pull the cursor.
You can find full documentation of the SQLite ORDER BY keyword here.
You have not said if you are using raw SQL or any of the android SQLite functions, so you may also want to look at the android sqlite insert function here.
Related
So this is were the error occur on CON_SID + "AS 'SID' + RIGHT('000000' + CAST(ID AS VARCHAR(6)),6)PERSISTED);";
#Override
public void onCreate(SQLiteDatabase db) {
String query = "CREATE TABLE " + TBL_Name +
" ("+ CON_ID + "INT IDENTITY(1,1) NOT NULL PRIMARY KEY AUTOINCREMENT, "+
CON_Name + " TEXT, " +
CON_Address + " TEXT, " +
CON_BDay + " TEXT, " +
CON_Gender + " TEXT, " +
CON_Course + " TEXT, " +
CON_SID + "AS 'SID' + RIGHT('000000' + CAST(ID AS VARCHAR(6)),6)PERSISTED);";
db.execSQL(query);
}
You cannot use MYSQL's dialect of SQL. However, you could mimic the result by utilising a TRIGGER (not that you need to - explained below) for example :-
First create the table (names based upon your question) e.g. :-
CREATE TABLE IF NOT EXISTS example (
id INTEGER PRIMARY KEY,
name TEXT,
address TEXT,
bday TEXT,
gender TEXT,
course TEXT,
sid TEXT UNIQUE
);
note AUTOINCREMENT dropped, see link
Then add the TRIGGER using :-
CREATE TRIGGER IF NOT EXISTS example_after_insert AFTER INSERT ON example
BEGIN
UPDATE example SET sid = 'SID'||substr('000000',1,6-length(id))||id WHERE id = new.id;
END
;
The SID would then be generated whenever a row is inserted. For example :-
/* INSERT rows where id column is generated by SQLite */
INSERT INTO example (name,address,bday,gender,course) VALUES
('name1','addr1','bday1','female','course1'),
('name2','addr2','bday2','male','course2'),
('name3','addr3','bday3','female','course3')
;
/* INSERT rows with specific ID's to test values */
INSERT INTO example (id,name,address,bday,gender,course) VALUES
(15,'name1','addr1','bday1','female','course1'),
(135,'name2','addr2','bday2','male','course2'),
(1234,'name3','addr3','bday3','female','course3'),
(98765,'name3','addr3','bday3','female','course3'),
(999999,'name3','addr3','bday3','female','course3'),
(9999999,'name3','addr3','bday3','female','course3') /* overflow */
;
Using SELECT * FROM example; then shows :-
Not that you need to
You could achieve the same result without the trigger by simply generating the column when needed.
This approach would afford the following benefits
reduce the storage space required
reduce the processing required when inserting a row
no extra column
no trigger and update
no additional index conflict checking
conform better with normalisation (not duplicating data)
For example to get the same result without accessing the sid column (i.e. showing that it's not needed) you could use (the generated column has been named schoolID ):-
SELECT
id,
name,
address,
bday,
gender,
course,
'SID'||substr('000000',1,6-length(id))||id AS schoolID
FROM example;
The result :-
INSERT OR REPLACE works when there is only one row in the table and it happens to be the one that is replaced. However, when there are multiple rows in the table, INSERT OR REPLACE just inserts and creates a duplicate!
For example, if I create an entry with eventId = '123'. And then try to write another entry with eventId = '123' and roomnumber equal to something different than the first entry, INSERT OR REPLACE will work. However, if there are more than one rows in the table it will create a duplicate. Here is my code:
String createSql = "CREATE TABLE IF NOT EXISTS events (\n"
+ " eventId VARCHAR(20) PRIMARY KEY ON CONFLICT REPLACE,\n"
+ " roomNumber VARCHAR(20) NOT NULL,\n"
+ " startTime TIMESTAMP NOT NULL,\n"
+ " endTime TIMESTAMP NOT NULL,\n"
+ " name VARCHAR(250),\n"
+ " isVIP BOOLEAN NOT NULL,\n"
+ " capacity INTEGER(20) NOT NULL, \n"
+ " UNIQUE (eventId) \n"
+ ");";
String sql = "INSERT OR REPLACE INTO events (eventId, roomNumber, startTime, endTime, capacity, name, isVIP)" + " Values('"+event.getID()+"', '"+event.getRoomNumber()+"', '"+event.getStartTime()+"', '"+event.getEndTime()+"', '"+event.getCapacity()+"', '"+event.getName()+"', '"+event.getVIPStatus()+"')";
I would read this thread for more information about how REPLACE works.
https://stackoverflow.com/questions/29539838/replace-versus-insert-in-sql#:~:text=According%20to%20the%20documentation%2C%20the,the%20new%20row%20is%20inserted.
Also I would suggest trying just "REPLACE," as it functions as INSERT but will replace on conflicts.
I have an xml file as shown in the picture. I want two things, first, I want to insert pre-defined values in my sqlite database on onCreate method using an arraylist (or any method). Then secondly, I want to use those values from the arraylist, now in my database, to populate the two spinners(Producer and Product).
I have a database file that handles the db connections and methods and this is what I have done so far. This code is inside my onCreate method
db.execSQL("CREATE TABLE " + TABLE_PRODUCT + "("
+ PRODUCT_ID + " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," + PRODUCT_NAME + " TEXT,"
+ PRODUCER_FK + " INTEGER" + " FOREIGN KEY(PRODUCER_FK) REFERENCES TABLE_PRODUCER(PRODUCER_ID))");
ContentValues contentv=new ContentValues();
contentv.put("name", "Soya Seed");
getWritableDatabase().insert("TABLE_PRODUCT", null, contentv);
db.execSQL("CREATE TABLE " + TABLE_PRODUCER + "("
+ PRODUCER_ID + " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," + PRODUCER_NAME + " TEXT,"
+ PRODUCER_ADDRESS + " TEXT,"
+ PRODUCER_PHONE + " TEXT UNIQUE," + PRODUCER_EMAIL + " TEXT,"
+ CONTACT_PERSON + " TEXT" + ")");
ContentValues cv=new ContentValues();
cv.put("name", "ZamSEED");
cv.put("address", "Luanda");
cv.put("phone", "+244977654321");
cv.put("email", "demo#zamseed.com");
cv.put("contact_name", "Mr. Tembo");
getWritableDatabase().insert("TABLE_PRODUCER", null, cv);
Then I have an inventory file that reads from the database to get values from the product and producers tables to populate the spinners.
My challenge is how can I tell if my db.execSQL is actually successful?
And how would I use an arraylist to insert values in the database?
NOTE: the app runs fine when I ran it but I am not sure if the tables are created and values inserted. Am a newbie to Android programming, thanks.
After some time of research into this, I found this article here that led me to see the actual tables of my db.execSQL command and the data contained. In Ubuntu:
cd /path/to/my/sdk/platform-tools
./adb shell
run-as <app package name>
cd /data/data/<app package name>/databases
ls
chmod 666 <database file name>
sqlite3 <database file name>
> (semi-colon terminated commands can be run here to query the data)
> .exit
(copy full database path)
exit
Then use sqlite3 commands to work on database > (semi-colon terminated commands can be run here to query the data)
DatabaseHelper.java
public ArrayList<String>getProductList(){
ArrayList<String>products = new ArrayList<String>();
SQLiteDatabase qDB = getReadableDatabase();
String columns[]=new String[]{PRODUCT_NAME};
Cursor cursor = qDB.query(TABLE_PRODUCT,columns,null,null,null,null,null);
while (cursor.moveToNext()){
String produectName = cursor.getString(1);
products.add(productName);
Log.e("e",products);
}
return products;
}
SomeActivity.java
spinnerProducts = (Spinner) findViewById(R.id.spinnerProducts);
ArrayList<String>productsList = new DatabaseHelper(context).getProductsList();
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(context,android.R.layout.simple_list_item_1,productsList);
spinnerProducts.setAdapter(arrayAdapter);
...
//same logic for Producers list
My challenge is how can I tell if my db.execSQL is actually successful?
It was successful if it did not throw an exception.
However calling getWritableDatabase() in onCreate() is an error since that results in recursion: getWritableDatabase() triggers a call to onCreate() in the first place. You should use the SQLiteDatabase passed to you as a param instead.
If you did not see an exception about the recursive call then you already had a database file with the correct version. You can uninstall your app to clean up its data and then install and run it again to make onCreate() run again.
And how would I use an arraylist to insert values in the database?
Use a loop to iterate the list and insert values one by one.
I have two tables; a 'parent' and a 'child' table. (not SQLite defitinions, just something i call them)
Everytime a child-object is created, it is assigned the value 0 in one of its columns.
When a new parent-object is created, every unassigned child-object, has to update the value mentioned before, to the parent-object's ID. My code looks like this:
public long createWorkout(String workoutName){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NAME, workoutName);
//Creates a new parent-object (a workout - the childs are exercises)
//the generated ID is returned as a long (workout_pk_id)
long workout_pk_id = db.insert(TABLE_WORKOUT, null, values);
//Selects all objects in the child-table with KEY_WORKOUT_ID = 0 (the column mentioned before)
String selectQuery = "SELECT * FROM " + TABLE_EXERCISE + " WHERE " + KEY_WORKOUT_ID + " == " + 0;
Cursor cursor = db.rawQuery(selectQuery, null);
//Takes each found object with value 0, and updates the value to the returned parent-ID from before.
if (cursor.moveToFirst()) {
do {
String k = "UPDATE " + TABLE_EXERCISE + " SET " + KEY_WORKOUT_ID + " == " + workout_pk_id;
db.execSQL(k);
} while (cursor.moveToNext());
}
return workout_pk_id;
}
But for some reason this doesn't work. The ID the childs/exercises remains 0. Can you help me?
I don't know if the error is somewhere in the setup of my tables, in that case i could provide some more information.
Thanks in advance. /Jeppe
EDIT: This is used in android, and I have debugged and verified that the workout_pk_id is returned, 45 objects are found in the selectQuery and yet it doesn't work. I also tried ContentValues to update the values, didn't work.
Edited the " == " to " = ", but the value is still not updated.
This is from eclipse - I've created a workout called "test", with the ID 160.
The exercise "test1" has the ID 430 (unique) but the workout_id is still 0.
It's been awhile since I did any Android stuff but I believe the "==" operator is incorrect:
String k = "UPDATE " + TABLE_EXERCISE + " SET " + KEY_WORKOUT_ID + " == " + workout_pk_id;
The operator you're using is a comparative operator, "=" is the assignment operator.
I also believe there is a better way to do what you are trying to do, currently refreshing my memory on Android so I'll get back to you. In the meantime tell me if replacing the operator works
Yeah so another way you can do this is by using subqueries. So it would look something like:
UPDATE TABLE_EXCERCISE SET KEY_WORKOUT_ID = WORKOUT_PK_ID WHERE KEY_WORKOUT_ID =
(
*subquery here to select parent object ids*
)
Here's a link to help:
http://www.tutorialspoint.com/sqlite/sqlite_sub_queries.htm
Let me know how this works for you.
I think you have to look to your update query.
It has to be:
String k = "UPDATE " + TABLE_EXERCISE + " SET " + KEY_WORKOUT_ID + " = " + workout_pk_id;
Look at the "=" between KEY_WORKOUT_ID and workout_pk_id.
i need a tip here , here i have a code to insert into sqlite database:
Thread t = new Thread(new Runnable() {
#Override
public void run() {
String sqlCreate = "CREATE TABLE IF NOT EXISTS " + name
+ " (ID INTEGER PRIMARY KEY AUTOINCREMENT,"
+ " Type TEXT,"
+ " Text TEXT,"
+ " OtherFormats TEXT,"
+ " Date TEXT,"
+ " Image TEXT,"
+ " RealName TEXT)";
db.execSQL(sqlCreate);
//(String Type, String Text ,String name,String OtherFormats,String Itime,String
RealName)
String sqlInsert= "INSERT INTO " + "'"+name+"'" +
" VALUES
("+"'"+ID+"'"+","+"'"+Type+"'"+","+"'"+Text+"'"+","+
"'"+OtherFormats+"'"+","+"'"+Date+"'"+"
,"+"'"+Image+"'"+","+"'"+RealName+"')";
db.execSQL(sqlInsert);
}
});
t.start();
the question is as you u see my ID is auto increment, but for executing it well, i need to put a value there,what value should i put so it database does the increament itself?
thanks
05-26 03:56:33.018: E/AndroidRuntime(23809):
android.database.sqlite.SQLiteException: near "VALUES": syntax error (code 1): ,
while compiling: INSERT INTO 'new' (Type,Text,OtherFormats ,Date,Image,RealName VALUES('m','hey','n','03:56','j','s')
You can do this. Enter the name of columns you need to insert
String sqlInsert= "INSERT INTO " + "'"+name+"' (Type,Text,OtherFormats ,Date,Image,RealName )VALUES
("+"'"+ID+"'"+","+"'"+Type+"'"+","+"'"+Text+"'"+","+
"'"+OtherFormats+"'"+","+"'"+Date+"'"+"
,"+"'"+Image+"'"+","+"'"+RealName+"')";
db.execSQL(sqlInsert);
the question is as you u see my ID is auto increment, but for executing it well, i need to put a value there,what value should i put so it database does the increament itself?
Put in a NULL or just leave it unspecified.
From the documentation:
If no ROWID is specified on the insert, or if the specified ROWID has a value of NULL, then an appropriate ROWID is created automatically.