Swift中操作SQLite时如何为选中列设置别名,别名取值返回nil如何解决
问题根因
你使用的是SQLite.swift框架,出现该问题的核心原因是:你在查询时生成的别名表达式,和Model中取值时重新创建的Expression<Int>("C_ID")不是同一个实例。SQLite.swift的Row.get()方法是通过表达式的内部唯一标识匹配列,而非单纯匹配字符串别名,重复创建的同名表达式无法匹配到查询返回的别名列,因此会返回nil,强制取值时就会抛出“列不存在”的错误导致崩溃。
修复方案
步骤1:统一定义所有列与别名表达式
不要在不同逻辑中重复创建Expression实例,提前将用到的表、普通列、别名列统一抽离定义:
// 全局/同作用域统一定义,所有逻辑共用同一套表达式实例 let cat_table = Table("cat") let id = Expression<Int>("id") let cat_text = Expression<String>("text") // 提前定义好id列的别名表达式,后续查询、取值都用这个实例 let c_idAlias = id.alias(name: "C_ID")
步骤2:修改查询逻辑
查询时直接使用预定义的别名表达式即可:
func show() { do { // 打印生成的SQL可确认别名是否生效 print("生成的查询SQL:\(cat_table.select(id, cat_text, c_idAlias).asSQL())") let resultSet = try db.prepare(cat_table .select(id, cat_text, c_idAlias)) .map({ Model(row: $0) }) for res in resultSet { print("👉🏻 Name: \(res.c_id) -- ID: \(res.text) \n") } } catch { fatalError(error.localizedDescription) } }
步骤3:修改Model取值逻辑
取值时直接用预定义的别名表达式,不要重新创建同名Expression:
class Model { let id: Int let text: String let c_id: Int? // 不需要可选的话可以直接改成非可选类型 init(row: Row) { do { id = try row.get(id) text = try row.get(cat_text) // 共用预定义的别名表达式取值 c_id = try? row.get(c_idAlias) // 移除?强制取值也不会崩溃:c_id = try row.get(c_idAlias) } catch { print("Model初始化失败:\(error)") // 打印具体错误方便排查 fatalError() } } init() { id = 1 text = "" c_id = 1 } }
通用排查技巧
- 打印
row.columnNames可查看查询返回的所有列名,确认别名C_ID是否存在于返回结果中 - 打印
select语句的asSQL()返回值,可确认生成的原生SQL是否正确设置了别名 - 取值时捕获的error会明确提示“某列不存在”,出现该报错直接确认对应表达式是否和查询时用的是同一个实例
内容的提问来源于stack exchange,提问作者Arman_Gorjipoor
相关产品推荐
相关产品推荐

