关于我测试出了一个日常应该碰不到的 sqlite 问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
rrubick
V2EX    数据库

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

  •  
  •   rrubick 2023-12-29 09:40:44 +08:00 1707 次点击
    这是一个创建于 724 天前的主题,其中的信息可能已经有所发展或是发生改变。

    场景复现

    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 的问题呢?

    请大佬指点

    9 条回复    2024-01-01 21:39:54 +08:00
    codehz
        1
    codehz  
       2023-12-29 10:17:42 +08:00 via iPhone
    真要解决的话,用这个
    https://www.sqlite.org/pragma.html#pragma_user_version
    记录一个版本进去,写好升降级逻辑
    rrubick
        2
    rrubick  
    OP
       2023-12-29 10:36:17 +08:00
    @codehz #1
    主要是不太理解里面原理。而且我看到 sqlite 有个 ondowngrade 的默认实现,幸亏我看了一眼,原来默认是删数据。。。
    kneo
        3
    kneo  
       2023-12-29 11:24:27 +08:00
    数据库的表结构和数据都是数据,app 升级降级修改的是代码,数据还是原来的数据,除非你在代码里做了数据迁移。不可能说你用旧数据库代码会自动删除新 column 。
    rrubick
        4
    rrubick  
    OP
       2023-12-30 15:38:06 +08:00 via iPhone
    @codehz #1

    @kneo #3
    请教大佬,因为 sql 不支持插入前判断,那怎么去做到不会有 sql 执行报错呢
    kneo
        5
    kneo  
       2023-12-30 16:18:59 +08:00 via Android
    @magic3584 稳妥点,就执行一个语句拿 table 信息。
    PRAGMA table_info(table_name)
    自己根据表结构执行相应的操作。
    rrubick
        6
    rrubick  
    OP
       2023-12-30 21:11:33 +08:00
    @kneo #5
    我目前都是把每条 sql 语句放在数组里,然后在升级的时候去循环执行。
    sqlite 竟然不支持 ADD COLUMN IF NOT EXISTS 这种。如果执行多条 sql 的话,就只能在循环里加方法了。。。
    kneo
        7
    kneo  
       2023-12-30 22:18:46 +08:00
    每个数据库都不一样,不支持是很正常的。
    julyclyde
        8
    julyclyde  
       2024-01-01 20:04:05 +08:00
    为什么会爆 is exsit 呢?
    难道不是应该 does exist 吗??
    rrubick
        9
    rrubick  
    OP
       2024-01-01 21:39:54 +08:00
    @julyclyde #8
    反正就是 column 已经存在的意思,具体单词没记太清
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     989 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 18:52 PVG 02:52 LAX 10:52 JFK 13:52
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86