如何在GRDB中用INSTR批量更新多行?支持原生查询吗?
解决GRDB中实现指定UPDATE语句的问题
一、使用GRDB DSL正确实现
你当前的代码存在两处逻辑错误:
- 字符串包含判断写反:应该是数据库字段
title包含给定字符串,而非给定字符串包含字段 start的条件逻辑不符原SQL:原SQL是start - ? < 60,等价于start < ? + 60,你写的Column("start") > date - 60逻辑相反
修正后的DSL代码
方式1:用GRDB内置方法模拟instr行为
如果只需要判断子串存在,直接用contains方法即可,效果和instr非0判断一致:
_ = try dbQueue?.write { db in try MyTable // 对应原SQL的start - ? < 60 → start < date + 60 .filter(Column("start") < date + 60) // 对应instr(title, ?):字段title包含给定的title字符串 .filter(Column("title").contains(title)) .updateAll(db, Column("path").set(to: path)) }
方式2:显式调用instr函数
如果需要严格匹配instr的语法(比如特殊匹配场景),可以直接构造SQL函数表达式:
_ = try dbQueue?.write { db in try MyTable .filter(Column("start") < date + 60) // 调用instr函数,返回值非0则条件成立 .filter(SQL("instr(title, ?)", title) != 0) .updateAll(db, Column("path").set(to: path)) }
二、使用原生SQL查询实现
完全可以用原生SQL执行,GRDB支持直接执行原生语句,按SQL中占位符的顺序填充参数即可:
_ = try dbQueue?.write { db in let sql = "UPDATE MyTable SET path = ? WHERE instr(title, ?) AND start - ? < 60" // 参数顺序对应SQL中的三个占位符:path、title、date try db.execute(sql: sql, arguments: [path, title, date]) }
如果需要更严谨的类型控制,也可以用Statement构建执行:
_ = try dbQueue?.write { db in let statement = try db.makeStatement(sql: "UPDATE MyTable SET path = ? WHERE instr(title, ?) AND start - ? < 60") statement.arguments = [path, title, date] try statement.execute() }
内容的提问来源于stack exchange,提问作者Silve2611
相关产品推荐
相关产品推荐

