【问题标题】:How do I add a foreign key to a Table in SQLite?如何在 SQLite 的表中添加外键?
【发布时间】:2023-04-03 10:20:01
【问题描述】:

我创建了两个名为 TermTable 和 CourseTable 的表。我希望 CourseTable 有一个外键来引用 TermTable。

这是我创建表格的代码:


public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table " + TermDbSchema.TermTable.NAME + "(" +
                "_id integer primary key autoincrement, " +
                TermDbSchema.TermTable.Cols.UUID + ", " +
                TermDbSchema.TermTable.Cols.TITLE + ", " +
                TermDbSchema.TermTable.Cols.START_DATE + ", " +
                TermDbSchema.TermTable.Cols.END_DATE +
                ")"
        );
//I want to give CourseTable a foreign key to reference TermTable^^
        db.execSQL("create table " + TermDbSchema.CourseTable.NAME + "(" +
                "_id integer primary key autoincrement, " +
                TermDbSchema.CourseTable.Cols.UUID + ", " +
                TermDbSchema.CourseTable.Cols.TITLE + ", " +
                TermDbSchema.CourseTable.Cols.START_DATE + ", " +
                TermDbSchema.CourseTable.Cols.END_DATE + ", " +
                TermDbSchema.CourseTable.Cols.COURSE_STATUS + ", " +
                TermDbSchema.CourseTable.Cols.OPTIONAL_NOTE + ", " +
                TermDbSchema.CourseTable.Cols.MENTOR_NAME + ", " +
                TermDbSchema.CourseTable.Cols.MENTOR_PHONE + ", " +
                TermDbSchema.CourseTable.Cols.MENTOR_EMAIL +

                ")"
        );
}

这是代码架构代码:

public class TermDbSchema {

public static final class TermTable {
        public static final String NAME = "terms";
        public static final class Cols {
            public static final String UUID = "uuid";
            public static final String TITLE = "title";
            public static final String START_DATE = "startdate";
            public static final String END_DATE = "enddate";
        }
    }
    public static final class CourseTable {
        public static final String NAME = "courses";
        public static final class Cols {
            public static final String UUID = "uuid";
            public static final String TITLE = "title";
            public static final String START_DATE = "startdate";
            public static final String END_DATE = "enddate";
            public static final String COURSE_STATUS = "coursestatus";
            public static final String OPTIONAL_NOTE = "optionalnote";
            public static final String MENTOR_NAME = "mentorname";
            public static final String MENTOR_PHONE = "mentorphone";
            public static final String MENTOR_EMAIL = "mentoremail";        
        }
}

如何向 CourseTable 添加外键,以便它可以引用 TermTable?

【问题讨论】:

标签: java android sql sqlite android-sqlite


【解决方案1】:

将 CourseTable 更改为有另一列作为参考(链接、关系、关联、映射都是其他术语) :-

public static final class CourseTable {
    public static final String NAME = "courses";
    public static final class Cols {
        public static final String UUID = "uuid";
        public static final String TITLE = "title";
        public static final String START_DATE = "startdate";
        public static final String END_DATE = "enddate";
        public static final String COURSE_STATUS = "coursestatus";
        public static final String OPTIONAL_NOTE = "optionalnote";
        public static final String MENTOR_NAME = "mentorname";
        public static final String MENTOR_PHONE = "mentorphone";
        public static final String MENTOR_EMAIL = "mentoremail"; 
        public static final String TERM_LINK = "termlink"    //<<<<<<<<<< ADDED   
    }
  • 列名当然可以是你想要的

更改为课程表创建 SQL 以添加外键约束。

         db.execSQL("create table " + TermDbSchema.CourseTable.NAME + "(" +
            "_id integer primary key autoincrement, " +
            TermDbSchema.CourseTable.Cols.UUID + ", " +
            TermDbSchema.CourseTable.Cols.TITLE + ", " +
            TermDbSchema.CourseTable.Cols.START_DATE + ", " +
            TermDbSchema.CourseTable.Cols.END_DATE + ", " +
            TermDbSchema.CourseTable.Cols.COURSE_STATUS + ", " +
            TermDbSchema.CourseTable.Cols.OPTIONAL_NOTE + ", " +
            TermDbSchema.CourseTable.Cols.MENTOR_NAME + ", " +
            TermDbSchema.CourseTable.Cols.MENTOR_PHONE + ", " +
            TermDbSchema.CourseTable.Cols.MENTOR_EMAIL + ", " + //<<<<<<<<<< CHANGED
            TermDbSchema.CourseTable.Cols.TERM_LINK + " INTEGER REFERENCES " + TermDbSchema.TermTable.NAME + "(_id)" + //<<<<<<<<<< ADDED

            ")"
    );
  • 您可能希望遵守您的惯例,省略 INTEGER(列的类型亲和性),这不是问题。之所以包含它,是因为大多数会指定列类型,而不是应用默认 (NUMERIC)。

重要

然后重写onConfigure来调用setForeignKeyConstraintsEnabled传递true。

例如:-

@Override
public void onConfigure(SQLiteDatabase db) {
    super.onConfigure(db);
    db.setForeignKeyConstraintsEnabled(true);
}
  • 默认情况下外键支持是关闭的,除非外键支持打开,否则进行上述编码更改将毫无用处。

然后您需要执行以下操作之一:-

  • 删除应用数据
  • 卸载应用程序

然后重新运行应用程序。

  • 注意任何现有数据都将丢失。如果您需要保留数据,那可能会相对复杂。

外键

请注意,定义外键仅是定义一个约束(规则),该约束要求将值放入具有约束的列中,该值是所引用的父表/列的行之一中的值。

定义外键约束不会自动使关系发生。也就是说,您在添加课程时仍然需要确定相关术语(一个常见的误解是它会这样做)。

您可能希望考虑扩展定义以包括 ON DELETE 和 ON UPDATE 操作,例如 CASCADE。例如ON DELETE CASCADE 将在删除(如果)学期行时删除课程表中的子行。同样,如果学期表中的值发生更改,ON UPDATE CASCADE 将更新课程表中子项的引用值(这些可以使生活更简单)。

例如你可以使用:-

    TermDbSchema.CourseTable.Cols.TERM_LINK + " INTEGER REFERENCES " + TermDbSchema.TermTable.NAME + "(_id) ON DELETE CASCADE ON UPDATE CASCADE" + //<<<<<<<<<< ADDED

您不妨参考SQLite Foreign Key Support

【讨论】:

    【解决方案2】:

    CourseTable 类的 Cols 类中定义一个字符串,该字符串将包含此新列的名称,例如:

    public static final String TERM_ID = "term_id";
    

    更改表CourseTableCREATE语句:

    db.execSQL("create table " + TermDbSchema.CourseTable.NAME + "(" +
            "_id integer primary key autoincrement, " +
            TermDbSchema.CourseTable.Cols.UUID + ", " +
            TermDbSchema.CourseTable.Cols.TITLE + ", " +
            TermDbSchema.CourseTable.Cols.START_DATE + ", " +
            TermDbSchema.CourseTable.Cols.END_DATE + ", " +
            TermDbSchema.CourseTable.Cols.COURSE_STATUS + ", " +
            TermDbSchema.CourseTable.Cols.OPTIONAL_NOTE + ", " +
            TermDbSchema.CourseTable.Cols.MENTOR_NAME + ", " +
            TermDbSchema.CourseTable.Cols.MENTOR_PHONE + ", " +
            TermDbSchema.CourseTable.Cols.MENTOR_EMAIL + ", " +
            TermDbSchema.CourseTable.Cols.TERM_ID + " INTEGER, " +
            "FOREIGN KEY (" + TermDbSchema.CourseTable.Cols.TERM_ID +
            ") REFERENCES " + TermDbSchema.TermTable.NAME + "(_id)" + 
            ")"
    );
    

    这个新列将引用列_id,它是TermTable 的主键。
    您需要从设备上卸载应用程序,以便删除数据库,然后重新运行以重新创建数据库。

    【讨论】:

    • 这个不好的 setForeignKeyConstraintsEnabled(true) 获取数据库打开或 onConfigure 是需要的,否则什么也不会发生。
    猜你喜欢
    • 2010-12-25
    • 2021-02-12
    • 2018-07-19
    • 1970-01-01
    • 2023-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-24
    相关资源
    最近更新 更多