You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用sqlite.swift读取SQLite的Blob字段崩溃:提示列值为空但实际有值

问题:SQLite.swift读取FMDB创建的Blob字段时崩溃

我用FMDB创建了SQLite数据库并插入数据,现在改用SQLite.swift替代FMDB。读取一个实际包含值的Blob类型字段时程序崩溃,报错如下:

SQLite/Query.swift:1235: Fatal error: 'try!' expression unexpectedly raised an error: Unexpected null value for column

相关代码

查询函数

func fetchAllNotes() -> [Note] {
    guard let db = db else {
        print("Database connection is not available.")
        return []
    }

    var notesArray = [Note]()

    do {
        for note in try db.prepare(notes) {
            let note = Note(
                id: note[id],
                title: note[title],
                content: note[content],
                isdraft: note[isdraft],
                fontsize: note[fontsize]
            )
            notesArray.append(note)
        }
    } catch {
        print("Failed to fetch notes: \(error)")
    }

    return notesArray
}

Note结构体

struct Note: Identifiable {
    let id: Int64
    let title: String
    let content: Blob
    let isdraft: Int
    let fontsize: Int

    init(id: Int64 = 0, title: String, content: Blob, isdraft: Int = 1, fontsize: Int = 16) {
        self.id = id
        self.title = title
        self.content = content
        self.isdraft = isdraft
        self.fontsize = fontsize
    }
}

崩溃栈信息

_swift_runtime_on_report

libswiftCore.dylib`:
->  0x7ff8156f7320 <+0>: pushq  %rbp //Crashed in this line
    0x7ff8156f7321 <+1>: movq   %rsp, %rbp
    0x7ff8156f7324 <+4>: popq   %rbp
    0x7ff8156f7325 <+5>: retq
    0x7ff8156f7326 <+6>: nopw   %cs:(%rax,%rax)

swift_unexpectedError

0x7ff81546c3fa <+826>: pushq  $0x0
0x7ff81546c3fc <+828>: pushq  -0x68(%rbp)
0x7ff81546c3ff <+831>: pushq  %rax
0x7ff81546c400 <+832>: pushq  -0x70(%rbp)
0x7ff81546c403 <+835>: callq  0x7ff815414870            ; Swift._assertionFailure(_: Swift.StaticString, _: Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never
->  0x7ff81546c408 <+840>: nopl   (%rax,%rax)

解决方案

问题核心是FMDB与SQLite.swift对Blob字段的空值处理逻辑不一致——即使你认为字段有值,可能存在部分数据中该字段实际为NULL,或者FMDB插入时允许空值但SQLite.swift读取时强制非空导致崩溃。

方法1:将Blob字段改为可选类型

修改Note结构体的content属性为可选类型,并调整初始化逻辑:

struct Note: Identifiable {
    let id: Int64
    let title: String
    let content: Blob?
    let isdraft: Int
    let fontsize: Int

    init(id: Int64 = 0, title: String, content: Blob?, isdraft: Int = 1, fontsize: Int = 16) {
        self.id = id
        self.title = title
        self.content = content
        self.isdraft = isdraft
        self.fontsize = fontsize
    }
}

查询时直接读取即可,SQLite.swift会自动处理NULL值:

let note = Note(
    id: note[id],
    title: note[title],
    content: note[content],
    isdraft: note[isdraft],
    fontsize: note[fontsize]
)

方法2:检查并修复数据库中的NULL记录

执行SQL查询确认是否存在content字段为NULL的记录:

SELECT * FROM notes WHERE content IS NULL;

如果存在这类记录,要么更新记录填充有效Blob数据,要么在后续插入时确保该字段不为空。

方法3:SQLite.swift字段定义匹配数据库规则

确保你的notes表字段定义中,content字段允许空值。对应SQLite.swift的表达式定义也要设为可选:

let content = Expression<Blob?>("content")

内容的提问来源于stack exchange,提问作者iDevBeginner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 18:23:12