> For the complete documentation index, see [llms.txt](https://docs.acpt.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.acpt.io/custom-content-types/foreign-keys.md).

# Foreign Keys

Define relational constraints between custom tables using foreign keys.

A **foreign key** is a database-level constraint that links a column in one table to the primary key of another table. Foreign keys enforce referential integrity: you cannot create a record in the child table that references a non-existent record in the parent table, and you can control what happens when a parent record is deleted or updated.

Foreign keys are configured in **Step 4** of the [table wizard](/custom-content-types/tables.md).

## Creating a foreign key

1. Open the table wizard and navigate to **Step 4 — Foreign Keys**.
2. Click **Add foreign key**.
3. Fill in the constraint settings:

| Field                | Description                                                               |
| -------------------- | ------------------------------------------------------------------------- |
| **Constraint name**  | Unique identifier for this FK constraint (e.g. `fk_movies_director`).     |
| **Local column**     | The column in *this* table that holds the reference (e.g. `director_id`). |
| **Reference table**  | The parent table (e.g. `directors`).                                      |
| **Reference column** | The column in the parent table being referenced (usually `id`).           |
| **On delete**        | Action when the parent record is deleted (see actions below).             |
| **On update**        | Action when the parent key value is updated.                              |

## Referential actions

| Action        | Description                                                                                                      |
| ------------- | ---------------------------------------------------------------------------------------------------------------- |
| **CASCADE**   | Automatically delete or update the child rows when the parent row is deleted/updated.                            |
| **SET NULL**  | Set the foreign key column to `NULL` when the parent row is deleted/updated. Requires the column to be nullable. |
| **RESTRICT**  | Prevent deletion/update of the parent row while child rows still reference it.                                   |
| **NO ACTION** | Same as RESTRICT in MySQL (checked at the end of the statement).                                                 |

(`SET DEFAULT` is not offered — InnoDB parses but ignores it.)

## Example — Movies and Directors

A `movies` table references a `directors` table:

| Field            | Value                   |
| ---------------- | ----------------------- |
| Constraint name  | `fk_movies_director_id` |
| Local column     | `director_id`           |
| Reference table  | `directors`             |
| Reference column | `id`                    |
| On delete        | `SET NULL`              |
| On update        | `CASCADE`               |

<figure><img src="https://3235524095-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fiyf0tSKPgXiyoQ3zV3I6%2Fuploads%2Fgit-blob-0d9e0fee87cf62f05e0e40bc329a292bde287234%2Fcct-foreign-keys-step.png?alt=media" alt="Foreign keys step of the table wizard"><figcaption><p>Step 4 — Foreign keys, showing the fk_movies_director_id constraint.</p></figcaption></figure>

This means:

* A movie's `director_id` must match a valid `id` in `directors`.
* If a director is deleted, all their movies have `director_id` set to `NULL` (the movie is preserved but orphaned).
* If a director's `id` changes, the `director_id` in all related movies is updated automatically.

## Deleting a foreign key

Click **Delete** next to the constraint in Step 4. The constraint is dropped from the database the next time the schema is synced.

{% hint style="info" %}
Foreign key constraints only work with tables using the **InnoDB** storage engine. ACPT creates all custom tables as InnoDB by default.
{% endhint %}

## See also

* [Relational fields](/custom-content-types/relational-fields.md) — for the UI-level relationship experience (linking records across tables via the admin form)
