【问题标题】:Cursor cannot find a column when foreign key is setup设置外键时光标找不到列
【发布时间】:2018-08-12 13:24:53
【问题描述】:

我已经尝试这个很久了。我正在尝试根据 ID 从数据库中检索内容。在我将 INNER JOIN 和 WHERE 子句引入我的语句之前,一切都运行良好。我收到了这个错误

错误

android.database.sqlite.SQLiteException: no such column: classes_sections.classes_sections_ids (code 1): , while compiling: SELECT * FROM classes INNER JOIN classes_sections ON classes_sections.classes_sections_ids = classes.classes_sections_id WHERE classes.classes_id =2

我认为问题出在我的外键引用和我的查询中。我真的需要你的帮助。我被困在这一点上。谢谢。

这是我声明我在数据库中使用的常量的地方(FK 表示外键和 PK 主键)

//Classes Table Columns names
private static final String COLUMN_CLASSES_ID = "classes_id";
private static final String COLUMN_CLASS_ITEM_INDEX ="class_item_index";
private static final String COLUMN_CLASSES_NAME = "classes_name";
private static final String COLUMN_CLASSES_CODENAME = "classes_codename";
private static final String COLUMN_CLASSES_SECTIONS = "classes_sections_id";//FK
private static final String COLUMN_CLASSES_TEACHERS = "classes_teachers";//FK
private static final String COLUMN_CLASSES_STUDENTS = "classes_students";//FK

//Classes Sections Table Column names
private static final String COLUMN_CLASSES_SECTIONS_ID = "classes_sections_ids";//PK
private static final String COLUMN_CLASSES_SECTIONS_NAME = "classes_sections_name";
private static final String COLUMN_CLASSES_SECTIONS_DESCRIPTION = "classes_sections_description";

这是我的表格的代码

 // create classes_table sql query
private String CREATE_CLASSES_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_CLASSES + "("
        + COLUMN_CLASSES_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + COLUMN_CLASS_ITEM_INDEX + " NUMBER,"
        + COLUMN_CLASSES_NAME + " VARCHAR," + COLUMN_CLASSES_CODENAME + " VARCHAR, " + COLUMN_CLASSES_SECTIONS + " INTEGER," + COLUMN_CLASSES_TEACHERS
        + " VARCHAR," + COLUMN_CLASSES_STUDENTS + " VARCHAR,"
        + "FOREIGN KEY(" + COLUMN_CLASSES_SECTIONS + " INTEGER) REFERENCES " + TABLE_CLASSES_SECTIONS  + "(" + COLUMN_CLASSES_SECTIONS_ID + ")  ON DELETE CASCADE  " + ");";



//create sections sql query
private String CREATE_CLASSES_SECTIONS_TABLE =  "CREATE TABLE IF NOT EXISTS " + TABLE_CLASSES_SECTIONS + "("
        + COLUMN_CLASSES_SECTIONS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + COLUMN_CLASSES_SECTIONS_NAME + " VARCHAR,"
        + COLUMN_CLASSES_SECTIONS_DESCRIPTION + " VARCHAR" + ")";

此方法通过ID从数据库中检索数据

public ArrayList<SectionsBean> getAllSectionsByClassesID(long id){

    String selectQuery = "SELECT * FROM "
            + "classes INNER JOIN classes_sections ON classes_sections.classes_sections_ids = classes.classes_sections_id WHERE classes.classes_id =" + id;

 SQLiteDatabase db = this.getReadableDatabase();

    ArrayList<SectionsBean> sectionsBeanList = new ArrayList<SectionsBean>();

   Cursor cursor = db.rawQuery(selectQuery,null);


    Log.i("Query details", String.valueOf(cursor));
    Log.d("DataDetails", DatabaseUtils.dumpCursorToString(cursor));

    while (cursor.moveToNext()) {


        ClassesBean classesBean = new ClassesBean();
        classesBean.setId(cursor.getLong(cursor.getColumnIndex(COLUMN_CLASSES_ID)));
        classesBean.setClasses_name(cursor.getString(cursor.getColumnIndex(COLUMN_CLASSES_NAME)));


        SectionsBean sectionsBean = new SectionsBean();
        sectionsBean.setSectionsID(cursor.getLong(cursor.getColumnIndex(COLUMN_CLASSES_SECTIONS_ID)));
        sectionsBean.setSections_name(cursor.getString(cursor.getColumnIndex(COLUMN_CLASSES_SECTIONS_NAME)));



        sectionsBean.setClassesBean(classesBean);
        sectionsBeanList.add(sectionsBean);

    }
    return sectionsBeanList;

}

【问题讨论】:

  • 您好,如果您要输出 SQL 代码字符串,您/我们可以在 SQL 环境中尝试它们。例如 sqlfiddle.com。你的 DDL 在哪里?我们如何才能看到您是否定义了据说不存在的列?请阅读minimal reproducible example并采取行动。

标签: android database sqlite foreign-keys cursor


【解决方案1】:

您的问题可能是由于输入错误,也许 classes_sections 不等于 TABLE_CLASSES_SECTIONS 解析到的任何内容。

我建议您始终只对所有数据库组件(数据库表列)使用单一来源。

因此而不是:-

String selectQuery = "SELECT * FROM "
            + "classes INNER JOIN classes_sections ON classes_sections.classes_sections_ids = classes.classes_sections_id WHERE classes.classes_id =" + id;

您应该按照以下方式构建查询:-

String selectQuery = "SELECT * FROM " +
    TABLE_CLASSES +
    " INNER JOIN " + TABLE_CLASSES_SECTIONS +
    " ON " +
    TABLE_CLASSES_SECTIONS + "." + COLUMN_CLASSES_SECTIONS_ID +
    " = " + TABLE_CLASSES + "." + COLUMN_CLASSES_SECTIONS +
    " WHERE " + 
    TABLE_CLASSES + "." + COLUMN_CLASSES_SECTIONS +
    " = " + String.valueOf(id);

注意

  • 这是原理代码,尚未经过测试,因此可能包含输入错误。

编辑

仔细检查后,classes 表的定义也存在问题,因为您已有效编码:-

CREATE TABLE IF NOT EXISTS classes (
        classes_id INTEGER PRIMARY KEY AUTOINCREMENT,"
        class_item_index NUMBER,
        classes_name" VARCHAR,
        classes_codename VARCHAR, 
        classes_sections_id INTEGER,
        classes_teachers VARCHAR,
        classes_students VARCHAR,
        FOREIGN KEY(classes_sections_id INTEGER) REFERENCES classes_sections  (classes_sections_ids)  ON DELETE CASCADE);

表约束定义在语法上不正确,因为 column_name 参数接受 1 个或多个逗号分隔的列名的列表。 INTEGER 不是有效的关键字:-

CREATE TABLE

因此你应该改变:-

// create classes_table sql query
private String CREATE_CLASSES_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_CLASSES + "("
        + COLUMN_CLASSES_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + COLUMN_CLASS_ITEM_INDEX + " NUMBER,"
        + COLUMN_CLASSES_NAME + " VARCHAR," + COLUMN_CLASSES_CODENAME + " VARCHAR, " + COLUMN_CLASSES_SECTIONS + " INTEGER," + COLUMN_CLASSES_TEACHERS
        + " VARCHAR," + COLUMN_CLASSES_STUDENTS + " VARCHAR,"
        + "FOREIGN KEY(" + COLUMN_CLASSES_SECTIONS + " INTEGER) REFERENCES " + TABLE_CLASSES_SECTIONS  + "(" + COLUMN_CLASSES_SECTIONS_ID + ")  ON DELETE CASCADE  " + ");";

到(*即从 column_names 参数中删除 INTEGER **):-

 // create classes_table sql query
private String CREATE_CLASSES_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_CLASSES + "("
        + COLUMN_CLASSES_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + COLUMN_CLASS_ITEM_INDEX + " NUMBER,"
        + COLUMN_CLASSES_NAME + " VARCHAR," + COLUMN_CLASSES_CODENAME + " VARCHAR, " + COLUMN_CLASSES_SECTIONS + " INTEGER," + COLUMN_CLASSES_TEACHERS
        + " VARCHAR," + COLUMN_CLASSES_STUDENTS + " VARCHAR,"
        + "FOREIGN KEY(" + COLUMN_CLASSES_SECTIONS + ") REFERENCES " + TABLE_CLASSES_SECTIONS  + "(" + COLUMN_CLASSES_SECTIONS_ID + ")  ON DELETE CASCADE  " + ");";

注意

  • 此更改将要求删除并重新创建类表。
    • 解决这个问题的最简单方法是删除数据库,但会丢失所有数据,在这种情况下会调用onCreate 方法(假设您使用的是 SQLiteOpenHelper 的子类,也就是 DatabaseHelper)。
    • 您可以清除/删除应用程序的数据或卸载应用程序,这将有效地删除数据库。

附加

使用从上述作品派生的以下 SQL(从句法上):-

DROP TABLE IF EXISTS classes;
CREATE TABLE IF NOT EXISTS classes (
        classes_id INTEGER PRIMARY KEY AUTOINCREMENT,
        class_item_index NUMBER,
        classes_name VARCHAR,
        classes_codename VARCHAR, 
        classes_sections_id INTEGER,
        classes_teachers VARCHAR,
        classes_students VARCHAR,
        FOREIGN KEY(classes_sections_id) REFERENCES classes_sections  (classes_sections_ids)  ON DELETE CASCADE);

DROP TABLE IF EXISTS classes_sections;
CREATE TABLE IF NOT EXISTS classes_sections (
        classes_sections_ids INTEGER PRIMARY KEY AUTOINCREMENT,
        classes_sections_name VARCHAR,
        classes_sections_description VARCHAR);
SELECT * FROM classes INNER JOIN classes_sections ON classes_sections.classes_sections_ids = classes.classes_sections_id WHERE classes.classes_id =2

即:-

【讨论】:

  • 谢谢@MikeT 我已经看到你的答案了,我今天晚些时候试试
  • ok @MikeT 我已经尝试了您的代码和建议的编辑,错误已经消失,但这次代码没有检索到任何内容。此时可能是什么问题。
  • 这是在 logcat 中作为光标内容显示的内容。 D/DataDetails: &gt;&gt;&gt;&gt;&gt; Dumping cursor android.database.sqlite.SQLiteCursor@24ff741 &lt;&lt;&lt;&lt;&lt; 表示光标@MikeT 中没有数据
  • 表为空,classes 表有行但没有引用 classes_sections 行,没有符合选择条件的 classes 行。
  • 但这怎么可能。 @MikeT 在单击类以检索所有数据之前,我首先使用一个小的添加按钮在应用程序中添加部分。可能是什么问题?
猜你喜欢
  • 1970-01-01
  • 2016-08-11
  • 2012-05-21
  • 2016-11-06
  • 2020-05-03
  • 2022-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多