为什么我的内部联接查询不返回任何内容?

时间:2019-02-09 02:01:45

标签: java android sqlite

我有两个表格“锻炼”和“锻炼”。我正尝试使用与我们单击的“锻炼”匹配的“ execution_id”来获取所有锻炼。我进行了内部联接查询,但似乎未返回任何内容。我的查询出问题了吗?

我正在使用SQLite创建数据库。我已经检查以确保“练习”表中有一些练习,并且它们都有一个execution_id。

我的查询:

    @Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
    SQLiteDatabase db = dbHelper.getReadableDatabase();
    Cursor cursor = null;
    int match = uriMatcher.match(uri);
    switch (match){
        case WORKOUT:
            cursor = db.query(WorkoutContract.WorkoutEntry.TABLE_NAME_WORKOUT,projection,selection,selectionArgs,null,null,sortOrder);
            break;
        case WORKOUT_ID:
            selection = WorkoutContract.WorkoutEntry._ID + "=?";
            selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};
            cursor = db.query(WorkoutContract.WorkoutEntry.TABLE_NAME_WORKOUT,projection,selection,selectionArgs,null,null,sortOrder);
            break;
        case EXERCISE:
            cursor = db.query(WorkoutContract.WorkoutEntry.TABLE_NAME_EXERCISES,projection,selection,selectionArgs,null,null,sortOrder);
            break;
        case EXERCISE_ID:
            selection = WorkoutContract.WorkoutEntry._ID + "=?";
            selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};
            cursor = db.query(WorkoutContract.WorkoutEntry.TABLE_NAME_EXERCISES,projection,selection,selectionArgs,null,null,sortOrder);
            break;
        case WORkOUT_EXERCISE:
            final String QUERY = "SELECT workouts._id, " +
                    "exercise_name," +
                    "weight," +
                    "reps," +
                    "rpe"+
                    " FROM "+
                    "exercises"+
                    " INNER JOIN workouts ON workouts._id = exercises.workout_id"+
                    " WHERE workouts._id=1";
           cursor = db.rawQuery(QUERY, null);
            break;

        default:
            throw new IllegalArgumentException("Failed to retrieve" + uri);
    }
    cursor.setNotificationUri(getContext().getContentResolver(),uri);
    int rowcount = cursor.getCount();
    Log.d("ROWCOUNT","Number of rows = " + String.valueOf(rowcount));
    return cursor;    }

我的桌子:

String CREATE_TABLE_WORKOUTS = "CREATE TABLE " + WorkoutContract.WorkoutEntry.TABLE_NAME_WORKOUT + " ("
            + WorkoutContract.WorkoutEntry._ID + " INTEGER PRIMARY KEY, "
            + WorkoutContract.WorkoutEntry.WORKOUT_TITLE + " STRING, "
            + WorkoutContract.WorkoutEntry.WORKOUT_DATE + " STRING" + ")";

    String CREATE_TABLE_EXERCISES = "CREATE TABLE " + WorkoutContract.WorkoutEntry.TABLE_NAME_EXERCISES + " ("
            + WorkoutContract.WorkoutEntry._ID + " INTEGER PRIMARY KEY, "
            + WorkoutContract.WorkoutEntry.EXERCISE_NAME  + " STRING, "
            + WorkoutContract.WorkoutEntry.REPS + " INTEGER, "
            + WorkoutContract.WorkoutEntry.RPE + " INTEGER, "
            + WorkoutContract.WorkoutEntry.WEIGHT + " INTEGER, "
            + WorkoutContract.WorkoutEntry.WORKOUT_ID + " INTEGER, "
            + "FOREIGN KEY"+"("+ WorkoutContract.WorkoutEntry.WORKOUT_ID+")" + " REFERENCES "
            + WorkoutContract.WorkoutEntry.TABLE_NAME_WORKOUT
            +"("
            +(WorkoutContract.WorkoutEntry._ID) +")" +")";

我希望光标返回带有相应的execution_id的一些练习,但是我似乎什么也没回来。没有错误,只是一个空列表。

已修复

1)我在MainActivity中指向错误的URI,所以我更改了它。

Uri uri = withAppendedId(WorkoutContract.WorkoutEntry.CONTENT_URI, id);

Uri uri = withAppendedId(WorkoutContract.WorkoutEntry.JOIN_TABLE_URI, id);

2)回到我的WorkoutProvider类中,将selectionArgs设置为:

 selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};

并将其传递给我的rawQuery。

cursor = db.rawQuery(QUERY, selectionArgs);

1 个答案:

答案 0 :(得分:1)

您的问题是您实际上是在说..... WHERE workouts._id = '_id'的情况下说selectionArgs = new String[]{String.valueOf(WorkoutContract.WorkoutEntry.WORKOUT_ID)};

,而 WorkoutContract.WorkoutEntry.WORKOUT_ID 是列名 _id

因此,永远不会进行WHERE子句的匹配,因为 _id 列必须是整数(在Java语言中为长整数,因为它是64位带符号整数),因为该列是别名 rowid

相反,您需要使用

selectionArgs = new String[]{String.valueOf(the_id_that_you_are_looking_for)};

  • the_id_that_you_are_looking_for 可能是很长的(可以是int但应该正确的是很长),它是从您调用查询的位置传递/获得的,例如在一项活动中。

问题编辑后。

假设其他情况下的其他查询有效,则可以使用:-

    case WORkOUT_EXERCISE:

        String table = WorkoutContract.WorkoutEntry.TABLE_NAME_EXERCISES +
            " INNER JOIN " + WorkoutContract.WorkoutEntry.TABLE_NAME_WORKOUT +
            " ON " + WorkoutContract.WorkoutEntry.TABLE_NAME_WORKOUT + "." +
            WorkoutContract.WorkoutEntry._ID + " = " +
            WorkoutContract.WorkoutEntry.TABLE_NAME_EXERCISES + "." +
            WorkoutContract.WorkoutEntry.WORKOUT_ID;


        String[] columns = new String[]{
            WorkoutContract.WorkoutEntry.EXERCISE_NAME,
            WorkoutContract.WorkoutEntry.WEIGHT,
            WorkoutContract.WorkoutEntry.REPS,
            WorkoutContract.WorkoutEntry.RPE               
        };

        String whereclause = WorkoutContract.WorkoutEntry._ID + " =?";

        cursor = db.query(table,columns,whereclause,selectionArgs,null,null,null);
        break;

注释

  • 与其他情况一样,这基本上是使用查询方法,因为看起来潜在的问题是您不知道如何包括 JOIN (基本上它是第一个参数的一部分) 。
    • 第一个参数表,尽管文档说是用于编译查询的表名。 SQLiteDatabase - query实际上,它是 FROM 子句,可能非常复杂(如上所述)。
  • 我还没有假设其他参数可以直接使用,因此很可能是投影,而子句,selectionargs和sortorder可以直接使用(所以 table 可能是只有您需要关注的变量)。
  • 以上代码为原则代码,未经测试或运行,因此可能包含错误。

或者,您可以使用:-

    case WORkOUT_EXERCISE:
        final String QUERY = "SELECT workouts._id, " +
                "exercise_name," +
                "weight," +
                "reps," +
                "rpe"+
                " FROM "+
                "exercises"+
                " INNER JOIN workouts ON workouts._id = exercises.workout_id"+
                " WHERE workouts._id=?";
       cursor = db.rawQuery(QUERY, selectionArgs);
        break;
  • 这假定 selectionArgs 仅仅是传递的ID。
  • 这将比以前的方法适应性差。