关于我测试出了一个日常应该碰不到的 sqlite 问题

132 天前
 magic3584

场景复现

  1. 手机上安装版本 1 的 app
  2. 通过 Testflight 安装版本 2 ,数据都还在
  3. App Store 安装版本 1 ,数据还在
  4. 通过 Testflight 安装版本 2 ,数据没了(其实 db 还在)

当时凌晨 1 点多了,我刚提交审核,本来测试了前 3 步,我想着睡觉前再测一下更新问题,结果发现页面都空了。 作为一个本地数据存储的 app ,这是个致命的 bug 。于是我赶紧撤销了审核申请。

问题排查

前两步正常更新没问题,后面第 4 步发现页面空了。 由于 iPhone 没有越狱,看不到里面文件。于是我重复前 3 步,然后用 debug 安装版本 2 ,果然发现了问题。

版本 2 里我新增了字段ALTER TABLE table ADD COLUMN columnName,然后第四步的时候,由于是从版本 1 安装的,所以还会执行 db update 操作,这个 sql 报错Column is exsit 导致数据库关闭,所以页面没数据。Xcode 导出包内容后,db 文件都还在。

解决办法

问了 chatGPT ,它说 sql 应该这么写ALTER TABLE your_table ADD COLUMN IF NOT EXISTS new_column_name data_type; ,但是,运行的时候提示语法有问题,查了一下,sqlite 不支持这个语法😂 chatGPT 你真会玩。 但是,因为语法问题导致 sql 执行失败,数据库竟然能打开,我???

最后在执行 sql 的时候 try catch ,最起码不会打不开数据库了(之前没加是因为我觉得 sql 不会有问题)

讨论

为什么说这个 sqlite 问题日常碰不到呢,因为众所周知只能下最新版本的 app ,所以不会有在不同版本之间切换的操作。为了不让数据丢失,每次发版都小心翼翼的,这次真的吓到我了。

但是这里面的原理是什么呢?数据库版本降了字段不会自动删除吗?你们有碰到过哪种 sql 的问题呢?

请大佬指点

1297 次点击
所在节点    数据库
9 条回复
codehz
132 天前
真要解决的话,用这个
https://www.sqlite.org/pragma.html#pragma_user_version
记录一个版本进去,写好升降级逻辑
magic3584
132 天前
@codehz #1
主要是不太理解里面原理。而且我看到 sqlite 有个 ondowngrade 的默认实现,幸亏我看了一眼,原来默认是删数据。。。
kneo
132 天前
数据库的表结构和数据都是数据,app 升级降级修改的是代码,数据还是原来的数据,除非你在代码里做了数据迁移。不可能说你用旧数据库代码会自动删除新 column 。
magic3584
131 天前
@codehz #1

@kneo #3
请教大佬,因为 sql 不支持插入前判断,那怎么去做到不会有 sql 执行报错呢
kneo
131 天前
@magic3584 稳妥点,就执行一个语句拿 table 信息。
PRAGMA table_info(table_name)
自己根据表结构执行相应的操作。
magic3584
130 天前
@kneo #5
我目前都是把每条 sql 语句放在数组里,然后在升级的时候去循环执行。
sqlite 竟然不支持 ADD COLUMN IF NOT EXISTS 这种。如果执行多条 sql 的话,就只能在循环里加方法了。。。
kneo
130 天前
每个数据库都不一样,不支持是很正常的。
julyclyde
128 天前
为什么会爆 is exsit 呢?
难道不是应该 does exist 吗??
magic3584
128 天前
@julyclyde #8
反正就是 column 已经存在的意思,具体单词没记太清

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1004290

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX