V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
magic3584
V2EX  ›  数据库

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

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

    场景复现

    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
    记录一个版本进去,写好升降级逻辑
    magic3584
        2
    magic3584  
    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 。
    magic3584
        4
    magic3584  
    OP
       364 天前 via iPhone
    @codehz #1

    @kneo #3
    请教大佬,因为 sql 不支持插入前判断,那怎么去做到不会有 sql 执行报错呢
    kneo
        5
    kneo  
       364 天前 via Android
    @magic3584 稳妥点,就执行一个语句拿 table 信息。
    PRAGMA table_info(table_name)
    自己根据表结构执行相应的操作。
    magic3584
        6
    magic3584  
    OP
       363 天前
    @kneo #5
    我目前都是把每条 sql 语句放在数组里,然后在升级的时候去循环执行。
    sqlite 竟然不支持 ADD COLUMN IF NOT EXISTS 这种。如果执行多条 sql 的话,就只能在循环里加方法了。。。
    kneo
        7
    kneo  
       363 天前
    每个数据库都不一样,不支持是很正常的。
    julyclyde
        8
    julyclyde  
       362 天前
    为什么会爆 is exsit 呢?
    难道不是应该 does exist 吗??
    magic3584
        9
    magic3584  
    OP
       361 天前
    @julyclyde #8
    反正就是 column 已经存在的意思,具体单词没记太清
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2705 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 12:38 · PVG 20:38 · LAX 04:38 · JFK 07:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.