A project defines its schema once, as a named list of CREATE TABLE
statements whose column comments are the data dictionary (see
schema_dictionary()). create_schema() creates the tables that do not
exist yet and, since CREATE TABLE IF NOT EXISTS never changes an
existing table, adds the columns introduced after a table was first
created.
Arguments
- con
A DBI connection with write access.
- schema
Named list of character strings: one
CREATE TABLE IF NOT EXISTSstatement per table, named after the table.- added_columns
Named list or
NULL. For each table, a named character vectorc(column = "TYPE")of columns to add if they are missing (migration of databases created with an older schema).
Details
The recommended layout, learnt from the author's database projects:
one database file per project as the single source of truth;
singular table names, every table linked to
documentbydoc_id(<source>:<identifier in the source>, seemake_doc_id());no
PRIMARY KEYconstraint: DuckDB checks it eagerly, which makes a "delete then insert" update fail inside one transaction. Uniqueness is checked in R before writing (check_unique()) and in the sanity check.
Examples
schema <- list(
document = "
CREATE TABLE IF NOT EXISTS document (
doc_id VARCHAR, -- <source>:<source_id>
source VARCHAR, -- collection the record comes from
title VARCHAR
)"
)
con <- db_connect(tempfile(fileext = ".duckdb"))
#> duckdb is storing downloaded extensions and secrets under ~/.duckdb:
#> ℹ /home/agoutsmedt/.duckdb
#> This persists across sessions and is shared with the DuckDB CLI and other clients.
#> ℹ Run duckdb(shared_home = FALSE) to use a temporary directory instead.
#> ℹ See ?duckdb_storage for details and alternatives.
create_schema(con, schema, added_columns = list(document = c(year = "INTEGER")))
#> ℹ document: added column year.
DBI::dbListFields(con, "document")
#> [1] "doc_id" "source" "title" "year"
db_disconnect(con)