danielk1977 | c30bfee | 2008-10-10 17:58:26 +0000 | [diff] [blame] | 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 |
danielk1977 | e632004 | 2009-02-25 15:43:57 +0000 | [diff] [blame] | 7 | implemented using SQL triggers, which SQLite does support. This text |
| 8 | file describes a feature of the SQLite shell tool (sqlite3) that |
danielk1977 | c30bfee | 2008-10-10 17:58:26 +0000 | [diff] [blame] | 9 | extracts foreign key definitions from an existing SQLite database and |
danielk1977 | e632004 | 2009-02-25 15:43:57 +0000 | [diff] [blame] | 10 | creates the set of CREATE TRIGGER statements required to implement |
danielk1977 | c30bfee | 2008-10-10 17:58:26 +0000 | [diff] [blame] | 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. |
danielk1977 | c30bfee | 2008-10-10 17:58:26 +0000 | [diff] [blame] | 94 | |
| 95 | USAGE |
| 96 | |
danielk1977 | e632004 | 2009-02-25 15:43:57 +0000 | [diff] [blame] | 97 | The functionality is accessed through an sqlite3 shell tool "dot-command": |
danielk1977 | c30bfee | 2008-10-10 17:58:26 +0000 | [diff] [blame] | 98 | |
danielk1977 | e632004 | 2009-02-25 15:43:57 +0000 | [diff] [blame] | 99 | .genfkey ?--no-drop? ?--ignore-errors? ?--exec? |
| 100 | |
| 101 | When this command is run, it first checks the schema of the open SQLite |
danielk1977 | c30bfee | 2008-10-10 17:58:26 +0000 | [diff] [blame] | 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 |
danielk1977 | e632004 | 2009-02-25 15:43:57 +0000 | [diff] [blame] | 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. |
danielk1977 | c30bfee | 2008-10-10 17:58:26 +0000 | [diff] [blame] | 108 | |
danielk1977 | e632004 | 2009-02-25 15:43:57 +0000 | [diff] [blame] | 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. |
danielk1977 | c30bfee | 2008-10-10 17:58:26 +0000 | [diff] [blame] | 113 | |
danielk1977 | e632004 | 2009-02-25 15:43:57 +0000 | [diff] [blame] | 114 | All triggers generated by this command have names that match the pattern |
danielk1977 | c30bfee | 2008-10-10 17:58:26 +0000 | [diff] [blame] | 115 | "genfkey*". Unless the --no-drop option is specified, then the program |
danielk1977 | e632004 | 2009-02-25 15:43:57 +0000 | [diff] [blame] | 116 | also generates a "DROP TRIGGER" statement for each trigger that exists |
danielk1977 | c30bfee | 2008-10-10 17:58:26 +0000 | [diff] [blame] | 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). |
danielk1977 | e632004 | 2009-02-25 15:43:57 +0000 | [diff] [blame] | 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 |
danielk1977 | c30bfee | 2008-10-10 17:58:26 +0000 | [diff] [blame] | 137 | |