GRDB Stories
The little things that make the SQLite library GRDB.swift different.
You are free to shape your database as you want, and today we’ll talk about primary keys.
You know, a primary key is a dedicated set of columns in a database table that uniquely identifies rows. The most commonly used primary key is a auto-incremented column “id”:
try db.create(table: "person") { t in
t.autoIncrementedPrimaryKey("id")
t.column("name", .text)
}
But this id is not always the best fit. For example, a country is better identified by its ISO 3166–1 code, and a citizenship is naturally defined as a pair (person, country):
try db.create(table: "country") { t in
t.column("isoCode", .text).primaryKey()
t.column("name", .text)
}try db.create(table: "citizenship") { t in
t.column("personId", .integer)
.references("person", onDelete: .cascade)
t.column("countryIsoCode", .text)
.references("country", onDelete: .cascade)
t.primaryKey(["personId", "countryIsoCode"])
}
Now if you define dedicated Records for each one of those tables…
class Person: Record { ... }
class Country: Record { ... }
class Citizenship: Record { ... }
…GRDB looks at the database schema and uses the correct primary key when it generates SQL statements for you:
let person = Person.fetchOne(db, key: 1)
let country = Country.fetchOne(db, key: "FR")
let citizenship = Citizenship(person: person, country: country)
try citizenship.insert(db)
try citizenship.delete(db)