簡體   English   中英

在Android的SQLite中使用INNER JOIN遇到問題

[英]Trouble using INNER JOIN in SQLite in Android

我在本地服務器上有一個MySQL數據庫。 我通過HTTP使用PHP和JSON從MySQL數據庫中獲取數據。 在Android應用中,使用JSON結果填充SQLite數據庫。 我已經驗證了SQLite數據庫實際上是通過運行類似於以下內容的測試查詢來填充的

Cursor cursor = database.rawQuery("SELECT recipe_id, ingredient_id, name FROM mm_ingredient_in_recipe_groups", null);

然后迭代結果光標以查看數據是否存在。 存在的數據存儲在三個表中:

  1. mm_ingredients ,包含食譜的成分。
  2. mm_recipes ,包含配方數據。
  3. mm_ingredient_in_recipe ,包含用於將數據mm_recipesmm_ingredients的數據(即解決多對多關系)。

我想做的是運行一個查詢,為參數配方名稱選擇成分。 這意味着我必須使用mm_ingredient_in_recipemm_ingredients來內mm_ingredient_in_recipe mm_recipes

我嘗試運行以下查詢:

database.rawQuery("SELECT ingredient.name, ingredient.base_unit FROM mm_ingredients AS ingredient INNER JOIN mm_ingredient_in_recipe AS ir ON ir.ingredient_id = ingredient._id INNER JOIN mm_recipes AS recipe ON ir.recipe_id = recipe._id WHERE recipe.name = ?", new String[] {"Spicy tomatsuppe"});

這將返回一個空游標。 但是,在我的MySQL數據庫中,運行相應的查詢

SELECT ingredient.name, ingredient.base_unit FROM mm_ingredients AS ingredient INNER JOIN mm_ingredient_in_recipe AS ir ON ir.ingredient_id = ingredient.id INNER JOIN mm_recipes AS recipe ON ir.recipe_id = recipe.id WHERE recipe.name = "Spicy tomatsuppe";

返回期望的數據。 我在這里做錯了什么? 似乎我運行的每個查詢都可以正常工作,直到我開始包含INNER JOIN為止。 (據我所知,最好的做法是在SQLite中將id字段命名為_id。)

編輯:添加用於寫入數據庫的代碼:

以下是如何為表mm_recipes填充數據庫的mm_recipes 其他兩個表也是如此。 我將JSONArray.optString()用於SQLite的TEXT數據類型,將JSONArray.optInt()用於INTEGER ,將JSONArray.optDouble()用於REAL

public static final String TABLE_NAME                       = "mm_recipes";
public static final String TABLE_NAME_IN_JSON               = "mm_recipes";

public static final String COLUMN_ID                        = "_id";
public static final String COLUMN_NAME                      = "name";
public static final String COLUMN_IN_APP                    = "in_app";
public static final String COLUMN_DIFFICULTY                = "difficulty";
public static final String COLUMN_TIME_CONSUMPTION_UPPER    = "time_consumption_upper";
public static final String COLUMN_TIME_CONSUMPTION_LOWER    = "time_consumption_lower";
public static final String COLUMN_PREPARATION_TIME          = "preparation_time";
public static final String COLUMN_PORTIONS                  = "portions";
public static final String COLUMN_PORTIONS_UNIT             = "portions_unit";
public static final String COLUMN_DESCRIPTION               = "description";
public static final String COLUMN_TIPS                      = "tips";
public static final String COLUMN_USE_INGREDIENT_GROUPS     = "use_ingredient_groups";

public static final void populateDatabase(SQLiteDatabase database, JSONObject databaseData) throws JSONException{

    JSONArray table_data = databaseData.optJSONArray(TABLE_NAME_IN_JSON);
    ContentValues contentValues = new ContentValues();

    for (int i = 0; i < table_data.length(); i++){
        JSONObject data = table_data.getJSONObject(i);

        contentValues.clear();

        contentValues.put(COLUMN_NAME,                      data.optString(COLUMN_NAME));
        contentValues.put(COLUMN_IN_APP,                    data.optInt(COLUMN_IN_APP));
        contentValues.put(COLUMN_DIFFICULTY,                data.optString(COLUMN_DIFFICULTY));
        contentValues.put(COLUMN_TIME_CONSUMPTION_UPPER,    data.optInt(COLUMN_TIME_CONSUMPTION_UPPER));
        contentValues.put(COLUMN_TIME_CONSUMPTION_LOWER,    data.optInt(COLUMN_TIME_CONSUMPTION_LOWER));
        contentValues.put(COLUMN_PREPARATION_TIME,          data.optInt(COLUMN_PREPARATION_TIME));
        contentValues.put(COLUMN_PORTIONS,                  data.optInt(COLUMN_PORTIONS));
        contentValues.put(COLUMN_PORTIONS_UNIT,             data.optString(COLUMN_PORTIONS_UNIT));
        contentValues.put(COLUMN_DESCRIPTION,               data.optString(COLUMN_DESCRIPTION));
        contentValues.put(COLUMN_TIPS,                      data.optString(COLUMN_TIPS));
        contentValues.put(COLUMN_USE_INGREDIENT_GROUPS,     data.optInt(COLUMN_USE_INGREDIENT_GROUPS));

        database.insert(TABLE_NAME, null, contentValues);
    }

}

作為參考,這也是如何創建mm_recipe表的示例。 在我的mm_recipe類別中:

public static final String DATATYPE_ID                      = "INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL";
public static final String DATATYPE_NAME                    = "TEXT NOT NULL";
public static final String DATATYPE_IN_APP                  = "INTEGER DEFAULT 0";
public static final String DATATYPE_DIFFICULTY              = "TEXT NOT NULL";
public static final String DATATYPE_TIME_CONSUMPTION_UPPER  = "INTEGER NOT NULL";
public static final String DATATYPE_TIME_CONSUMPTION_LOWER  = "INTEGER NOT NULL";
public static final String DATATYPE_PREPARATION_TIME        = "INTEGER";
public static final String DATATYPE_PORTIONS                = "INTEGER NOT NULL";
public static final String DATATYPE_PORTIONS_UNIT           = "TEXT NOT NULL";
public static final String DATATYPE_DESCRIPTION             = "TEXT";
public static final String DATATYPE_TIPS                    = "TEXT";
public static final String DATATYPE_USE_INGREDIENT_GROUPS   = "INT";

/**Create table statement.*/
public static final String CREATE_TABLE = 
    "CREATE TABLE"                  + " " + TABLE_NAME                      + " (" +
    COLUMN_ID                       + " " + DATATYPE_ID                     + ", " +
    COLUMN_NAME                     + " " + DATATYPE_NAME                   + ", " +
    COLUMN_IN_APP                   + " " + DATATYPE_IN_APP                 + ", " +
    COLUMN_DIFFICULTY               + " " + DATATYPE_DIFFICULTY             + ", " +
    COLUMN_TIME_CONSUMPTION_UPPER   + " " + DATATYPE_TIME_CONSUMPTION_UPPER + ", " +
    COLUMN_TIME_CONSUMPTION_LOWER   + " " + DATATYPE_TIME_CONSUMPTION_LOWER + ", " +
    COLUMN_PREPARATION_TIME         + " " + DATATYPE_PREPARATION_TIME       + ", " +
    COLUMN_PORTIONS                 + " " + DATATYPE_PORTIONS               + ", " +
    COLUMN_PORTIONS_UNIT            + " " + DATATYPE_PORTIONS_UNIT          + ", " +
    COLUMN_DESCRIPTION              + " " + DATATYPE_DESCRIPTION            + ", " +
    COLUMN_TIPS                     + " " + DATATYPE_TIPS                   + ", " +
    COLUMN_USE_INGREDIENT_GROUPS    + " " + DATATYPE_USE_INGREDIENT_GROUPS  + ");";

在我的SQLiteOpenHelper類中:

@Override
public void onCreate(SQLiteDatabase database) {
    database.execSQL(Table_mm_recipes.CREATE_TABLE);
    database.execSQL(Table_mm_ingredient_in_recipe.CREATE_TABLE);
    database.execSQL(Table_mm_ingredients.CREATE_TABLE);
} 

事實證明,這是(很出乎意料的)一些愚蠢的錯誤。 我將把它留在這里,以防其他人犯類似的錯誤。

由於我已經設置了每次創建時都刪除數據庫中所有內容的代碼,因此:

database.execSQL("DELETE FROM " + Table_mm_recipes.TABLE_NAME);
database.execSQL("DELETE FROM " + Table_mm_ingredient_in_recipe.TABLE_NAME);
database.execSQL("DELETE FROM " + Table_mm_ingredients.TABLE_NAME);

數據出了點問題。 這樣做實際上沒有任何意義,因為您可以只創建數據庫並在SQLiteOpenHelper.onCreate()插入數據就可以了。 如果需要在設置任何版本控制之前更新數據,只需卸載並重新安裝該應用程序即可。 然后,可以根據需要在SQLiteOpenHelper.onUpgrade()銷毀數據。 我不確定數據是如何被弄亂的,但是確實可以。

什么奇怪,雖然,是,我仍然可以看到通過做一個簡單的數據庫已經在其數據

Cursor cursor = database.rawQuery("SELECT recipe_id, ingredient_id, name FROM mm_ingredient_in_recipe_groups", null);

並從之前迭代該光標。 我在INNER JOIN語句之前直接對所有表執行了此操作,但是它們仍然無法正常工作。 這可能與錯誤刪除/創建數據庫有關。

除此之外,以上所有代碼均應有效並且可以工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM