Java Android中使用SQLite的外键约束?关于删除级联
我有两个表格:轨道和航路点,一条轨道可以有许多航路点,但一个航路点只分配给一条轨道 在way points表中,我有一个名为“trackidfk”的列,它在创建轨迹后插入轨迹ID,但是我没有在此列上设置外键约束 当我删除轨道时,我想删除指定的航路点,这可能吗?。我读过关于使用触发器的文章,但我认为Android不支持触发器 要创建航路点表,请执行以下操作:Java Android中使用SQLite的外键约束?关于删除级联,java,android,sqlite,foreign-keys,Java,Android,Sqlite,Foreign Keys,我有两个表格:轨道和航路点,一条轨道可以有许多航路点,但一个航路点只分配给一条轨道 在way points表中,我有一个名为“trackidfk”的列,它在创建轨迹后插入轨迹ID,但是我没有在此列上设置外键约束 当我删除轨道时,我想删除指定的航路点,这可能吗?。我读过关于使用触发器的文章,但我认为Android不支持触发器 要创建航路点表,请执行以下操作: public void onCreate(SQLiteDatabase db) { db.execSQL( "CREATE TABL
public void onCreate(SQLiteDatabase db) {
db.execSQL( "CREATE TABLE " + TABLE_NAME
+ " ("
+ _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ LONGITUDE + " INTEGER,"
+ LATITUDE + " INTEGER,"
+ TIME + " INTEGER,"
+ TRACK_ID_FK + " INTEGER"
+ " );"
);
...
}
我认为SQLite不支持这种开箱即用的方式。我在应用程序中所做的是:
通过这种方式,我确定要么删除所有数据,要么不删除任何数据。触发器受android支持,而这种级联删除类型不受sqlite支持。可以找到在android上使用触发器的示例。尽管使用Thorsten所说的事务可能与触发器一样简单。支持带on delete cascade的外键约束,但您需要启用它们。
我刚刚将以下内容添加到我的SQLOpenHelper中,这似乎起到了作用
@Override
public void onOpen(SQLiteDatabase db) {
super.onOpen(db);
if (!db.isReadOnly()) {
// Enable foreign key constraints
db.execSQL("PRAGMA foreign_keys=ON;");
}
}
我声明我的引用列如下
mailbox_id INTEGER REFERENCES mailboxes ON DELETE CASCADE
android 1.6中的SQLite版本是3.5.9,所以它不支持外键 “本文档描述了对SQLite版本3.6.19中引入的SQL外键约束的支持。” 在Froyo中是SQLite版本3.6.22,所以 编辑: 要查看sqlite版本:Android 2.2及更高版本的sqlite支持adb shell sqlite3版本外键和“on delete cascade”。但在使用它们时要小心:有时在一列上启动一个外键时会报告错误,但真正的问题在于子表中的另一列外键约束,或者某个其他表引用此表 看起来SQLite在启动其中一个约束时会检查所有约束。文档中实际上提到了它。DDL与DML约束检查。因为Android 4.1(API 16)支持:
public void setForeignKeyConstraintsEnabled (boolean enable)
正如e.shishkin在API 16上的帖子所说,您应该使用
db.setForeignKeyConstraintEnabled(布尔值)
在SqLiteOpenHelper.onConfigure(SqLiteDatabase)
方法中启用外键约束
无论@phil提到什么都是好的。但您可以使用中提供的另一个默认方法 数据库本身来设置foreignkey。这是setForeignKeyConstraintEnabled(true)
有关文档,请参阅“永远不要太老的问题”以获得更完整的答案
@Override public void onOpen(SQLiteDatabase db) {
super.onOpen(db);
if (!db.isReadOnly()) {
setForeignKeyConstraintsEnabled(db);
}
mOpenHelperCallbacks.onOpen(mContext, db);
}
private void setForeignKeyConstraintsEnabled(SQLiteDatabase db) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
setForeignKeyConstraintsEnabledPreJellyBean(db);
} else {
setForeignKeyConstraintsEnabledPostJellyBean(db);
}
}
private void setForeignKeyConstraintsEnabledPreJellyBean(SQLiteDatabase db) {
db.execSQL("PRAGMA foreign_keys=ON;");
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void setForeignKeyConstraintsEnabledPostJellyBean(SQLiteDatabase db) {
db.setForeignKeyConstraintsEnabled(true);
}
@覆盖公共void onOpen(SQLiteDatabase db){
super.onOpen(db);
如果(!db.isReadOnly()){
SetForeignKeyConstraintEnabled(db);
}
onOpen(mContext,db);
}
私有void setForeignKeyConstraintEnabled(SQLiteDatabase db){
if(Build.VERSION.SDK\u INT
如果您使用的是Android Room,请按如下所示操作
Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
.addCallback(object : RoomDatabase.Callback() {
// Called when the database has been opened.
override fun onOpen(db: SupportSQLiteDatabase) {
super.onOpen(db)
//True to enable foreign key constraints
db.setForeignKeyConstraintsEnabled(true)
}
// Called when the database is created for the first time.
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
}
}).build()
但是您是否使用一种方法从两个表中删除?是的,我非常赞同API中的Notes示例。在您的情况下,当我要删除轨道时,我会创建事务、删除轨道和航路点并提交事务。这一切都是一次性的,这意味着它只有在安卓2.2Froyo之后才能工作,而安卓2.2Froyo有SQLITE3.6。22@RedPlanet-这是因为只有在将某些内容写入数据库时才强制执行此约束。(如果您所做的一切都是从数据库中读取,则无法打破此约束)另外,Phil,与其使用onOpen方法,不如使用onConfigure方法。源代码:谷歌建议编写“代码> PrasMa<代码>语句,但它需要API级别16(Android 4.1),然后可以简单地调用。一个还需要考虑在代码< OnCudio< /代码> /<代码> OnDevel < <代码> >代码>升级> <代码>之前启用外键约束。请参阅。@Natix包括对super的调用,以确保在实现的类和其父类之间引入中间类时功能正确。那么是否有任何方法强制执行此类约束。。我的意思是有没有办法升级sqlite版本。。因为我们必须支持android 2.1的软件版本,该版本的sqlite版本为3.5.9,如上所述。不,您必须自己处理所有事情:(您发布的文档建议:
调用此方法的好时机是在调用openOrCreateDatabase(File,SQLiteDatabase.CursorFactory)之后或在onConfigure中(SQLiteDatabase)回调。
因此,与打开相比,onconfig
似乎是正确的位置。
@Override public void onOpen(SQLiteDatabase db) {
super.onOpen(db);
if (!db.isReadOnly()) {
setForeignKeyConstraintsEnabled(db);
}
mOpenHelperCallbacks.onOpen(mContext, db);
}
private void setForeignKeyConstraintsEnabled(SQLiteDatabase db) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
setForeignKeyConstraintsEnabledPreJellyBean(db);
} else {
setForeignKeyConstraintsEnabledPostJellyBean(db);
}
}
private void setForeignKeyConstraintsEnabledPreJellyBean(SQLiteDatabase db) {
db.execSQL("PRAGMA foreign_keys=ON;");
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void setForeignKeyConstraintsEnabledPostJellyBean(SQLiteDatabase db) {
db.setForeignKeyConstraintsEnabled(true);
}
Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
.addCallback(object : RoomDatabase.Callback() {
// Called when the database has been opened.
override fun onOpen(db: SupportSQLiteDatabase) {
super.onOpen(db)
//True to enable foreign key constraints
db.setForeignKeyConstraintsEnabled(true)
}
// Called when the database is created for the first time.
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
}
}).build()