Sqlite Foreign Keys

SQLite: Foreign Keys

This SQLite post explains how to use Foreign Keys in SQLite with syntax and examples.

What is a Foreign Key in SQLite?

A foreign key is a way to enforce referential integrity within your SQLite database. A foreign key means that values in one table must also appear in another table.

The referenced table is called the parent table while the table with the foreign key is called the child table. The foreign key in the child table will generally reference a primary key in the parent table.

A foreign key can only be defined in a CREATE TABLE statement.

TIP: You can not add a foreign key to a table using ALTER TABLE because SQLite does not support ADD CONSTRAINT in the ALTER TABLE statement. However, we will show you a workaround later in this tutorial that will allow you to add a foreign key to an existing table.

How to Create a Foreign Key using the CREATE TABLE Statement

Syntax

The syntax to create a foreign key using a CREATE TABLE statement in SQLite is:

CREATE TABLE table_name
(
  column1 datatype [ NULL | NOT NULL ],
  column2 datatype [ NULL | NOT NULL ],
  ...

  CONSTRAINT fk_column
    FOREIGN KEY (column1, column2, ... column_n)
    REFERENCES parent_table (column1, column2, ... column_n)
);

Example

Let's look at an example of how to create a foreign key using the CREATE TABLE statement in SQLite.

For example:

CREATE TABLE departments
( department_id INTEGER PRIMARY KEY AUTOINCREMENT,
  department_name VARCHAR
);

CREATE TABLE employees
( employee_id INTEGER PRIMARY KEY AUTOINCREMENT,
  last_name VARCHAR NOT NULL,
  first_name VARCHAR,
  department_id INTEGER,
  CONSTRAINT fk_departments
    FOREIGN KEY (department_id)
    REFERENCES departments(department_id)
);

In this example, we've created a primary key on the departments table that consists of only one field - the department_id field. Then we've created a foreign key called fk_departments on the employees table that references the departments table based on the department_id field.

How to Add a Foreign Key to an Existing Table

You can not use the ALTER TABLE statement to add a foreign key in SQLite. Instead you will need to rename the table, create a new table with the foreign key, and then copy the data into the new table.

Syntax

The syntax to add a foreign key to an existing table in SQLite is:

PRAGMA foreign_keys=off;

BEGIN TRANSACTION;

ALTER TABLE table1 RENAME TO _table1_old;

CREATE TABLE table1
(
  column1 datatype [ NULL | NOT NULL ],
  column2 datatype [ NULL | NOT NULL ],
  ...

  CONSTRAINT fk_column
    FOREIGN KEY (column1, column2, ... column_n)
    REFERENCES parent_table (column1, column2, ... column_n)
);

INSERT INTO table1 SELECT * FROM _table1_old;

COMMIT;

PRAGMA foreign_keys=on;

Example

First, let's start by creating our 2 tables (departments and employees):

CREATE TABLE departments
( department_id INTEGER PRIMARY KEY AUTOINCREMENT,
  department_name VARCHAR
);

CREATE TABLE employees
( employee_id INTEGER PRIMARY KEY AUTOINCREMENT,
  last_name VARCHAR NOT NULL,
  first_name VARCHAR,
  department_id INTEGER
);

Next, let's add some data to these tables:

INSERT INTO departments VALUES (30, 'HR');
INSERT INTO departments VALUES (999, 'Sales');

INSERT INTO employees VALUES (10000, 'Smith', 'John', 30);
INSERT INTO employees VALUES (10001, 'Mark', 'Dave', 999);

Now, let's add a foreign key to the employees table:

PRAGMA foreign_keys=off;

BEGIN TRANSACTION;

ALTER TABLE employees RENAME TO _employees_old;

CREATE TABLE employees
( employee_id INTEGER PRIMARY KEY AUTOINCREMENT,
  last_name VARCHAR NOT NULL,
  first_name VARCHAR,
  department_id INTEGER,
  CONSTRAINT fk_departments
    FOREIGN KEY (department_id)
    REFERENCES departments(department_id)
);

INSERT INTO employees SELECT * FROM _employees_old;

COMMIT;

PRAGMA foreign_keys=on;

This example will rename our existing employees table to _employees_old. Then it will create the new employees table with a foreign key called fk_departments that references the departments table based on the department_id field. Then it will insert all of the data from the _employees_old table into the employees table.

This workaround allows you to add a foreign key to the employees table without losing the data in the table.