Foreign Key SQLite: Implementing Relationships

Understanding database relationships is key to effective data modeling. In SQLite, we can define relationships between tables using foreign keys – a column that references the primary key of another table. This enforces data integrity and consistency within the database.

In this comprehensive guide, we will walk through foreign keys in SQLite while building out an example database step-by-step. You’ll learn how to create tables, define primary keys, set up foreign key constraints, and insert related data across multiple tables.

Along the way, we’ll cover:

  • The fundamentals of relational data modeling
  • How foreign keys connect tables together
  • Syntax for defining foreign key constraints in SQLite
  • Techniques for inserting, updating, and deleting related data
  • How foreign keys help maintain data integrity
  • Options for cascading deletes and updates

Let’s get started!

Also read: SQLite Date Functions: A Comprehensive Guide

Relational Data Modeling Basics

Before diving into foreign keys, let’s quickly recap some key concepts in relational database design…

In a nutshell, relational databases store data in tabular format across multiple tables. Tables contain rows and columns similar to spreadsheets.

Key components include:

  • Tables – Contains columns and rows that store data
  • Columns – Defines details about the data
  • Rows – Single record in the table
  • Primary Key – Unique identifier for rows in a table
  • Foreign Key – Column that links data between tables

Benefits of this approach:

  • Structured organization of data
  • Reduced data redundancy
  • Enforced data integrity
  • Flexible querying of related data

But how do we connect these tables together to build relationships? This is where foreign keys come in!

Foreign Keys Explained

foreign key is a column that establishes a link between two tables. It acts as a cross-reference between tables by matching the value of one column (typically the primary key) in one table to another column in a different table.

For example, an orders table might have a customer_id column that references the customer_id primary key on the customers table. This connects orders to the customer that placed them.

The table containing the foreign key is called the child table. The table that contains the referenced column (usually the primary key) is called the parent table. This establishes a clear hierarchy between the two tables.

In practice, foreign keys enforce referential integrity constraints on relationships. This ensures:

  • Child records always reference a valid parent record
  • Deleting parent records cascades to child records
  • Prevents orphan records and inconsistencies

Next let’s see how to implement foreign keys when creating SQLite tables…

Creating Tables with Foreign Keys in SQLite

We will model a simple e-commerce database with products, orders, and customers tables connected via foreign keys.

-- Parent table 
CREATE TABLE products (
  product_id INTEGER PRIMARY KEY,
  name TEXT, 
  price NUMERIC
);

-- Child table
CREATE TABLE orders (
  order_id INTEGER PRIMARY KEY, 
  product_id INTEGER,
  quantity INTEGER,  
  FOREIGN KEY(product_id) REFERENCES products(product_id) 
);

-- Parent table
CREATE TABLE customers (
  customer_id INTEGER PRIMARY KEY,
  first_name TEXT,
  last_name TEXT
);  

-- Child table 
CREATE TABLE orders (
  order_id INTEGER PRIMARY KEY,
  customer_id INTEGER,
  order_date TEXT,
  FOREIGN KEY(customer_id) REFERENCES customers(customer_id)
);

Let’s break this down…

We first created a products table with a primary key product_id column for uniquely identifying rows.

Next we defined an orders table with a product_id column intended to reference the products table.

We configured this foreign key relationship using:

FOREIGN KEY(product_id) REFERENCES products(product_id)

This ensures all product_id values in the orders table refers to a valid product record. This is our parent-child relationship between the tables.

Similarly, we created customers and orders tables with a foreign key defined from orders → customers linking related data.

Key Takeaways:

  • Child tables contain foreign keys, parent tables contain referenced primary key
  • REFERENCES defines table and column being referenced
  • Enforces data consistency between tables

Now let’s look at how we can work with related data across multiple tables…

With our schema in place, let’s add some records by inserting rows across the related products, orders, and customers tables.

-- Add products
INSERT INTO products (name, price) VALUES 
  ('Product 1', 9.99),
  ('Product 2', 5.49),
  ('Product 3', 15.00);


-- List products (with generated product_id values)  
SELECT * FROM products;

/*
product_id  name       price
----------  ----------  ----------
1           Product 1   9.99
2           Product 2   5.49
3           Product 3   15  
*/


-- Add customers
INSERT INTO customers (first_name, last_name) VALUES
  ('John', 'Doe'),
  ('Lisa', 'Smith'),
  ('Ahmed', 'Khan');

  
-- List all customers
SELECT * FROM customers;  

/*
customer_id  first_name  last_name
------------  ----------  --------------
      1       John        Doe
      2       Lisa        Smith
      3       Ahmed       Khan
*/


-- Add related orders data
INSERT INTO orders (product_id, customer_id, quantity) VALUES 
  (1, 1, 2),
  (2, 1, 1),
  (3, 2, 5), 
  (1, 3, 10);

-- List all orders
SELECT * FROM orders;

/*
order_id  product_id  customer_id  quantity
----------  ----------  -----------  ----------
   1       1           1            2
   2       2           1            1
   3       3           2            5
   4       1           3            10
*/ 

The key steps we took:

  1. Inserted parent products records
  2. Inserted parent customer records
  3. Inserted related orders with foreign keys matching:
    • Valid product_id values from products table
    • Valid customer_id values from customers table

This allowed us to reuse existing keys between tables for maintaining relationships and data consistency.

Later if a product gets deleted – all child records using that product become invalid and also get deleted by default – avoiding orphan records!

ON DELETE CASCADE Overview

Speaking of deletes – what happens when parent records referenced by a foreign key gets deleted?

It will result in child records having invalid foreign key values causing data inconsistency.

To handle this, we can configure foreign keys to automatically:

  • Restrict: Rejects delete preventing data loss
  • Set Null: Sets foreign key as NULL
  • Cascade: Deletes child records

ON DELETE CASCADE is the most common approach.

Below is the syntax for defining on delete rules when creating tables:

-- Example products and orders table

CREATE TABLE products (
  product_id INTEGER PRIMARY KEY
);

CREATE TABLE orders (
  order_id INTEGER PRIMARY KEY  
  product_id INTEGER,
  FOREIGN KEY(product_id) 
    REFERENCES products(product_id)
    ON DELETE CASCADE  
);

Now if a product gets deleted, all related orders also get deleted automatically avoiding inconsistencies!

ON DELETE CASCADE works similarly with UPDATE statements propagating changes from parent to child tables.

Summary Tables for Quick Reference

Here is a comparison table summarizing key details on foreign keys in SQLite covered so far:

TopicDescription
Foreign KeyA column that references the primary key of another table
Child TableContains the foreign key
Parent TableContains referenced primary key column
REFERENCESDefines parent table and referenced column
InsertsReuse keys between tables to preserve relationships
ON DELETE CASCADEDeletes child records when parent key deleted

In addition, refer to below code snippets showing foreign key syntax, creation, inserts, and deletes based on our e-commerce example database:

Foreign Key Definition

CREATE TABLE orders (
  order_id INTEGER PRIMARY KEY,
  product_id INTEGER,
  FOREIGN KEY(product_id) REFERENCES products(product_id)
);

Insert Related Data

INSERT INTO orders (product_id, customer_id)
VALUES (1, 2); 

ON DELETE CASCADE

FOREIGN KEY(product_id)
  REFERENCES products(product_id)
  ON DELETE CASCADE

Putting it All Together

In this comprehensive deep dive, you learned all about foreign keys in SQLite – from relationships concepts to triggers and integrity constraints.

We took a very hands-on approach building out an example database schema step-by-step:

  • Covered syntax for defining foreign key constraints
  • Added multi-table data with foreign keys intact
  • Discussed deletes cascades and updates for data consistency

You should now have a solid grasp of working with relational data across multiple linked tables powered by foreign keys in SQLite.

The structured organization and flexibility it provides will serve you well for any application working with related data!