| OLD | NEW |
| (Empty) |
| 1 | |
| 2 OVERVIEW | |
| 3 | |
| 4 The SQLite library is capable of parsing SQL foreign key constraints | |
| 5 supplied as part of CREATE TABLE statements, but it does not actually | |
| 6 implement them. However, most of the features of foreign keys may be | |
| 7 implemented using SQL triggers, which SQLite does support. This text | |
| 8 file describes a feature of the SQLite shell tool (sqlite3) that | |
| 9 extracts foreign key definitions from an existing SQLite database and | |
| 10 creates the set of CREATE TRIGGER statements required to implement | |
| 11 the foreign key constraints. | |
| 12 | |
| 13 CAPABILITIES | |
| 14 | |
| 15 An SQL foreign key is a constraint that requires that each row in | |
| 16 the "child" table corresponds to a row in the "parent" table. For | |
| 17 example, the following schema: | |
| 18 | |
| 19 CREATE TABLE parent(a, b, c, PRIMARY KEY(a, b)); | |
| 20 CREATE TABLE child(d, e, f, FOREIGN KEY(d, e) REFERENCES parent(a, b)); | |
| 21 | |
| 22 implies that for each row in table "child", there must be a row in | |
| 23 "parent" for which the expression (child.d==parent.a AND child.e==parent.b) | |
| 24 is true. The columns in the parent table are required to be either the | |
| 25 primary key columns or subject to a UNIQUE constraint. There is no such | |
| 26 requirement for the columns of the child table. | |
| 27 | |
| 28 At this time, all foreign keys are implemented as if they were | |
| 29 "MATCH NONE", even if the declaration specified "MATCH PARTIAL" or | |
| 30 "MATCH FULL". "MATCH NONE" means that if any of the key columns in | |
| 31 the child table are NULL, then there is no requirement for a corresponding | |
| 32 row in the parent table. So, taking this into account, the expression that | |
| 33 must be true for every row of the child table in the above example is | |
| 34 actually: | |
| 35 | |
| 36 (child.d IS NULL) OR | |
| 37 (child.e IS NULL) OR | |
| 38 (child.d==parent.a AND child.e==parent.b) | |
| 39 | |
| 40 Attempting to insert or update a row in the child table so that the | |
| 41 affected row violates this constraint results in an exception being | |
| 42 thrown. | |
| 43 | |
| 44 The effect of attempting to delete or update a row in the parent table | |
| 45 so that the constraint becomes untrue for one or more rows in the child | |
| 46 table depends on the "ON DELETE" or "ON UPDATE" actions specified as | |
| 47 part of the foreign key definition, respectively. Three different actions | |
| 48 are supported: "RESTRICT" (the default), "CASCADE" and "SET NULL". SQLite | |
| 49 will also parse the "SET DEFAULT" action, but this is not implemented | |
| 50 and "RESTRICT" is used instead. | |
| 51 | |
| 52 RESTRICT: Attempting to update or delete a row in the parent table so | |
| 53 that the constraint becomes untrue for one or more rows in | |
| 54 the child table is not allowed. An exception is thrown. | |
| 55 | |
| 56 CASCADE: Instead of throwing an exception, all corresponding child table | |
| 57 rows are either deleted (if the parent row is being deleted) | |
| 58 or updated to match the new parent key values (if the parent | |
| 59 row is being updated). | |
| 60 | |
| 61 SET NULL: Instead of throwing an exception, the foreign key fields of | |
| 62 all corresponding child table rows are set to NULL. | |
| 63 | |
| 64 LIMITATIONS | |
| 65 | |
| 66 Apart from those limitiations described above: | |
| 67 | |
| 68 * Implicit mapping to composite primary keys is not supported. If | |
| 69 a parent table has a composite primary key, then any child table | |
| 70 that refers to it must explicitly map each column. For example, given | |
| 71 the following definition of table "parent": | |
| 72 | |
| 73 CREATE TABLE parent(a, b, c, PRIMARY KEY(a, b)); | |
| 74 | |
| 75 only the first of the following two definitions of table "child" | |
| 76 is supported: | |
| 77 | |
| 78 CREATE TABLE child(d, e, f, FOREIGN KEY(d, e) REFERENCES parent(a, b)); | |
| 79 CREATE TABLE child(d, e, f, FOREIGN KEY(d, e) REFERENCES parent); | |
| 80 | |
| 81 An implicit reference to a composite primary key is detected as an | |
| 82 error when the program is run (see below). | |
| 83 | |
| 84 * SQLite does not support recursive triggers, and therefore this program | |
| 85 does not support recursive CASCADE or SET NULL foreign key | |
| 86 relationships. If the parent and the child tables of a CASCADE or | |
| 87 SET NULL foreign key are the same table, the generated triggers will | |
| 88 malfunction. This is also true if the recursive foreign key constraint | |
| 89 is indirect (for example if table A references table B which references | |
| 90 table A with a CASCADE or SET NULL foreign key constraint). | |
| 91 | |
| 92 Recursive CASCADE or SET NULL foreign key relationships are *not* | |
| 93 detected as errors when the program is run. Buyer beware. | |
| 94 | |
| 95 USAGE | |
| 96 | |
| 97 The functionality is accessed through an sqlite3 shell tool "dot-command": | |
| 98 | |
| 99 .genfkey ?--no-drop? ?--ignore-errors? ?--exec? | |
| 100 | |
| 101 When this command is run, it first checks the schema of the open SQLite | |
| 102 database for foreign key related errors or inconsistencies. For example, | |
| 103 a foreign key that refers to a parent table that does not exist, or | |
| 104 a foreign key that refers to columns in a parent table that are not | |
| 105 guaranteed to be unique. If such errors are found and the --ignore-errors | |
| 106 option was not present, a message for each one is printed to stderr and | |
| 107 no further processing takes place. | |
| 108 | |
| 109 If errors are found and the --ignore-errors option is passed, then | |
| 110 no error messages are printed. No "CREATE TRIGGER" statements are generated | |
| 111 for foriegn-key definitions that contained errors, they are silently | |
| 112 ignored by subsequent processing. | |
| 113 | |
| 114 All triggers generated by this command have names that match the pattern | |
| 115 "genfkey*". Unless the --no-drop option is specified, then the program | |
| 116 also generates a "DROP TRIGGER" statement for each trigger that exists | |
| 117 in the database with a name that matches this pattern. This allows the | |
| 118 program to be used to upgrade a database schema for which foreign key | |
| 119 triggers have already been installed (i.e. after new tables are created | |
| 120 or existing tables dropped). | |
| 121 | |
| 122 Finally, a series of SQL trigger definitions (CREATE TRIGGER statements) | |
| 123 that implement the foreign key constraints found in the database schema are | |
| 124 generated. | |
| 125 | |
| 126 If the --exec option was passed, then all generated SQL is immediately | |
| 127 executed on the database. Otherwise, the generated SQL strings are output | |
| 128 in the same way as the results of SELECT queries are. Normally, this means | |
| 129 they will be printed to stdout, but this can be configured using other | |
| 130 dot-commands (i.e. ".output"). | |
| 131 | |
| 132 The simplest way to activate the foriegn key definitions in a database | |
| 133 is simply to open it using the shell tool and enter the command | |
| 134 ".genfkey --exec": | |
| 135 | |
| 136 sqlite> .genfkey --exec | |
| 137 | |
| OLD | NEW |