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

Sqlite.swift关联查询后如何使用列别名AS实现结果解码?

问题原因

SQLite.swift 在执行多表关联查询时,会自动对返回的列名添加表名前缀和双引号转义,你在 CodingKeys 中定义的questions.id格式和实际返回的转义后列名"questions"."id"不匹配,因此触发列不存在的报错。

推荐解决方案(别名法,兼容性最好)

在查询时给每个需要的字段指定无歧义的别名,直接和模型属性对应,完全避开转义列名匹配问题:

1. 修改查询代码

首先定义各表的字段表达式,查询时通过aliased方法指定别名:

let questions = Table("questions")
let replies = Table("replies")
        
let id = Expression<Int64>("id")
let questionId = Expression<Int64>("question_id")
// 分别定义两个表的text字段
let qText = Expression<String>("text")
let rText = Expression<String>("text")
              
// 查询时指定别名,和模型属性名完全对应
let query = questions.select(
    questions[id].aliased("id"),
    questions[qText].aliased("questionText"),
    replies[rText].aliased("replyText")
).join(replies, on: questions[id] == replies[questionId])

let rows = try! db.prepare(query)
let values: [MyModel] = try rows.map({ try $0.decode() })

2. 简化模型定义

不需要再带表名前缀,直接对应别名即可,同时移除解码时的try!避免意外崩溃:

struct MyModel: Decodable, Identifiable {
    var id: Int
    var questionText: String
    var replyText: String

    enum CodingKeys: String, CodingKey {
        case id, questionText, replyText
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.id = try container.decode(Int.self, forKey: .id)
        self.questionText = try container.decode(String.self, forKey: .questionText)
        self.replyText = try container.decode(String.self, forKey: .replyText)
    }
}
备选方案(不修改查询逻辑)

如果不想调整查询代码,也可以直接将 CodingKeys 的 rawValue 改为和转义后的列名完全匹配的格式,注意要把双引号也写进字符串里:

enum CodingKeys: String, CodingKey {
    case id = "\"questions\".\"id\""
    case questionText = "\"questions\".\"text\""
    case replyText = "\"replies\".\"text\""
}

该方案可读性差,后续如果表名或字段名修改容易出错,仅建议临时调试时使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 05:39:01