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
相关产品推荐
相关产品推荐

