可以从 Android SQLiteConstraintException 获取具体的错误详细信息吗?

2023-11-27

对于某些数据,我收到以下错误,并且概念足够清晰:


android.database.sqlite.SQLiteConstraintException: FOREIGN KEY constraint failed (code 787)  

但是,这并不能帮助我找到哪个特定记录具有无效的 FK。有没有办法打开(或提取)日志记录并提供有用的详细信息(例如有问题的表,甚至导致问题的 FK 值),而不是破坏我的代码并尝试使用新事务隔离每个插入?

另外,我正在使用 SqlBrite,并打开了调试日志记录(仅记录操作,我仍然没有获得有关错误的更多信息)

Update:这是我自己的代码上面的所有 logcat;本质上,当尝试关闭先前打开的事务(BriteDatabase.Transaction)时会捕获异常(BriteDatabase.Transaction 对象是新添加的;我刚刚从 SqlBrite 0.1.0 迁移到 0.4.1)。

android.database.sqlite.SQLiteConstraintException: FOREIGN KEY constraint failed (code 787)
    at android.database.sqlite.SQLiteConnection.nativeExecute(Native Method)
    at android.database.sqlite.SQLiteConnection.execute(SQLiteConnection.java:555)
    at android.database.sqlite.SQLiteSession.endTransactionUnchecked(SQLiteSession.java:437)
    at android.database.sqlite.SQLiteSession.endTransaction(SQLiteSession.java:401)
    at android.database.sqlite.SQLiteDatabase.endTransaction(SQLiteDatabase.java:522)
    at com.squareup.sqlbrite.BriteDatabase$1.end(BriteDatabase.java:85)

解决方案一:

您可以使用adb shell dumpsys dbinfo -v命令查看有关数据库的一些信息。

就我而言,我创建了一个小示例,插入相同的记录两次,强制SQLiteConstraintException:

MyDB db = new MyDB(this);

// Insert the same record twice to force a SQLiteConstraintException
db.insertIntoMyTable("1","MyName");
db.insertIntoMyTable("1","MyName");

这是的输出adb shell dumpsys dbinfo -v我的 Nexus 4 中的命令(我不确定,但我认为输出信息在设备之间可能有所不同):

Connection pool for /data/data/com.your.package.name/databases/MyDB:
Open: true
Max connections: 1
Available primary connection:
Connection #0:
  connectionPtr: 0xffffffffb883aaf0
  isPrimaryConnection: true
  onlyAllowReadOnlyOperations: false
  Most recently executed operations:
    0: [2015-11-13 17:59:16.227] executeForLastInsertedRowId took 1ms - failed, sql="INSERT INTO MyTable(name,_id) VALUES (?,?)", bindArgs=["MyName", "1"], exception="UNIQUE constraint failed: MyTable._id (code 1555)"
    1: [2015-11-13 17:59:16.227] prepare took 0ms - succeeded, sql="INSERT INTO MyTable(name,_id) VALUES (?,?)"
    2: [2015-11-13 17:59:16.209] executeForLastInsertedRowId took 18ms - succeeded, sql="INSERT INTO MyTable(name,_id) VALUES (?,?)", bindArgs=["MyName", "1"]
    3: [2015-11-13 17:59:16.209] prepare took 0ms - succeeded, sql="INSERT INTO MyTable(name,_id) VALUES (?,?)"
    4: [2015-11-13 17:59:16.208] executeForLong took 1ms - succeeded, sql="PRAGMA user_version;"
    5: [2015-11-13 17:59:16.208] prepare took 0ms - succeeded, sql="PRAGMA user_version;"
    6: [2015-11-13 17:59:16.208] executeForString took 0ms - succeeded, sql="SELECT locale FROM android_metadata UNION SELECT NULL ORDER BY locale DESC LIMIT 1"
    7: [2015-11-13 17:59:16.207] execute took 1ms - succeeded, sql="CREATE TABLE IF NOT EXISTS android_metadata (locale TEXT)"
    8: [2015-11-13 17:59:16.207] executeForLong took 0ms - succeeded, sql="PRAGMA wal_autocheckpoint=100"
    9: [2015-11-13 17:59:16.207] executeForLong took 0ms - succeeded, sql="PRAGMA wal_autocheckpoint"
    10: [2015-11-13 17:59:16.207] executeForLong took 0ms - succeeded, sql="PRAGMA journal_size_limit=524288"
    11: [2015-11-13 17:59:16.207] executeForLong took 0ms - succeeded, sql="PRAGMA journal_size_limit"
    12: [2015-11-13 17:59:16.206] executeForString took 0ms - succeeded, sql="PRAGMA synchronous"
    13: [2015-11-13 17:59:16.206] executeForString took 0ms - succeeded, sql="PRAGMA journal_mode=PERSIST"
    14: [2015-11-13 17:59:16.205] executeForString took 1ms - succeeded, sql="PRAGMA journal_mode"
    15: [2015-11-13 17:59:16.204] executeForLong took 0ms - succeeded, sql="PRAGMA foreign_keys"
    16: [2015-11-13 17:59:16.204] executeForLong took 0ms - succeeded, sql="PRAGMA page_size"
  Prepared statement cache:
    0: statementPtr=0xffffffffb8839558, numParameters=0, type=1, readOnly=true, sql="SELECT locale FROM android_metadata UNION SELECT NULL ORDER BY locale DESC LIMIT 1"
Available non-primary connections:
<none>
Acquired connections:
<none>
Connection waiters:
<none>

分析输出,在Most recently executed operations:我得到以下信息(一条记录成功插入,另一条记录失败):

0: [2015-11-13 17:59:16.227] executeForLastInsertedRowId took 1ms - failed, sql="INSERT INTO MyTable(name,_id) VALUES (?,?)", bindArgs=["MyName", "1"], exception="UNIQUE constraint failed: MyTable._id (code 1555)"
2: [2015-11-13 17:59:16.209] executeForLastInsertedRowId took 18ms - succeeded, sql="INSERT INTO MyTable(name,_id) VALUES (?,?)", bindArgs=["MyName", "1"]

解决方案2:

这个解决方案有点棘手,但您可以使用android.database.sqlite.SQLiteDebug类通过 Java 代码获取类似信息。

如果你看一下this你会看到这个类被标记为@hide这意味着 SQLiteDebug 类已从 API 文档中排除,但仍然可以通过反射访问它。

因此,要打印 SQLite 数据库的调试信息,可以使用以下代码:

// The messages will be printed as Log.ERROR using the tag "DB"
Printer p = new LogPrinter(Log.ERROR, "DB");
// We will invoke the "dump" method of the "android.database.sqlite.SQLiteDebug" class
// We eill use the "-v" parameter because we want the output to be verbose
Class<?> c = Class.forName("android.database.sqlite.SQLiteDebug");
Method method = c.getMethod("dump", new Class[]{Printer.class, String[].class});
method.invoke(null, p, new String[]{"-v"});

一个简单的例子来说明解决方案:

MyDB db = new MyDB(this);

// Insert the same record twice to force a SQLiteConstraintException
db.insertIntoMyTable("1","MyName");
db.insertIntoMyTable("1","MyName");

try {
    Printer p = new LogPrinter(Log.ERROR, "DB");
    Class<?> c = Class.forName("android.database.sqlite.SQLiteDebug");
    Method method = c.getMethod("dump", new Class[]{Printer.class, String[].class});
    method.invoke(null, p, new String[]{"-v"});
}
catch (Exception e) {
    Log.e("MyTag", e.getMessage());
}

在这种情况下,我使用LogPrinter将调试信息转储到 logcat,但您可以使用自己的Printer执行。

在我的 Nexus 4 中,logcat 看起来像这样(我不确定,但我认为输出信息在设备之间可能有所不同):

E/SQLiteLog(22296): (1555) abort at 10 in [INSERT INTO MyTable(name,_id) VALUES (?,?)]: UNIQUE constraint failed: MyTable._id
E/SQLiteDatabase(22296): Error inserting name=MyName _id=1
E/SQLiteDatabase(22296): android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: MyTable._id (code 1555)
E/SQLiteDatabase(22296):    at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
E/SQLiteDatabase(22296):    at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:782)
E/SQLiteDatabase(22296):    at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
E/SQLiteDatabase(22296):    at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
E/SQLiteDatabase(22296):    at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1471)
E/SQLiteDatabase(22296):    at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1341)
E/SQLiteDatabase(22296):    at com.example.antonio.prueba3.MyDB.insertIntoMyTable(MyDB.java:32)
E/SQLiteDatabase(22296):    at com.example.antonio.prueba3.MainActivity.onCreate(MainActivity.java:24)
E/SQLiteDatabase(22296):    at android.app.Activity.performCreate(Activity.java:5990)
E/SQLiteDatabase(22296):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
E/SQLiteDatabase(22296):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
E/SQLiteDatabase(22296):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
E/SQLiteDatabase(22296):    at android.app.ActivityThread.access$800(ActivityThread.java:151)
E/SQLiteDatabase(22296):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
E/SQLiteDatabase(22296):    at android.os.Handler.dispatchMessage(Handler.java:102)
E/SQLiteDatabase(22296):    at android.os.Looper.loop(Looper.java:135)
E/SQLiteDatabase(22296):    at android.app.ActivityThread.main(ActivityThread.java:5254)
E/SQLiteDatabase(22296):    at java.lang.reflect.Method.invoke(Native Method)
E/SQLiteDatabase(22296):    at java.lang.reflect.Method.invoke(Method.java:372)
E/SQLiteDatabase(22296):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
E/SQLiteDatabase(22296):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
E/DB      (22296): Connection pool for /data/data/com.example.antonio.prueba3/databases/MyDB:
E/DB      (22296):   Open: true
E/DB      (22296):   Max connections: 1
E/DB      (22296):   Available primary connection:
E/DB      (22296):     Connection #0:
E/DB      (22296):       connectionPtr: 0xffffffffb883aaf0
E/DB      (22296):       isPrimaryConnection: true
E/DB      (22296):       onlyAllowReadOnlyOperations: false
E/DB      (22296):       Most recently executed operations:
E/DB      (22296):         0: [2015-11-13 17:59:16.227] executeForLastInsertedRowId took 1ms - failed, sql="INSERT INTO MyTable(name,_id) VALUES (?,?)", bindArgs=["MyName", "1"], exception="UNIQUE constraint failed: MyTable._id (code 1555)"
E/DB      (22296):         1: [2015-11-13 17:59:16.227] prepare took 0ms - succeeded, sql="INSERT INTO MyTable(name,_id) VALUES (?,?)"
E/DB      (22296):         2: [2015-11-13 17:59:16.209] executeForLastInsertedRowId took 18ms - succeeded, sql="INSERT INTO MyTable(name,_id) VALUES (?,?)", bindArgs=["MyName", "1"]
E/DB      (22296):         3: [2015-11-13 17:59:16.209] prepare took 0ms - succeeded, sql="INSERT INTO MyTable(name,_id) VALUES (?,?)"
E/DB      (22296):         4: [2015-11-13 17:59:16.208] executeForLong took 1ms - succeeded, sql="PRAGMA user_version;"
E/DB      (22296):         5: [2015-11-13 17:59:16.208] prepare took 0ms - succeeded, sql="PRAGMA user_version;"
E/DB      (22296):         6: [2015-11-13 17:59:16.208] executeForString took 0ms - succeeded, sql="SELECT locale FROM android_metadata UNION SELECT NULL ORDER BY locale DESC LIMIT 1"
E/DB      (22296):         7: [2015-11-13 17:59:16.207] execute took 1ms - succeeded, sql="CREATE TABLE IF NOT EXISTS android_metadata (locale TEXT)"
E/DB      (22296):         8: [2015-11-13 17:59:16.207] executeForLong took 0ms - succeeded, sql="PRAGMA wal_autocheckpoint=100"
E/DB      (22296):         9: [2015-11-13 17:59:16.207] executeForLong took 0ms - succeeded, sql="PRAGMA wal_autocheckpoint"
E/DB      (22296):         10: [2015-11-13 17:59:16.207] executeForLong took 0ms - succeeded, sql="PRAGMA journal_size_limit=524288"
E/DB      (22296):         11: [2015-11-13 17:59:16.207] executeForLong took 0ms - succeeded, sql="PRAGMA journal_size_limit"
E/DB      (22296):         12: [2015-11-13 17:59:16.206] executeForString took 0ms - succeeded, sql="PRAGMA synchronous"
E/DB      (22296):         13: [2015-11-13 17:59:16.206] executeForString took 0ms - succeeded, sql="PRAGMA journal_mode=PERSIST"
E/DB      (22296):         14: [2015-11-13 17:59:16.205] executeForString took 1ms - succeeded, sql="PRAGMA journal_mode"
E/DB      (22296):         15: [2015-11-13 17:59:16.204] executeForLong took 0ms - succeeded, sql="PRAGMA foreign_keys"
E/DB      (22296):         16: [2015-11-13 17:59:16.204] executeForLong took 0ms - succeeded, sql="PRAGMA page_size"
E/DB      (22296):       Prepared statement cache:
E/DB      (22296):         0: statementPtr=0xffffffffb8839558, numParameters=0, type=1, readOnly=true, sql="SELECT locale FROM android_metadata UNION SELECT NULL ORDER BY locale DESC LIMIT 1"
E/DB      (22296):   Available non-primary connections:
E/DB      (22296):     <none>
E/DB      (22296):   Acquired connections:
E/DB      (22296):     <none>
E/DB      (22296):   Connection waiters:
E/DB      (22296):     <none>

分析输出,我得到SQLiteConstraintException:

E/SQLiteDatabase(22296): android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: MyTable._id (code 1555)

并且在Most recently executed operations:我得到以下信息(一条记录成功插入,另一条记录失败):

E/DB      (22296):         0: [2015-11-13 17:59:16.227] executeForLastInsertedRowId took 1ms - failed, sql="INSERT INTO MyTable(name,_id) VALUES (?,?)", bindArgs=["MyName", "1"], exception="UNIQUE constraint failed: MyTable._id (code 1555)"
E/DB      (22296):         2: [2015-11-13 17:59:16.209] executeForLastInsertedRowId took 18ms - succeeded, sql="INSERT INTO MyTable(name,_id) VALUES (?,?)", bindArgs=["MyName", "1"]

希望能帮助到你。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

可以从 Android SQLiteConstraintException 获取具体的错误详细信息吗? 的相关文章

  • Android Studio 3.0.0 不允许 DOCTYPE

    升级到Android Studio 3 0 0 同步并更新gradle插件 出现以下错误 Error DOCTYPE not allowed if function http apache org xml features disallow
  • GridView 中多次调用 getView()

    我的 Activity 由包含 40 多个元素的 GridView 组成 开始活动后 用户最多可以看到 15 个项目 3 行 每行 5 个项目 我在 getView 正文中编写传递给获取 View 的 LogCat 编号 Log i get
  • android webview 函数 onPagefinished 被调用两次

    我的android webview功能onPageFinished被调用两次 我不知道为什么 但它在 android 2 2 上运行良好 但当我将其升级到 4 时 它就不起作用了 代码附在下面 Code Override public vo
  • 如何获取.so文件的依赖项列表?

    假设我有libFoo so为 android arm 编译 我不确定它链接到什么STL实现 有options http developer android com intl ru ndk guides standalone toolchai
  • Youtube 退出全屏模式 TextView 可见性问题

    我正在全屏模式下播放视频 当我单击后退按钮时 我可以退出全屏模式 但无法显示我在全屏情况下隐藏的 TextView 要在全屏模式下隐藏 textView 我使用以下代码 Override public void onInitializati
  • 如何从 Retrofit2 获取字符串响应?

    我正在做 android 正在寻找一种方法来执行超级基本的 http GET POST 请求 我不断收到错误 java lang IllegalArgumentException Unable to create converter for
  • SQLite + SpatiaLite 问题

    我正在尝试使用 System Data SQLite 提供程序从 C 访问 SpatiaLite 当我尝试加载 SpatiaLite 扩展时 我总是得到 System Data SQLite SQLiteException SQLite e
  • 如何将 android.net.Uri 转换为 java.net.URL? [复制]

    这个问题在这里已经有答案了 有没有办法从Uri to URL 我正在使用的库需要这个 它only接受一个URL但我需要在我的设备上使用图像 如果该方案的Uri is http or https new URL uri toString 应该
  • 如何防止布局的方向改变,而不是整个屏幕/活动的方向改变

    我需要一个子布局 可以是任何布局 例如FrameLayout or RelativeLayout 忽略方向变化并始终保持横向 但不是它的父级或任何其他兄弟布局 视图 它们应该相应地改变它们的方向 因此 我不能使用setRequestedOr
  • 如何在进入新活动之前终止线程和处理程序

    大家好 在我尝试清理处理程序时 这段代码可能有点混乱 因为我一直在尝试追踪崩溃发生的位置 我有一个对话框活动 显示密码输入 进度条由线程和处理程序动画显示 似乎当我试图查看进度条是否完成并尝试终止线程时 当我尝试进入新活动时 我这样做的方式
  • Android 从命令行停止模拟器

    这个问题与如何通过命令行关闭Android模拟器 https stackoverflow com questions 5912403 how to shut down android emulator via cmd 但是 在尝试第一个答案
  • Android Studio 将音乐文件读取为文本文件,如何恢复它?

    gameAlert mp3是我的声音文件 运行应用程序时 它询问我该文件不与任何文件类型关联 请定义关联 我选择TextFile错误地 现在我的音乐文件被读取为文本文件 我如何将其转换回music file protected void o
  • Android - 如何更改 TimePicker 中的文本颜色?

    我正在使用 TimePicker 到 LinearLayout 中 背景颜色 黑色 但是 我看不到 TimePicker 中的数字 并且我需要在布局中将背景颜色设置为黑色 如何更改 TimePicker 中的 textColor 我已经尝试
  • 在Android Studio中更改项目主题?

    我使用浅色主题创建了一些项目 现在我想将其更改为深色 但我不知道该怎么做 顺便说一句 我不是问如何在代码中做到这一点 只是问如何更改项目的默认主题 在 AndroidManifest xml 的 application 标签下 您可以设置您
  • Nexus 7 (2013) 和 Win 7 64 - 尽管检查了许多论坛和在线资源,仍无法安装 USB 驱动程序

    我正在尝试设置 Nexus 7 2013 进行调试 但我在安装 USB 驱动程序的步骤中陷入困境 到目前为止 这是我尝试过的 采取的步骤 在 Nexus 7 2013 上打开调试模式 连接设备至 PC 下载 Google USB 驱动程序于
  • 直接使用从密钥库加载的 SecretKey 时,密钥用户未经过身份验证

    我正在尝试使用 Cipher 和在 KeyStore 中加载的 SecretKey 来加密数据 但总是收到此错误 导致 android security KeyStoreException 关键用户未经过身份验证 我尝试自己创建 Secre
  • Android AutoCompleteTextView 带芯片

    我不确定我是否使用了正确的词语来描述此 UI 功能 但我已附上我希望在我的应用程序中实现的目标的快照 它由 Go SMS 使用 用户在编辑文本中键入联系人 在用户从完成下拉列表中选择联系人后 该联系人将被插入到编辑文本中 如附图所示 编辑文
  • Android:解析 XML 数据的最佳解析器 [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我正在开发一个应用程序 其中我第一次要解析来自远程服务器的 xml 文件中的数据 但我无法选择哪个解析器是有效的或最适合解析的 因为我知道主要有
  • Android ScrollView fillViewport 不工作

    我有一个简单的布局 名称位于顶部 按钮位于屏幕底部 或者超出该按钮 以防我添加更多项目 所以我使用带有 LinearLayout 的 ScrollView 如下所示
  • 当ScrollView滚动到底部时加载更多数据

    我有一个带有动态加载内容的滚动视图 有时可能会有很多内容 所以我想在用户滚动到底部时加载更多内容 我搜索了合适的方法 发现了两种 onScrollChanged and getScrollY 但我不知道如何将它用于我的目的 请给我一些建议

随机推荐