Table
Table
can build query interface requests.
// SELECT * FROM player WHERE score >= 1000
let table = Table("player")
let rows: [Row] = try dbQueue.read { db in
table.all()
.filter(Column("score") >= 1000)
.fetchAll(db)
}
-
The table name
-
Create a
Table
let table = Table<Row>("player") let table = Table<Player>("player")
-
-
Creates a request for all rows of the table.
// Fetch all players let table = Table<Player>("player") let request = table.all() let players: [Player] = try request.fetchAll(db)
-
Creates a request which fetches no row.
// Fetch no players let table = Table<Player>("player") let request = table.none() let players: [Player] = try request.fetchAll(db) // Empty array
-
Creates a request which selects selection.
// SELECT id, email FROM player let table = Table("player") let request = table.select(Column("id"), Column("email"))
-
Creates a request which selects sql.
// SELECT id, email FROM player let table = Table("player") let request = table.select(sql: "id, email")
-
Creates a request which selects an SQL literal.
Literals allow you to safely embed raw values in your SQL, without any risk of syntax errors or SQL injection:
// SELECT id, email, score + 1000 FROM player let table = Table("player") let bonus = 1000 let request = table.select(literal: """ id, email, score + \(bonus) """)
-
Creates a request which selects selection, and fetches values of type type.
try dbQueue.read { db in // SELECT max(score) FROM player let table = Table("player") let request = table.select([max(Column("score"))], as: Int.self) let maxScore: Int? = try request.fetchOne(db) }
-
Creates a request which selects sql, and fetches values of type type.
try dbQueue.read { db in // SELECT max(score) FROM player let table = Table("player") let request = table.select(sql: "max(score)", as: Int.self) let maxScore: Int? = try request.fetchOne(db) }
-
Creates a request which selects an SQL literal, and fetches values of type type.
Literals allow you to safely embed raw values in your SQL, without any risk of syntax errors or SQL injection:
// SELECT IFNULL(name, 'Anonymous') FROM player let table = Table("player") let defaultName = "Anonymous" let request = table.select( literal: "IFNULL(name, \(defaultName))", as: String.self) let name: String? = try request.fetchOne(db)
-
Creates a request which appends selection.
// SELECT id, email, name FROM player let table = Table("player") let request = table .select([Column("id"), Column("email")]) .annotated(with: [Column("name")])
-
Creates a request with the provided predicate.
// SELECT * FROM player WHERE email = 'arthur@example.com' let table = Table<Player>("player") let request = table.filter(Column("email") == "arthur@example.com")
-
Creates a request with the provided primary key predicate.
// SELECT * FROM player WHERE id = 1 let table = Table<Player>("player") let request = table.filter(key: 1)
-
Creates a request with the provided primary key predicate.
// SELECT * FROM player WHERE id IN (1, 2, 3) let table = Table<Player>("player") let request = table.filter(keys: [1, 2, 3])
-
Creates a request with the provided predicate.
// SELECT * FROM player WHERE email = 'arthur@example.com' let table = Table<Player>("player") let request = table.filter(sql: "email = ?", arguments: ["arthur@example.com"])
-
Creates a request with the provided predicate added to the eventual set of already applied predicates.
Literals allow you to safely embed raw values in your SQL, without any risk of syntax errors or SQL injection:
// SELECT * FROM player WHERE name = 'O''Brien' let table = Table<Player>("player") let name = "O'Brien" let request = table.filter(literal: "email = \(email)")
-
Creates a request sorted according to the provided orderings.
// SELECT * FROM player ORDER BY name let table = Table<Player>("player") let request = table.order(Column("name"))
-
Creates a request sorted by primary key.
// SELECT * FROM player ORDER BY id let table = Table<Player>("player") let request = table.orderByPrimaryKey() // SELECT * FROM country ORDER BY code let request = Country.orderByPrimaryKey()
-
Creates a request sorted according to sql.
// SELECT * FROM player ORDER BY name let table = Table<Player>("player") let request = table.order(sql: "name")
-
Creates a request sorted according to an SQL literal.
// SELECT * FROM player ORDER BY name let table = Table<Player>("player") let request = table.order(literal: "name")
-
Creates a request which fetches limit rows, starting at offset.
// SELECT * FROM player LIMIT 1 let table = Table<Player>("player") let request = table.limit(1)
-
Creates a request that allows you to define expressions that target a specific database table.
See
TableRecord.aliased(_:)
for more information. -
Returns a request which embeds the common table expression.
See
TableRecord.with(_:)
for more information. -
Creates a request which selects the primary key.
All primary keys are supported:
// SELECT id FROM player let table = Table("player") let request = try table.selectPrimaryKey(as: Int64.self) // SELECT code FROM country let table = Table("country") let request = try table.selectPrimaryKey(as: String.self) // SELECT citizenId, countryCode FROM citizenship let table = Table("citizenship") let request = try table.selectPrimaryKey(as: Row.self)
-
The number of rows.
-
A cursor over all records fetched from the database.
// SELECT * FROM player let table = Table<Player>("player") let players = try table.fetchCursor(db) // Cursor of Player while let player = try players.next() { // Player ... }
Records are iterated in the natural ordering of the table.
If the database is modified during the cursor iteration, the remaining elements are undefined.
The cursor must be iterated in a protected dispatch queue.
Throws
A DatabaseError is thrown whenever an SQLite error occurs. -
An array of all records fetched from the database.
// SELECT * FROM player let table = Table<Player>("player") let players = try table.fetchAll(db) // [Player]
Throws
A DatabaseError is thrown whenever an SQLite error occurs. -
The first found record.
// SELECT * FROM player LIMIT 1 let table = Table<Player>("player") let player = try table.fetchOne(db) // Player?
Throws
A DatabaseError is thrown whenever an SQLite error occurs. -
A set of all records fetched from the database.
// SELECT * FROM player let table = Table<Player>("player") let players = try table.fetchSet(db) // Set<Player>
Throws
A DatabaseError is thrown whenever an SQLite error occurs.
-
Creates a “Belongs To” association between Self and the destination type, based on a database foreign key.
For more information, see
TableRecord.belongsTo(_:key:using:)
. -
Creates a “Has many” association between Self and the destination type, based on a database foreign key.
For more information, see
TableRecord.hasMany(_:key:using:)
. -
Creates a “Has one” association between Self and the destination type, based on a database foreign key.
For more information, see
TableRecord.hasOne(_:key:using:)
.
-
Creates an association to a common table expression that you can join or include in another request.
For more information, see
TableRecord.association(to:on:)
. -
Creates an association to a common table expression that you can join or include in another request.
The key of the returned association is the table name of the common table expression.
-
Creates a “Has Many Through” association between Self and the destination type.
For more information, see
TableRecord.hasMany(_:through:using:key:)
. -
Creates a “Has One Through” association between Self and the destination type.
For more information, see
TableRecord.hasOne(_:through:using:key:)
.
-
Creates a request that prefetches an association.
-
Creates a request that includes an association. The columns of the associated record are selected. The returned association does not require that the associated database table contains a matching row.
-
Creates a request that includes an association. The columns of the associated record are selected. The returned association requires that the associated database table contains a matching row.
-
Creates a request that includes an association. The columns of the associated record are not selected. The returned association does not require that the associated database table contains a matching row.
-
Creates a request that includes an association. The columns of the associated record are not selected. The returned association requires that the associated database table contains a matching row.
-
Creates a request which appends columns of an associated record to the columns of the table.
let playerTable = Table("player") let teamTable = Table("team") let playerTeam = playerTable.belongsTo(teamTable) // SELECT player.*, team.color // FROM player LEFT JOIN team ... let teamColor = playerTeam.select(Column("color") let request = playerTable.annotated(withOptional: teamColor))
This method performs the same SQL request as
including(optional:)
. The difference is in the shape of Decodable records that decode such a request: the associated columns can be decoded at the same level as the main record:struct PlayerWithTeamColor: FetchableRecord, Decodable { var player: Player var color: String? } let players = try dbQueue.read { db in try request .asRequest(of: PlayerWithTeamColor.self) .fetchAll(db) }
Note: this is a convenience method. You can build the same request with
TableAlias
,annotated(with:)
, andjoining(optional:)
:let teamAlias = TableAlias() let request = playerTable .annotated(with: teamAlias[Column("color")]) .joining(optional: playerTeam.aliased(teamAlias))
-
Creates a request which appends columns of an associated record to the columns of the table.
let playerTable = Table("player") let teamTable = Table("team") let playerTeam = playerTable.belongsTo(teamTable) // SELECT player.*, team.color // FROM player JOIN team ... let teamColor = playerTeam.select(Column("color") let request = playerTable.annotated(withRequired: teamColor))
This method performs the same SQL request as
including(required:)
. The difference is in the shape of Decodable records that decode such a request: the associated columns can be decoded at the same level as the main record:struct PlayerWithTeamColor: FetchableRecord, Decodable { var player: Player var color: String } let players = try dbQueue.read { db in try request .asRequest(of: PlayerWithTeamColor.self) .fetchAll(db) }
Note: this is a convenience method. You can build the same request with
TableAlias
,annotated(with:)
, andjoining(required:)
:let teamAlias = TableAlias() let request = playerTable .annotated(with: teamAlias[Column("color")]) .joining(required: playerTeam.aliased(teamAlias))
-
Creates a request with the provided aggregate predicate.
// SELECT player.* // FROM player LEFT JOIN book ... // HAVING COUNT(DISTINCT book.id) = 0 let table = Table<Player>("player") var request = table.all() request = request.having(Player.books.isEmpty)
The selection defaults to all columns. This default can be changed for all requests by the
TableRecord.databaseSelection
property, or for individual requests with theTableRecord.select
method.
-
Deletes all rows, and returns the number of deleted rows.
Throws
A DatabaseError is thrown whenever an SQLite error occurs.
-
Returns whether a row exists for this primary key.
try Table("player").exists(db, key: 123) try Table("country").exists(db, key: "FR")
When the table has no explicit primary key, GRDB uses the hidden “rowid” column:
try Table("document").exists(db, key: 1)
-
Delete rows identified by their primary keys, and returns the number of deleted rows.
// DELETE FROM player WHERE id IN (1, 2, 3) try Table("player").deleteAll(db, keys: [1, 2, 3]) // DELETE FROM country WHERE code IN ('FR', 'US', 'DE') try Table("country").deleteAll(db, keys: ["FR", "US", "DE"])
When the table has no explicit primary key, GRDB uses the hidden “rowid” column:
// DELETE FROM document WHERE rowid IN (1, 2, 3) try Table("document").deleteAll(db, keys: [1, 2, 3])
-
Delete a row, identified by its primary key, and returns whether a database row was deleted.
// DELETE FROM player WHERE id = 123 try Table("player").deleteOne(db, key: 123) // DELETE FROM country WHERE code = 'FR' try Table("country").deleteOne(db, key: "FR")
When the table has no explicit primary key, GRDB uses the hidden “rowid” column:
// DELETE FROM document WHERE rowid = 1 try Table("document").deleteOne(db, key: 1)
-
Updates all rows, and returns the number of updated rows..
For example:
try dbQueue.write { db in // UPDATE player SET score = 0 try Table("player").updateAll(db, [Column("score").set(to: 0)]) }
Throws
A DatabaseError is thrown whenever an SQLite error occurs.