该fetchAll
方法返回一个常规的 Swift 数组,您可以像所有其他数组一样对其进行迭代:
let rows = try Row.fetchAll(db, sql, arguments:arguments) // [Row]
for row in rows {
// use row
}
该next
方法属于cursors,您可以通过该fetchCursor
方法获得。游标不是数组,因为它们不会一步加载所有数据库结果。相反,游标逐行迭代:
let rows = try Row.fetchCursor(db, sql, arguments:arguments) // DatabaseCursor<Row>
while let row = try rows.next() {
// use row
}
您会看到数组和游标都可以迭代数据库结果。你如何选择其中之一?看看区别:
- 数组包含数据库值的副本,可以在任何线程上使用。
- 如果获取的结果数量很多,数组可能会占用大量内存。
- 数组可以迭代多次。
- 游标以一种惰性方式迭代数据库结果,并且不会消耗太多内存。
- 游标更快,因为它们直接进入 SQLite,除非必要,否则不会复制数据库值。
- 游标不能在任何线程上使用。
- 游标只能迭代一次。
相比:
// On the main thread:
let (rowArray, rowCursor) = try dbQueue.inDatabase { db -> ([Row], DatabaseCursor<Row>) in
let rowArray = try Row.fetchAll(db, "SELECT ...")
let rowCursor = try Row.fetchCursor(db, "SELECT ...")
// OK
for row in rowArray { ... }
while let row = try rowCursor.next() { ... }
// Second iteration
for row in rowArray { ... } // the same rows
while let row = try rowCursor.next() { ... } // no result
return (rowArray, rowCursor)
}
// OK: arrays can be consumed on any thread
for row in rowArray { ... }
DispatchQueue.global(.default).async {
for row in rowArray { ... }
}
// DON'T DO THAT, NEVER
while let row = try rowCursor.next() { ... }
DispatchQueue.global(.default).async {
while let row = try rowCursor.next() { ... }
}
如果您看不到或不关心差异,请使用数组。如果您关心内存和性能,请在适当的时候使用游标。
文档链接:https ://github.com/groue/GRDB.swift/blob/master/README.md#fetching-methods