
1. 为什么 Category 表死活建不出来如果你正在跟着《第一行代码》或者类似的 Android 入门教程写 SQLite 示例大概率会卡在同一个地方MyDatabaseHelper里明明把CREATE_CATEGORY加进了onCreate()重新运行 App、点击「创建数据库」按钮结果category表就是不见踪影连那句「数据库创建成功」的 Toast 都不再弹了。这不是你代码写错了而是SQLiteOpenHelper的版本机制在起作用。SQLiteOpenHelper判断要不要执行onCreate()的唯一依据是数据库文件是否存在。BookStore.db在你第一次点按钮时就已经落盘到/data/data/包名/databases/目录下了之后无论你点多少次按钮getWritableDatabase()都只是打开这个已存在的文件onCreate()永远不会再被调用。你新加的建表语句自然也就没有机会执行。要触发建表逻辑必须走onUpgrade()这条路而触发它的开关就是构造方法里第四个参数——版本号。把它从1改成2系统检测到「当前请求版本 数据库文件记录版本」才会回调onUpgrade()。但这里有个经典坑很多教程第一版onUpgrade()直接写DROP TABLE再onCreate(db)数据全没了。正确做法是用switch(oldVersion)逐版本补丁且case末尾不写break保证跨版本升级时每一段修改都能顺序执行。这篇就按排障视角把MyDatabaseHelper的onCreate/onUpgrade和MainActivity里的版本号一起交给走 TaoToken 的 Codex 做对照检查让它指出哪一版漏了CREATE_CATEGORY、哪次升级会误删表。TaoToken 在这里只负责给 Codex 提供 Key 和 Base URL不参与建表、升级或任何 SQLite 操作。2. 前置给 Codex 配好 TaoToken 的 Key 和 Base URL在把代码丢给 Codex 之前先把接入信息准备好。这一步只做一次后面所有对话都复用。先去https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end注册账号登录后在控制台创建一把 API Key。创建入口在https://taotoken.net/consoleKey 管理页在https://taotoken.net/api-keys复制出来的那串就是后面要填的凭证。然后配置 Codex 的接入地址。Base URL 填https://taotoken.net/api注意结尾不要带/v1也不要带任何查询参数。Key 就用刚创建的那把。配置完成后Codex 的请求会走 TaoToken 转发到模型侧你本地不需要改任何网络设置。如果你更习惯在网页里直接对话验证可以打开https://taotoken.net/models用模型对话功能先试一句确认 Key 是通的。长期做编码和 Agent 任务的话https://taotoken.net/coding-plan里有对应的套餐说明按自己的调用量选就行。接入细节和参数说明统一看https://taotoken.net/docClaude Code 相关的配置在https://taotoken.net/claudecode-anthropic。注意TaoToken 只提供 Key 和 Base URL 这两个接入要素数据库的创建、升级、SQL 执行全部发生在你本地的 Android 运行时里跟 TaoToken 没有任何关系。排查结论要回到代码本身。3. 把 onCreate/onUpgrade 和版本号一起交给 Codex 对照配置好之后新建一个对话把下面这段「问题代码」整段贴进去。这是很多人卡住的原始状态onCreate()里已经补了CREATE_CATEGORYonUpgrade()还是粗暴的删表重建MainActivity里版本号还停在1。public class MyDatabaseHelper extends SQLiteOpenHelper { public static final String CREATE_BOOK CREATE TABLE book ( id integer PRIMARY KEY Autoincrement, author text, price real, pages integer, name text); public static final String CREATE_CATEGORY CREATE TABLE category ( id integer PRIMARY KEY Autoincrement, category_name text, category_code integer); private Context myContext; public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version); myContext context; } Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_BOOK); db.execSQL(CREATE_CATEGORY); Toast.makeText(myContext, 数据库创建成功, Toast.LENGTH_SHORT).show(); } Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL(DROP TABLE IF EXISTS Book); db.execSQL(DROP TABLE IF EXISTS Category); onCreate(db); } }// MainActivity 里构建 helper 的那一行 dbHelper new MyDatabaseHelper(this, BookStore.db, null, 1);贴完之后给 Codex 的指令可以这样写把排查目标说清楚这是我 Android 项目里的 SQLiteOpenHelper 子类和 MainActivity 的版本号调用。 现象BookStore.db 已存在我把 CREATE_CATEGORY 加进了 onCreate() 但重新运行点击按钮后 category 表建不出来Toast 也不弹。 请帮我对照检查三件事 1. onCreate() 里两张表的建表语句是否都完整 2. onUpgrade() 当前写法在版本号从 1 升到 2 时会发生什么是否会丢数据 3. MainActivity 里传入的版本号是否需要调整调整后 onUpgrade 应该怎么改才不丢数据。Codex 通常会指出onCreate()本身没问题两张表都在问题出在版本号还是1onUpgrade()根本不会触发而即便把版本号改成2触发了onUpgrade()当前的DROP TABLE写法会把book表里的数据全部清掉属于「升级即清库」的错误示范。4. 按 Codex 的结论改出正确的版本升级写法根据对照结果需要改两个地方。第一处是onUpgrade()改成按oldVersion逐版本打补丁的写法Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { switch (oldVersion) { case 1: db.execSQL(CREATE_CATEGORY); default: } }这里有两个细节必须说清楚。case 1里只执行CREATE_CATEGORY因为版本 1 到版本 2 的变化就是「新增一张 category 表」book表原样保留数据不动。case末尾不写break是为了让跨版本升级时后续case能继续往下走——比如用户从版本 1 直接升到版本 3case 1执行完会继续执行case 2的补丁保证每一版的结构变更都被应用。这是SQLiteOpenHelper官方推荐的增量升级模式。第二处是MainActivity里的版本号从1改成2dbHelper new MyDatabaseHelper(this, BookStore.db, null, 2);改完这两处重新运行 App点击「创建数据库」按钮。此时系统发现数据库文件记录的版本是1而代码请求的是2于是回调onUpgrade(db, 1, 2)进入case 1执行CREATE_CATEGORYcategory表被建出来同时book表和数据都还在。验证是否成功用 Android Studio 右下角的 Device File Explorer展开/data/data/你的包名/databases/能看到BookStore.db。右键导出或者用 Database Inspector 打开应该同时看到book和category两张表。如果只看到book说明版本号没生效或者onUpgrade没被调用回到第 5 节排查。5. 本篇常见错排查版本号改了但 onUpgrade 没触发。最常见的原因是 App 没有真正重新安装或数据库文件没被清掉。改版本号后建议先卸载 App 再运行或者手动删掉/data/data/包名/databases/BookStore.db让数据库从零创建这样onCreate()会直接建两张表。如果只是想验证升级路径就别删库直接改版本号跑。onUpgrade 里写了 break 导致跨版本漏补丁。有人觉得switch不写break是 bug顺手补上。结果用户从版本 1 升到版本 3 时case 1执行完就跳出case 2的补丁永远不执行表结构缺列。记住这里的switch是「顺序执行所有未完成的补丁」不是「匹配一个就停」。建表语句里表名大小写不一致。CREATE TABLE category和后面查询时写的Category在 SQLite 里默认不区分大小写但如果你在onUpgrade里DROP TABLE IF EXISTS Category而建的是category某些环境下会因为找不到表而报错。统一用小写最省心。Toast 不弹就以为 onCreate 没执行。Toast 只在onCreate()里数据库已存在时onCreate()不执行Toast 自然不弹这恰恰说明版本机制在工作。判断建表是否成功要看表本身不要看 Toast。把 TaoToken 当成能改数据库的工具。再强调一次TaoToken 给 Codex 提供的是 Key 和 Base URLCodex 帮你做的是代码对照和逻辑分析真正执行execSQL的是你手机或模拟器上的 Android 运行时。排查结论要落到MyDatabaseHelper和版本号上。6. 后续接入与验证入口代码改完、表建出来之后如果你还想让 Codex 帮你检查insert/update/delete/query那几段ContentValues和Cursor的写法或者排查Cursor忘记close()导致的内存泄漏可以继续在同一个对话里贴代码。接入信息不变Base URL 还是https://taotoken.net/apiKey 用https://taotoken.net/api-keys里那把。想先在网页里快速验证一段 SQL 或 Java 逻辑用https://taotoken.net/models的模型对话最直接。长期做 Android 编码和 Agent 任务https://taotoken.net/coding-plan里有对应的方案。所有接入参数和报错对照统一查https://taotoken.net/docClaude Code 场景的配置看https://taotoken.net/claudecode-anthropic。注册入口还是https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end第一次用的话从那里进就行。