2015-04-02 99 views
1

我在本地服务器上有一个MySQL数据库。我使用PHP和JSON over HTTP从MySQL数据库获取数据。在Android应用中,使用JSON结果填充SQLite数据库。我已经验证SQLite数据库实际上是通过运行类似于在Android中使用SQLite中的INNER JOIN时遇到问题

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(即解决多对多关系)中的数据的数据。

我想要做的是运行一个查询,选择参数配方名称的成分。这意味着我必须INNER JOIN mm_ingredientsmm_ingredient_in_recipemm_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。 (ID字段被命名为SQLite中_id,如应该是最好的做法,据我所知)。

编辑:添加代码写入到数据库:

下面是我如何填充一个例子数据库为表mm_recipes。其他两个表格也是如此。我使用JSONArray.optString()为SQLite的TEXT数据类型,JSONArray.optInt()INTEGERJSONArray.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); 
} 
+0

将数据写入数据库时​​,您可能使用了错误的数据类型。显示该代码。 – 2015-04-02 18:55:46

+0

我使用JSONArray的'optString()','optInt()'和'optDouble()'方法从JSON获取数据。如果我没有弄错的话,这些应该与SQLite的'TEXT','INTEGER'和'REAL'相对应。我编辑了这个问题以包含一个如何为'mm_recipes'填充数据库的例子。对于其他两个表格,它以相同的方式完成。 – 2015-04-02 19:13:10

回答

0

这竟然是(预期)一些愚蠢的错误。如果其他人发生类似的错误,我会在这里留下。

既然我已经设置代码上创作每次数据库删除所有内容,以这种方式:

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声明之前直接对所有表格进行了这项操作,但它们仍然无效。它可能与错误地删除/创建数据库有关。

除此之外,上面的所有代码都应该是有效的并且可以工作。