1) Сбой из-за удаления, но почему logcat говорит только о добавлении вопросов в категории 4, 5 и 6 (которых нет в моей таблице категорий)?
Нет. Сбой или, по крайней мере, показанное сообщение происходит из-за того, что в нем говорится: нарушение ограничения FOREIGN KEY, которое происходит до удаления (в addQuestion(q6);
), и поэтому удаление никогда не происходит.
Объяснить ограничение FOREIGN KEY и почему оно не удалось, немного сложно, потому что кажется, что вы перепутали столбцы таблицы. Однако я предполагаю, что это само по себе не является проблемой.
В частности, вы определяете ограничение FOREIGN KEY, используя
FOREIGN KEY(column_in_this_table_which_you_have_right)
REFERENCES the_other_table_which_you_have_right
(column_in_the_other_table_????)
Для столбца в другой таблице у вас есть QuestionsTable._ID
, он должен быть CategoriesTable._ID
. Однако они, вероятно, называются одинаково. Так что это не вызывает проблемы.
Сообщение об ошибке включает category_id=6.
Предполагая, что они оба разрешают идентифицировать, вы фактически говорите
Разрешить вставку строки в таблицу questions только в том случае, если столбец category_id* таблицы **questions совпадает (может ссылаться) на строку в categories< /strong>, где столбец ID совпадает с идентификатором_категории (например, 6).
Короче говоря, отображаемые сообщения говорят, что нет категории с идентификатором 6.
Почему не говорится об удалении ссылочного столбца, как я ожидал?
Потому что он разбился, не дойдя до db.execSQL("DELETE FROM " + CategoriesTable.TABLE_NAME + " WHERE ID = 1");
2) Почему он выдает исключение времени выполнения, тогда как при попытке добавить вопрос с категорией, которой нет в таблице категорий, просто игнорируется команда SQLite, но не происходит сбой приложения?
Потому что, по всей вероятности, ваше приложение вылетит во многих местах без него. Вы говорите, что это очень важно для дизайна. Я почти не сомневаюсь, что если бы опция игнорирования была таковой, вы бы гораздо больше противоречили этому (т. Е. Наилучший доступный вариант, никто не заставляет вас определять ограничение). Хотя, если это то, что вы хотите, вы можете проверить 4.2 Отложенные ограничения внешнего ключа
Является ли исключение времени выполнения ожидаемым поведением при нарушении ограничения внешнего ключа при попытке удалить указанный столбец?
Повторюсь, вы не зашли так далеко.
Однако вы можете проверить 4.3 Действия ON DELETE и ON UPDATE
Изменить - Объяснение путаницы.
Короче говоря, сбой на самом деле происходит из-за ограничения DELETE. Ограничения INSERT фиксируются, но отображаются, поскольку используется стандартный метод insert
. Журнал, если вы посмотрите на него внимательно, покажет это, как объяснено ниже.
Вот пример, основанный на вашем коде, который я собрал: -
04-11 21:47:10.241 1927-1927/? E/SQLiteDatabase: Error inserting option1=A category_id=6 option2=B option3=C difficulty=Hard answer_nr=3 question=Hard: C is correct
android.database.sqlite.SQLiteConstraintException: foreign key constraint failed (code 19)
at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:775)
at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1469)
at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1339)
at askit.questionaire.DatabaseHelper.addQuestion(DatabaseHelper.java:70)
at askit.questionaire.DatabaseHelper.fillQuestionsTable(DatabaseHelper.java:97)
at askit.questionaire.DatabaseHelper.onCreate(DatabaseHelper.java:52)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:252)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
at askit.questionaire.DatabaseHelper.<init>(DatabaseHelper.java:17)
at askit.questionaire.MainActivity.onCreate(MainActivity.java:14)
at android.app.Activity.performCreate(Activity.java:5008)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
04-11 21:47:10.245 1927-1927/? D/AndroidRuntime: Shutting down VM
04-11 21:47:10.245 1927-1927/? W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0xa6294288)
04-11 21:47:10.245 1927-1927/? E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{askit.questionaire/askit.questionaire.MainActivity}: android.database.sqlite.SQLiteConstraintException: foreign key constraint failed (code 19)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.database.sqlite.SQLiteConstraintException: foreign key constraint failed (code 19)
at android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount(Native Method)
at android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:727)
at android.database.sqlite.SQLiteSession.executeForChangedRowCount(SQLiteSession.java:754)
at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:64)
at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1665)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1594)
at askit.questionaire.DatabaseHelper.fillQuestionsTable(DatabaseHelper.java:99)
at askit.questionaire.DatabaseHelper.onCreate(DatabaseHelper.java:52)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:252)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
at askit.questionaire.DatabaseHelper.<init>(DatabaseHelper.java:17)
at askit.questionaire.MainActivity.onCreate(MainActivity.java:14)
at android.app.Activity.performCreate(Activity.java:5008)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Вы видите эквивалент: -
04-11 21:47:10.241 1927-1927/? E/SQLiteDatabase: Error inserting option1=A category_id=6 option2=B option3=C difficulty=Hard answer_nr=3 question=Hard: C is correct
android.database.sqlite.SQLiteConstraintException: foreign key constraint failed (code 19)
Однако это не приводит к сбою приложения.
- Если вы запустите приложение после удаления базы данных с закомментированным DELETE и посмотрите журнал, вы увидите то же самое в журнале, даже если приложение не аварийно завершает работу.
Что вам нужно сделать, так это продолжить просмотр журнала, и вы найдете эквивалент: -
04-11 21:47:10.245 1927-1927/? D/AndroidRuntime: Shutting down VM
04-11 21:47:10.245 1927-1927/? W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0xa6294288)
04-11 21:47:10.245 1927-1927/? E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{askit.questionaire/askit.questionaire.MainActivity}: android.database.sqlite.SQLiteConstraintException: foreign key constraint failed (code 19)
Это сбой, то есть FATAL EXCEPTION:
Если вы продолжите, вы увидите вызвано, вот куда вы смотрите, так что у вас есть:-
Caused by: android.database.sqlite.SQLiteConstraintException: foreign key constraint failed (code 19)
at android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount(Native Method)
at android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:727)
at android.database.sqlite.SQLiteSession.executeForChangedRowCount(SQLiteSession.java:754)
at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:64)
at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1665)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1594)
at askit.questionaire.DatabaseHelper.fillQuestionsTable(DatabaseHelper.java:99)
at askit.questionaire.DatabaseHelper.onCreate(DatabaseHelper.java:52)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:252)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
at askit.questionaire.DatabaseHelper.<init>(DatabaseHelper.java:17)
at askit.questionaire.MainActivity.onCreate(MainActivity.java:14)
at android.app.Activity.performCreate(Activity.java:5008)
Если вы просмотрите журнал, вызванный, вы увидите, что первая строка, в которой упоминается ваш пакет:
at askit.questionaire.DatabaseHelper.fillQuestionsTable(DatabaseHelper.java:99)
Строка 99 (ваш номер строки будет другим, как и пакет) указывает на
![введите здесь описание изображения](https://i.stack.imgur.com/sdIse.jpg)
- Примечание. Я изменил строку, чтобы использовать КОНСТАНТ (
CategoriesTable._ID
) для столбца идентификатора категории.
person
MikeT
schedule
11.04.2018