You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
SQLite directly supports a [set of schema alterations](https://www.sqlite.org/lang.html). Many of them are available as `Database` methods such as ``Database/create(table:options:body:)``, ``Database/alter(table:body:)``, listed below.
8
+
9
+
You can directly create tables when you open a database, as below:
10
+
11
+
```swift
12
+
let dbQueue =tryDatabaseQueue(path: "/path/to/database.sqlite")
13
+
14
+
try dbQueue.write { db in
15
+
try db.create(table: "player", options: .ifNotExists) { t in
16
+
t.autoIncrementedPrimaryKey("id")
17
+
t.column("name", .text).notNull()
18
+
t.column("score", .integer).notNull()
19
+
}
20
+
}
21
+
```
22
+
23
+
But you should prefer wrapping your schema changes in <doc:Migrations> when you plan to upgrade the database schema in future versions of your app.
24
+
25
+
> Tip: When modifying the database schema, prefer Swift APIs over raw SQL queries. This helps the compiler check if features are available on the SQLite version that ships on the target operating system. For example:
> When you need to perform a schema change that is not directly supported, or not available, you will sometimes need to recreate database tables. See <doc:Migrations> for the detailed procedure.
Copy file name to clipboardExpand all lines: GRDB/Documentation.docc/Migrations.md
+16-16Lines changed: 16 additions & 16 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -83,13 +83,13 @@ try dbQueue.read { db in
83
83
84
84
**The memory of applied migrations is stored in the database itself** (in a reserved table).
85
85
86
-
## Defining the Database Schema
86
+
## Defining the Database Schema from a Migration
87
87
88
-
SQLite directly supports a [limited set of schema alterations](https://www.sqlite.org/lang.html). Many of them are available as `Database`methods such as ``Database/create(table:options:body:)``, ``Database/alter(table:body:)``, etc.
88
+
See <doc:DatabaseSchema> for the methods that define the database schema.
89
89
90
-
> Tip: When you use a Swift API instead of a raw SQL query, GRDB can check its availability on the SQLite version that ships on the target operating system.
90
+
When you need to perform a schema change that is not directly supported by SQLite, or not available on your target operating system, you will need to recreate database tables.
91
91
92
-
Other changes to the schema are still possible, by recreating tables. For example:
92
+
For example:
93
93
94
94
```swift
95
95
migrator.registerMigration("Add NOT NULL check on author.name") { db in
@@ -104,25 +104,25 @@ migrator.registerMigration("Add NOT NULL check on author.name") { db in
104
104
}
105
105
```
106
106
107
-
This technique is described in the [Making Other Kinds Of Table Schema Changes](https://www.sqlite.org/lang_altertable.html#making_other_kinds_of_table_schema_changes) section of the SQLite documentation.
107
+
The detailed sequence of operations for recreating a database table from a migration is:
108
108
109
-
The detailed sequence of operations for recreating a database table is:
110
-
111
-
1. Remember the format of all indexes, triggers, and views associated with table X. This information will be needed in step 5 below. One way to do this is to run a query like the following: `SELECT type, sql FROM sqlite_schema WHERE tbl_name='X'`.
109
+
1. When relevant, remember the format of all indexes, triggers, and views associated with table X. This information will be needed in steps 6 and 7 below. One way to do this is to run a query like the following: `SELECT type, sql FROM sqlite_schema WHERE tbl_name='X'`.
112
110
113
111
2. Use `CREATE TABLE` to construct a new table "new_X" that is in the desired revised format of table X. Make sure that the name "new_X" does not collide with any existing table name, of course.
114
112
115
-
2. Transfer content from X into new_X using a statement like: `INSERT INTO new_X SELECT ... FROM X`.
113
+
3. Transfer content from X into new_X using a statement like: `INSERT INTO new_X SELECT ... FROM X`.
116
114
117
-
3. Drop the old table X: `DROP TABLE X`.
115
+
4. Drop the old table X: `DROP TABLE X`.
118
116
119
-
4. Change the name of new_X to X using: `ALTER TABLE new_X RENAME TO X`.
117
+
5. Change the name of new_X to X using: `ALTER TABLE new_X RENAME TO X`.
120
118
121
-
5. Use`CREATE INDEX`, `CREATE TRIGGER`, and `CREATE VIEW` to reconstruct indexes, triggers, and views associated with table X. Perhaps use the old format of the triggers, indexes, and views saved from step 3 above as a guide, making changes as appropriate for the alteration.
119
+
6. When relevant, use`CREATE INDEX`, `CREATE TRIGGER`, and `CREATE VIEW` to reconstruct indexes, triggers, and views associated with table X. Perhaps use the old format of the triggers, indexes, and views saved from step 3 above as a guide, making changes as appropriate for the alteration.
122
120
123
-
6. If any views refer to table X in a way that is affected by the schema change, then drop those views using `DROP VIEW` and recreate them with whatever changes are necessary to accommodate the schema change using `CREATE VIEW`.
121
+
7. If any views refer to table X in a way that is affected by the schema change, then drop those views using `DROP VIEW` and recreate them with whatever changes are necessary to accommodate the schema change using `CREATE VIEW`.
124
122
125
123
> Important: When recreating a table, be sure to follow the above procedure exactly, in the given order, or you might corrupt triggers, views, and foreign key constraints.
124
+
>
125
+
> When you want to recreate a table _outside of a migration_, check the full procedure detailed in the [Making Other Kinds Of Table Schema Changes](https://www.sqlite.org/lang_altertable.html#making_other_kinds_of_table_schema_changes) section of the SQLite documentation.
126
126
127
127
## Good Practices for Defining Migrations
128
128
@@ -148,7 +148,7 @@ migrator.registerMigration("Create authors") { db in
148
148
149
149
In other words, migrations should talk to the database, only to the database, and use the database language. This makes sure the Swift code of any given migrations will never have to change in the future.
150
150
151
-
Migrations and the rest of the application code do not live at the same "moment". Migrations describe the past states of the database, while the rest of the application code targets the latest one only. This difference is the reason why migrations should not depend on application types.
151
+
Migrations and the rest of the application code do not live at the same "moment". Migrations describe the past states of the database, while the rest of the application code targets the latest one only. This difference is the reason why **migrations should not depend on application types.**
152
152
153
153
## The eraseDatabaseOnSchemaChange Option
154
154
@@ -187,7 +187,7 @@ When you register a migration with `.immediate` foreign key checks, the migratio
187
187
migrator.registerMigration("Faster migration", foreignKeyChecks: .immediate) { db in... }
188
188
```
189
189
190
-
Such a migration is much faster, and it still guarantees database integrity. But it must only execute schema alterations directly supported by SQLite. Migrations that recreate tables as described in <doc:Migrations#Defining-the-Database-Schema>**must not** run with immediate foreign keys checks. You'll need to use the second mitigation technique:
190
+
Such a migration is much faster, and it still guarantees database integrity. But it must only execute schema alterations directly supported by SQLite. Migrations that recreate tables as described in <doc:Migrations#Defining-the-Database-Schema-from-a-Migration>**must not** run with immediate foreign keys checks. You'll need to use the second mitigation technique:
191
191
192
192
**Your second mitigation technique is to disable deferred foreign key checks.**
In order to prevent foreign key violations from being committed to disk, you can:
203
203
204
-
- Register migrations with immediate foreign key checks, as long as they do not recreate tables as described in <doc:Migrations#Defining-the-Database-Schema>:
204
+
- Register migrations with immediate foreign key checks, as long as they do not recreate tables as described in <doc:Migrations#Defining-the-Database-Schema-from-a-Migration>:
0 commit comments