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.
Related
I am trying to populate one table in my database with pretty complex data. For this, I am using a generator API (which gives me random data).
public void populateCrackers(){
PreparedStatement psm;
String queryJoke = "(SELECT jid FROM Jokes WHERE jid=?)";
String queryHat = "(SELECT hid FROM Hats WHERE hid=?)";
String queryGift = "(SELECT gid FROM Gifts WHERE gid=?)";
String query = "INSERT INTO Crackers(cid, name, jid, hid, gid, quantity) VALUES(" +
"?, " +
"?, " +
queryJoke + ", " +
queryHat + ", " +
queryGift + ", " +
"?)";
System.out.println(query);
String cracker_String = utils.JSONUtils.getJSON(crackerAPI, client);
JSONObject crackerJSON = new JSONObject(cracker_String);
JSONArray crackers = crackerJSON.getJSONArray("results");
for(int j=0; j<crackers.length(); j++){
try{
psm = connection.prepareStatement(query);
psm.setInt(1,crackers.getJSONObject(j).getInt("cid"));
psm.setString(2, crackers.getJSONObject(j).getString("cname"));
psm.setInt(3, crackers.getJSONObject(j).getInt("rjoke"));
psm.setInt(4, crackers.getJSONObject(j).getInt("rhat"));
psm.setInt(5, crackers.getJSONObject(j).getInt("rgift"));
psm.setInt(6, crackers.getJSONObject(j).getInt("cquantity"));
psm.execute();
System.out.println(crackers.getJSONObject(j).get("cid") + " "
+ crackers.getJSONObject(j).get("cname") + " "
+ crackers.getJSONObject(j).get("cquantity") + " "
+ crackers.getJSONObject(j).get("rjoke") + " "
+ crackers.getJSONObject(j).get("rhat") + " "
+ crackers.getJSONObject(j).get("rgift"));
}catch (Exception e){
e.printStackTrace();
}
}
}
This is the method that populates my "Crackers" tab. I am wondering if this be accepted as a prepared statement. When I run it in psql interactive command line tool, exactly that statement with some chosen ids (e.g INSERT INTO Crackers (cid, name, hid, jid, gid, quantity) VALUES('cid', 'name', (SELECT hid FROM Hats WHERE hid=11), (SELECT jid FROM Jokes where jid=99), (SELECT gid FROM Gifts WHERE gid=13), 5) it works flawlessly.
Does my preparedstatement break the Constraint?
Any ideas?
LATER EDIT: The inconsistency is the form of that null values can reach my Crackers table (e.g. Cracker(1, "hello", null, null, 3, 123) appears in the table.
There is nothing about Prepared statement. Constraint can be broken by parameters you set to it. And you can run your PLSQL statement as anonimous block in PreparedStatement as well.
Just surround it with BEGIN ... END. only one thing is different - for JDBC parameters are ? mark not :parameter as for PLSQL and there is no way to use named parameter.
That means if you need to use parameter more than once for JDBC you have to have that many ? marks and set all of them.
So, focus on parameters you pass to and their sequence.
The code is correct, though the prepared statement must be closed, and it would be better to create the statement once, before the for loop.
Now there is crackers.length() times a statement created but not closed. That might give problems.
Use the try-with-resouce syntax for automatic closing, irrespective of any exception or return.
try (PreparedStatement psm = connection.prepareStatement(query)) {
for (int j = 0; j < crackers.length(); j++) {
...
psm.executeUpdate();
And call executeUpdate instead of the more general execute. The resulting update count might be of interest (1/0).
I realised I had the wrong constraints on my table. I was letting null values in. There was nothing wrong with the prepared statement.
The right query to create the table is this one:
String createCrackersQuery = "CREATE TABLE Crackers(" +
" cid INTEGER," +
" name VARCHAR NOT NULL," +
" jid INTEGER NOT NULL," +
" hid INTEGER NOT NULL," +
" gid INTEGER NOT NULL," +
" quantity INTEGER NOT NULL," +
" CONSTRAINT Cracker_Primary PRIMARY KEY (cid)," +
" CONSTRAINT Cracker_Name_Unique UNIQUE(name)," +
" CONSTRAINT Joke_Foreign FOREIGN KEY (jid) REFERENCES Jokes(jid)," +
" CONSTRAINT Hat_Foreign FOREIGN KEY (hid) REFERENCES Hats(hid), " +
" CONSTRAINT Gift_Foreign FOREIGN KEY (gid) REFERENCES Gifts(gid)" +
")";
I want to change a single column inside a row. I'm trying to update the value inside "remindOnDate" field to "reminder" in the "tasks" table.
I tried a few things but they all work only when remindOnDate is null. Once it has a value stored in it, update won't work on it. I don't know why. What am I doing wrong? If the statement is wrong then it shouldn't work even when remindOnDate is null.
I tried this:
ContentValues editTask = new ContentValues();
editTask.put("remindOnDate", reminder);
database.update("tasks", editTask, "_id = ?", new String[]{id+""});
I also tried the following instead of the last line:
database.update("tasks", editTask, "_id = " + id, null);
Here is another thing I tried:
String createQuery = "UPDATE tasks SET remindOnDate = '" + reminder + "' WHERE _id = " + id + ";";
database.execSQL(createQuery);
I'm having an issue with a SQL query in Android - it doesn't seem to be returning the correct result, which I think might be due to my query structure possibly.
This is a running app. I have an initial query that works correctly, that gets me the most common out of the last three runs, which is:
Cursor workout = db.rawQuery("SELECT ActivityID, DistanceID FROM Workout WHERE _id IN(Select _id FROM Workout ORDER BY _id DESC LIMIT 3) Group By ActivityID, DistanceID HAVING COUNT(*) > 1", null);
So now I have the most common distance + activity (running/biking ect..) out of the last three runs, so I wanted to run a query that got me the activity + distance combination on the last three with the fasted time, so I have this:
Cursor fastestWorkout = db.rawQuery
("Select _id, RunTimeSeconds, Distance FROM Workout WHERE ActivityID = " + workout.getInt(0) +
" AND DistanceID = " + workout.getInt(1) +
" AND RunTimeSeconds IN " +
"(Select Min(RunTimeSeconds) From Workout WHERE ActivityID = " + workout.getInt(0) +
" AND DistanceID = " + workout.getInt(1) +
" ORDER BY _id DESC LIMIT 3)" +
" ORDER BY _id DESC LIMIT 3", null);
So the only thing special here is the sub-query that gets me the fastest time, which I imagine might be at fault, however I can't work out why. The cursor has three results in it at the end of this, when it should be one (There are two activities+distances that are the same and one unique - with different RunTimeSeconds, so it should be pulling back that one that is the fastest.
Any help would be appreciated!
If I understand correctly you want the row with the fastest run time. Instead of using a subquery to find this value, why not just order by this run time and pick the first result :
Cursor fastestWorkout = db.rawQuery
("Select _id, RunTimeSeconds, Distance FROM Workout WHERE ActivityID = " + workout.getInt(0) +
" AND DistanceID = " + workout.getInt(1) +
" ORDER BY RunTimeSeconds LIMIT 1", null);
Thanks for the help! I managed to figure this one out in the end! Bwt's suggestion with the ordering by run-time is what got me there!
I just used a sub-query to select from the last three runs, then I could order by the run-time and limit it to just one result, getting the fastest run!
Cursor fastestWorkout = db.rawQuery
("Select _id, RunTimeSeconds, DistanceID FROM (Select _id, RunTimeSeconds, DistanceID, ActivityID FROM Workout ORDER BY _id DESC LIMIT 3) WHERE ActivityID = " + workout.getInt(0) +
" AND DistanceID = " + workout.getInt(1) +
" ORDER BY RunTimeSeconds LIMIT 1", null);
Thanks for your help ans answers!
I'm having kind of a problem here, since I just startet developing for Android. I downloaded the sample from the official Android website "http://developer.android.com/training/contacts-provider/retrieve-names.html", which is basically capable of retrieving an showing all the contacts from the phone. The feature I wanted to add is to just show contacts from a certain group like "Friends" (hardcoded).
As far as I narrowed it down I have to change the selection part
final static String SELECTION =
(Utils.hasHoneycomb() ? Contacts.DISPLAY_NAME_PRIMARY : Contacts.DISPLAY_NAME) +
"<>''" + " AND " + Contacts.IN_VISIBLE_GROUP + "=1";
to something like this
final static String SELECTION =
Contacts.GroupID = "Friends";
which gives me errors, because it can't find the column.
I'm very eager to explore the potential of Android, but that one is giving me headache.
There two ways for getting list of contacts of a group. First, I suppose you have GroupId and want to get related list of contacts.
String[] projection = {
ContactsContract.Groups._ID,
ContactsContract.Groups.TITLE,
ContactsContract.Groups.ACCOUNT_NAME,
ContactsContract.Groups.ACCOUNT_TYPE
};
return context.getContentResolver().query(
ContactsContract.Groups.CONTENT_URI, projection, ContactsContract.Groups._ID + "=" + groupId , null, null
);
Second way:
I suppose you want to get contacts of specific group by a constants name. so, it's enough you change above codes:
context.getContentResolver().query(
ContactsContract.Groups.CONTENT_URI, projection, ContactsContract.Groups.ACCOUNT_NAME + "='Friends'" , null, null
);
Now you have necessary details from specific Group. Then you can fetch list of Contact List:
public static Cursor getContactsOfGroup(Group group) {
// getting ids of contacts that are in this specific group
String where = ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID + "="
+ group.id + " AND "
+ ContactsContract.CommonDataKinds.GroupMembership.MIMETYPE + "='"
+ ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE + "'";
Cursor query = context.getContentResolver().query(
ContactsContract.Data.CONTENT_URI,
new String[] {
ContactsContract.CommonDataKinds.GroupMembership.CONTACT_ID
}, where, null, ContactsContract.Data.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
String ids = "";
for (query.moveToFirst(); !query.isAfterLast(); query.moveToNext()) {
ids += "," + query.getString(0);
}
if (ids.length() > 0) {
ids = ids.substring(1);
}
// getting all of information of contacts. it fetches all of number from every one
String[] projection = new String[]{
"_id",
"contact_id",
"lookup",
"display_name",
"data1",
"photo_id",
"data2", // number type: 1:home, 2:mobile, 3: work, else : other
};
String selection = "mimetype ='" + ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "'"
+ " AND account_name='" + group.accountName + "' AND account_type='" + group.accountType + "'"
+ " AND contact_id in (" + ids + ")";
return context.getContentResolver().query(BASE_URI, projection, selection, null, null);
}
Notice, in second fetch in this method we check accountName and accountType to be sure this record is related this group, because may be there are some records that stored for another Apps like WhatsApp. and we don't like get those. ok?
I hope will useful for you.
I have a table in my data base that has three columns: Screen, Icon, and Rank: and i am trying to find the cleanest way to achieve the following..
i want to find all rows WHERE Screen = "myScreen" and Rank >5 // then make rank one less than current value.. I am doing this in Java via a SQLite Manager class in the following function:
public void DeleteScreenIcon (int id, String screenName, int rank){
int screenID = getScreenID(screenName);
SQLiteDatabase db=this.getWritableDatabase();
db.delete(isLookUp, colScreenID + "=" + screenID + " and " +colIconID+ "="+id, null);
// HERE IS WHERE I NOW WANT TO DO THAT..
db.execSQL("update "+ isLookUp +" set "+colRank+ "=" +colRank+ " -1 "+" where " + colScreenID + "='" +screenName + "' and " + colRank +">" +rank);
db.close();
}
sorry, im not that versed in SQL any help is appreciated
This update should do the trick:
UPDATE myTable
SET Rank = Rank - 1
WHERE Screen = "myScreen"
AND Rank > 5;