简体   繁体   中英

How to insert several values from one table to other table one column?

I'm creating android app and in one activity I need to create workout plan. From spinner I'm choosing exercise name (which comes from other table). I can choose more than one exercise. So which way is the best to do it? I tried adding several exercises to ArrayList and the save that ArrayList to database but I didn't find a way to do it. And I need to be able to edit workout plan(for example: delete or add exercises) so I think ArrayList is not a solution.

I realised that it's many to many relationship (a lot of exercises can be in a lot of workout plan) so I created table which contains exercise id and workout id:

   private static final String CREATE_TABLE_TRAININGEXERCISE = 
"CREATE TABLE " + TABLE_TRAININGEXERCISE + "(" + TEXERCISE_ID + 
" INTEGER," + TWORKOUT_ID + " INTEGER," + "FOREIGN KEY (TExerciseID) REFERENCES "
 + TABLE_EXERCISE + " (ExerciseID)," +
 " FOREIGN KEY (TWorkoutID) REFERENCES " + TABLE_WORKOUT + " (WorkoutID))";
}

I want my workout plan to look something like this:

  • Title: Chest
  • Exercises: Bench press 4x8| Incline bench press 3x12| Flies 3x12|

So how can I save these 3 exercises to one column?

Here's an example that does both what you ask, based upon you schema ie

  1. It adds a number of exercises to a workout via the mapping table (TRAININGEXERCISE) from an ArrayList (ArrayList as it uses id's).
  2. It produces output similar to what you wish (to the log) eg the example logs

:-

2019-05-13 13:13:46.736  D/MYDATA: Workout: Chest
        EXERCISES: Bench press,Incline bench press,Flies
2019-05-13 13:13:46.736  D/MYDATA: Workout: Abdomen
        EXERCISES: hump,lug,roll
2019-05-13 13:13:46.736  D/MYDATA: Workout: Everything
        EXERCISES: hump,lug,roll,kneel,Bench press,Incline bench press,Flies,Flip

The database helper, DBHelper.java used was :-

public class DBHelper extends SQLiteOpenHelper {

    public static final String DBNAME = "workout";
    public static final int DBVERSION = 1;

    public static final String TABLE_TRAININGEXERCISE = "training_excercise"; //<<<<<<<< OOOPS spelling :)
    public static final String TABLE_WORKOUT = "workout";
    public static final String TABLE_EXERCISE = "exersise"; //<<<<<<< OOOPS spelling :)
    public static final String TWORKOUT_ID = "WorkoutID";
    public static final String TWORKOUT_NAME = "workour_name";

    public static final String TEXERCISE_ID = "ExerciseID";
    public static final String TEXERCISE_NAME = "exercise_name";

    public static final String TTEEXERCISELINK = "TExerciseID"; //<<<<<<<<<< ADDED
    public static final String TTEWORKOUTLINK = "TWorkoutID"; //<<<<<<<<<< ADDED

    // Note as entities are always derived from constants above the spelling mistakes are irrelvant
    // (need a better smellchecker :) )

    //<<<<<<<<<< ENOUGH TO DEMONSTRATE >>>>>>>>>>
    private static final String CREATE_TABLE_WORKOUT =
            "CREATE TABLE " + TABLE_WORKOUT + "(" +
                    TWORKOUT_ID + " INTEGER PRIMARY KEY," +
                    TWORKOUT_NAME + " TEXT" +
                    ")";

    //<<<<<<<<<< ENOUGH TO DEMONSTRATE >>>>>>>>>>
    private static final String CREATE_TABLE_EXERCISE =
            "CREATE TABLE " + TABLE_EXERCISE + "(" +
                    TEXERCISE_ID + " INTEGER PRIMARY KEY," +
                    TEXERCISE_NAME + " TEXT " +
                    ")";

    //<<<<<<<<<<NOTE Uses constants for all entity names >>>>>>>>>> (see new ones above)
    private static final String CREATE_TABLE_TRAININGEXERCISE =
            "CREATE TABLE " + TABLE_TRAININGEXERCISE + "(" +
                    TTEEXERCISELINK + " INTEGER," +
                    TTEWORKOUTLINK + " INTEGER," +

                    "FOREIGN KEY (" + TTEEXERCISELINK + ") " +
                    "REFERENCES " + TABLE_EXERCISE + " (" + TEXERCISE_ID + ")," +

                    " FOREIGN KEY (" + TTEWORKOUTLINK + ") " +
                    "REFERENCES " + TABLE_WORKOUT + " (" + TWORKOUT_ID + "))";

    public DBHelper(Context context) {
        super(context, DBNAME, null, DBVERSION);
    }

    @Override
    public void onConfigure(SQLiteDatabase db) {
        super.onConfigure(db);
        db.setForeignKeyConstraintsEnabled(true); //<<<<<<<<<< MUST HAVE FOR FOREIGN KEYS
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_TABLE_EXERCISE);
        db.execSQL(CREATE_TABLE_WORKOUT);
        db.execSQL(CREATE_TABLE_TRAININGEXERCISE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    public long addWorkout(String name) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(TWORKOUT_NAME,name);
        return db.insert(TABLE_WORKOUT,null,cv);
    }

    public long addExecise(String name) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(TEXERCISE_NAME,name);
        return db.insert(TABLE_EXERCISE,null,cv);
    }

    public long addExcerciseToWorkout(long workoutid, long exerciseid) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(TTEWORKOUTLINK,workoutid);
        cv.put(TTEEXERCISELINK,exerciseid);
        return db.insert(TABLE_TRAININGEXERCISE,null,cv);
    }

    //<<<<<<<<<< ADD MANY EXERCISES to a WORKOUT via an ArrayList
    public void addManyExcercisesToWorkout(long workoutid,ArrayList<Long> exerciseids) {
        ArrayList<Long> rv = new ArrayList<>();
        SQLiteDatabase db = this.getWritableDatabase();
        db.beginTransaction();
        for (Long l: exerciseids) {
            long thisid = addExcerciseToWorkout(workoutid,l);
        }
        db.setTransactionSuccessful();
        db.endTransaction();
    }

    //<<<<<<<<<< Get all the exercises per workout via the group_concat function >>>>>>>>>>
    public void logAllWorkoutsWithExcercises() {
        SQLiteDatabase db = this.getWritableDatabase();
        //<<<<<<<<<< column name aliases (not required but desireable as they can be quite cumbersome) >>>>>>>>>>
        String workoutname_column_alias = "thisworkoutname";
        String concantenated_exercises_alias = "all_exercises";

        String tables = TABLE_WORKOUT +
                " JOIN " + TABLE_TRAININGEXERCISE + " ON " + TABLE_WORKOUT + "." + TWORKOUT_ID + "="  + TTEWORKOUTLINK +
                " JOIN " + TABLE_EXERCISE + " ON " + TTEEXERCISELINK +  "=" + TABLE_EXERCISE + "." + TEXERCISE_ID;
        String[] columns = new String[]{
                TABLE_WORKOUT + "." + TWORKOUT_NAME + " AS " + workoutname_column_alias,
                "'\n\tEXERCISES: '||group_concat(" +
                        TABLE_EXERCISE + "." + TEXERCISE_NAME +
                        ") AS " + concantenated_exercises_alias
        };
        String groupby = TABLE_WORKOUT + "." + TWORKOUT_ID;
        // Query resolves to :-
        /*
            SELECT 
                workout.workour_name AS thisworkoutname, 
                'EXERCISES: '||group_concat(exersise.exercise_name) AS all_exercises 
            FROM workout 
                JOIN training_excercise ON  workout.WorkoutID=TWorkoutID 
                JOIN exersise ON TExerciseID=exersise.ExerciseID 
                GROUP BY workout.WorkoutID
        */
        Cursor csr = db.query(tables,columns,null,null,groupby,null,null);
        while (csr.moveToNext()) {
            Log.d(
                    "MYDATA",
                    "Workout: " +
                            csr.getString(csr.getColumnIndex(workoutname_column_alias)) +
                            csr.getString(csr.getColumnIndex(concantenated_exercises_alias))
            );
        }
        csr.close();
    }
}

The testing was done via an activity as per :-

public class MainActivity extends AppCompatActivity {
    String[] allexcercises = new String[]{"hump", "lug", "roll", "kneel", "Bench press", "Incline bench press", "Flies","Flip"};
    // Note assume that hump is id 1, lug id 2 etc
    String[] allworkouts = new String[]{"Chest","Abdomen","Everything"};

    ArrayList<Long> chest_excercises = new ArrayList<>();
    ArrayList<Long> abdomen_excercises = new ArrayList<>();
    ArrayList<Long> everything_excercises = new ArrayList<>();

    DBHelper mDBHlpr;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDBHlpr = new DBHelper(this);
        addSomeData(); //<<<<<<<<<< Adds the testing data (only designed to run once)
        mDBHlpr.logAllWorkoutsWithExcercises(); //<<<<<<<<<< Output workouts with excercises
    }

    private void addSomeData() {
        // Excercises
        mDBHlpr.getWritableDatabase().beginTransaction();
        for (String excercise: allexcercises) {
            mDBHlpr.addExecise(excercise);
        }
        for (String workout: allworkouts) {
            mDBHlpr.addWorkout(workout);
        }
        mDBHlpr.getWritableDatabase().setTransactionSuccessful();
        mDBHlpr.getWritableDatabase().endTransaction();

        // Build ArrayLists as if from multiple spinner selections
        chest_excercises.add(new Long(5));
        chest_excercises.add(new Long(6));
        chest_excercises.add(new Long(7));

        abdomen_excercises.add(new Long(1));
        abdomen_excercises.add(new Long(2));
        abdomen_excercises.add(new Long(3));

        // Add all excercises to the everything workout ArrayList
        for(int l=1; l <= allexcercises.length; l++) {
            everything_excercises.add(new Long((long) l));
        }
        // Add multiple exercises per workout
        mDBHlpr.addManyExcercisesToWorkout(1,chest_excercises);
        mDBHlpr.addManyExcercisesToWorkout(2,abdomen_excercises);
        mDBHlpr.addManyExcercisesToWorkout(3,everything_excercises);

    }
}

You don't need to shove all exercises name into one column (which Contradicts the table scheme you created and will be hard to manipulate exercises if you do so), you need to insert each exercise into its own record in TABLE_TRAININGEXERCISE and link it to a single workout, the next step is to add an ArrayList into the workout model which you'll populate with a list of all exercises related to that same workout ID by using adding a method that fetches all records from TABLE_TRAININGEXERCISE using the workout ID.

That way you have its simpler to manipulate workout exercises (insert, update or delete) And you can achieve the desired output by printing the workout name and loop over its exercises and join them with a comma.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM