读书人

SQLite Foreign Key Support -sqlite3

发布时间: 2012-07-05 07:59:18 作者: rapoo

SQLite Foreign Key Support --sqlite3.6.19--from sqlite.org

Table Of Contents1. Introduction to Foreign Key Constraints2. Enabling Foreign Key Support3. Required and Suggested Database Indexes4. Advanced Foreign Key Constraint Features4.1. Composite Foreign Key Constraints4.2. Deferred Foreign Key Constraints4.3. ON DELETE and ON UPDATE Actions5. CREATE, ALTER and DROP TABLE commands6. Limits and Unsupported Features

Overview

This document describes the support for SQL foreign key constraints introduced in SQLite version 3.6.19.

The first section introduces the concept of an SQL foreign key by example and defines the terminology used for the remainder of the document. Section 2 describes the steps an application must take in order to enable foreign key constraints in SQLite (it is disabled by default). The next section, section 3, describes the indexes that the user must create in order to use foreign key constraints, and those that should be created in order for foreign key constraints to function efficiently. Section 4 describes the advanced foreign key related features supported by SQLite and section 5 describes the way the?ALTER?andDROP TABLE?commands are enhanced to support foreign key constraints. Finally, section 6 enumerates the missing features and limits of the current implementation.

This document does not contain a full description of the syntax used to create foreign key constraints in SQLite. This may be found as part of the documentation for the?CREATE TABLE?statement.

1. Introduction to Foreign Key Constraints

SQL foreign key constraints are used to enforce "exists" relationships between tables. For example, consider a database schema created using the following SQL commands:

CREATE TABLE artist(  artistid    INTEGER PRIMARY KEY,   artistname  TEXT);CREATE TABLE track(  trackid     INTEGER,  trackname   TEXT,   trackartist INTEGER     -- Must map to an artist.artistid!);

The applications using this database are entitled to assume that for each row in the?track?table there exists a corresponding row in the?artist?table. After all, the comment in the declaration says so. Unfortunately, if a user edits the database using an external tool or if there is a bug in an application, rows might be inserted into the?track?table that do not correspond to any row in the?artisttable. Or rows might be deleted from the?artist?table, leaving orphaned rows in the?track?table that do not correspond to any of the remaining rows in?artist. This might cause the application or applications to malfunction later on, or at least make coding the application more difficult.

One solution is to add an SQL foreign key constraint to the database schema to enforce the relationship between the?artist?and?track?table. To do so, a foreign key definition may be added by modifying the declaration of the?track?table to the following:

CREATE TABLE track(  trackid     INTEGER,   trackname   TEXT,   trackartist INTEGER,  FOREIGN KEY(trackartist) REFERENCES artist(artistid));

This way, the constraint is enforced by SQLite. Attempting to insert a row into the?track?table that does not correspond to any row in the?artist?table will fail, as will attempting to delete a row from the?artist?table when there exist dependent rows in the?track?table There is one exception: if the foreign key column in the?track?table is NULL, then no corresponding entry in the?artist?table is required. Expressed in SQL, this means that for every row in the?track?table, the following expression evaluates to true:

trackartist IS NULL OR EXISTS(SELECT 1 FROM artist WHERE artistid=trackartist)

Tip: If the application requires a stricter relationship between?artist?and?track, where NULL values are not permitted in the?trackartist?column, simply add the appropriate "NOT NULL" constraint to the schema.

There are several other ways to add an equivalent foreign key declaration to aCREATE TABLE?statement. Refer to the?CREATE TABLE documentation?for details.

The following SQLite command-line session illustrates the effect of the foreign key constraint added to the?track?table:

sqlite> SELECT * FROM artist;artistid  artistname       --------  -----------------1         Dean Martin      2         Frank Sinatra    sqlite> SELECT * FROM track;trackid  trackname          trackartist-------  -----------------  -----------11       That's Amore       1  12       Christmas Blues    1  13       My Way             2  sqlite> -- This fails because the value inserted into the trackartist column (3)sqlite> -- does not correspond to row in the artist table.sqlite> INSERT INTO track VALUES(14, 'Mr. Bojangles', 3);SQL error: foreign key constraint failedsqlite> -- This succeeds because a NULL is inserted into trackartist. Asqlite> -- corresponding row in the artist table is not required in this case.sqlite> INSERT INTO track VALUES(14, 'Mr. Bojangles', NULL);sqlite> -- Trying to modify the trackartist field of the record after it has sqlite> -- been inserted does not work either, since the new value of trackartist (3)sqlite> -- Still does not correspond to any row in the artist table.sqlite> UPDATE track SET trackartist = 3 WHERE trackname = 'Mr. Bojangles';SQL error: foreign key constraint failedsqlite> -- Insert the required row into the artist table. It is then possible tosqlite> -- update the inserted row to set trackartist to 3 (since a correspondingsqlite> -- row in the artist table now exists).sqlite> INSERT INTO artist VALUES(3, 'Sammy Davis Jr.');sqlite> UPDATE track SET trackartist = 3 WHERE trackname = 'Mr. Bojangles';sqlite> -- Now that "Sammy Davis Jr." (artistid = 3) has been added to the database,sqlite> -- it is possible to INSERT new tracks using this artist without violatingsqlite> -- the foreign key constraint:sqlite> INSERT INTO track VALUES(15, 'Boogie Woogie', 3);

As you would expect, it is not possible to manipulate the database to a state that violates the foreign key constraint by deleting or updating rows in the?artisttable either:

sqlite> -- Attempting to delete the artist record for "Frank Sinatra" fails, sincesqlite> -- the track table contains a row that refer to it.sqlite> DELETE FROM artist WHERE artistname = 'Frank Sinatra';SQL error: foreign key constraint failedsqlite> -- Delete all the records from the track table that refer to the artistsqlite> -- "Frank Sinatra". Only then is it possible to delete the artist.sqlite> DELETE FROM track WHERE trackname = 'My Way';sqlite> DELETE FROM artist WHERE artistname = 'Frank Sinatra';sqlite> -- Try to update the artistid of a row in the artist table while theresqlite> -- exists records in the track table that refer to it. sqlite> UPDATE artist SET artistid=4 WHERE artistname = 'Dean Martin';SQL error: foreign key constraint failedsqlite> -- Once all the records that refer to a row in the artist table havesqlite> -- been deleted, it is possible to modify the artistid of the row.sqlite> DELETE FROM track WHERE trackname IN('That''s Amore', 'Christmas Blues');sqlite> UPDATE artist SET artistid=4 WHERE artistname = 'Dean Martin';

SQLite uses the following terminology:

读书人网 >SQL Server

热点推荐