Referential actions
Referential actions determine what happens to a record when your application deletes or updates a related record.
From version 2.26.0, you can define referential actions on the relation fields in your Prisma schema. This allows you to define referential actions like cascading deletes and cascading updates at a Prisma ORM level.
Version differences
- If you use version 3.0.1 or later, you can use referential actions as described on this page.
- If you use a version between 2.26.0 and 3.0.0, you can use referential actions as described on this page, but you must enable the preview feature flag
referentialActions
. - If you use version 2.25.0 or earlier, you can configure cascading deletes manually in your database.
In the following example, adding onDelete: Cascade
to the author
field on the Post
model means that deleting the User
record will also delete all related Post
records.
model Post {
id Int @id @default(autoincrement())
title String
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
authorId Int
}
model User {
id Int @id @default(autoincrement())
posts Post[]
}
If you do not specify a referential action, Prisma ORM uses a default.
If you upgrade from a version earlier than 2.26.0:
It is extremely important that you check the upgrade paths for referential actions section. Prisma ORM's support of referential actions removes the safety net in Prisma Client that prevents cascading deletes at runtime. If you use the feature without upgrading your database, the old default action - ON DELETE CASCADE
- becomes active. This might result in cascading deletes that you did not expect.
What are referential actions?
Referential actions are policies that define how a referenced record is handled by the database when you run an update
or delete
query.
Referential actions on the database level
Referential actions are features of foreign key constraints that exist to preserve referential integrity in your database.
When you define relationships between data models in your Prisma schema, you use relation fields, which do not exist on the database, and scalar fields, which do exist on the database. These foreign keys connect the models on the database level.
Referential integrity states that these foreign keys must reference an existing primary key value in the related database table. In your Prisma schema, this is generally represented by the id
field on the related model.
By default a database will reject any operation that violates the referential integrity, for example, by deleting referenced records.
How to use referential actions
Referential actions are defined in the @relation
attribute and map to the actions on the foreign key constraint in the underlying database. If you do not specify a referential action, Prisma ORM falls back to a default.
The following model defines a one-to-many relation between User
and Post
and a many-to-many relation between Post
and Tag
, with explicitly defined referential actions:
model User {
id Int @id @default(autoincrement())
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
tags TagOnPosts[]
User User? @relation(fields: [userId], references: [id], onDelete: SetNull, onUpdate: Cascade)
userId Int?
}
model TagOnPosts {
id Int @id @default(autoincrement())
post Post? @relation(fields: [postId], references: [id], onUpdate: Cascade, onDelete: Cascade)
tag Tag? @relation(fields: [tagId], references: [id], onUpdate: Cascade, onDelete: Cascade)
postId Int?
tagId Int?
}
model Tag {
id Int @id @default(autoincrement())
name String @unique
posts TagOnPosts[]
}
This model explicitly defines the following referential actions:
- If you delete a
Tag
, the corresponding tag assignment is also deleted inTagOnPosts
, using theCascade
referential action - If you delete a
User
, the author is removed from all posts by setting the field value toNull
, because of theSetNull
referential action. To allow this,User
anduserId
must be optional fields inPost
.
Prisma ORM supports the following referential actions:
Referential action defaults
If you do not specify a referential action, Prisma ORM uses the following defaults:
Clause | Optional relations | Mandatory relations |
---|---|---|
onDelete | SetNull | Restrict |
onUpdate | Cascade | Cascade |
For example, in the following schema all Post
records must be connected to a User
via the author
relation:
model Post {
id Int @id @default(autoincrement())
title String
author User @relation(fields: [authorId], references: [id])
authorId Int
}
model User {
id Int @id @default(autoincrement())
posts Post[]
}
The schema does not explicitly define referential actions on the mandatory author
relation field, which means that the default referential actions of Restrict
for onDelete
and Cascade
for onUpdate
apply.
Caveats
The following caveats apply:
- Referential actions are not supported on implicit many-to-many relations. To use referential actions, you must define an explicit many-to-many relation and define your referential actions on the join table.
- Certain combinations of referential actions and required/optional relations are incompatible. For example, using
SetNull
on a required relation will lead to database errors when deleting referenced records because the non-nullable constraint would be violated. See this GitHub issue for more information.
Types of referential actions
The following table shows which referential action each database supports.
Database | Cascade | Restrict | NoAction | SetNull | SetDefault |
---|---|---|---|---|---|
PostgreSQL | ✔️ | ✔️ | ✔️ | ✔️⌘ | ✔️ |
MySQL/MariaDB | ✔️ | ✔️ | ✔️ | ✔️ | ❌ (✔️†) |
SQLite | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
SQL Server | ✔️ | ❌‡ | ✔️ | ✔️ | ✔️ |
CockroachDB | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
MongoDB†† | ✔️ | ✔️ | ✔️ | ✔️ | ❌ |
- † See special cases for MySQL.
- ⌘ See special cases for PostgreSQL.
- ‡ See special cases for SQL Server.
- †† Referential actions for MongoDB are available in Prisma ORM versions 3.7.0 and later.
Special cases for referential actions
Referential actions are part of the ANSI SQL standard. However, there are special cases where some relational databases diverge from the standard.
MySQL/MariaDB
MySQL/MariaDB, and the underlying InnoDB storage engine, does not support SetDefault
. The exact behavior depends on the database version:
- In MySQL versions 8 and later, and MariaDB versions 10.5 and later,
SetDefault
effectively acts as an alias forNoAction
. You can define tables using theSET DEFAULT
referential action, but a foreign key constraint error is triggered at runtime. - In MySQL versions 5.6 and later, and MariaDB versions before 10.5, attempting to create a table definition with the
SET DEFAULT
referential action fails with a syntax error.
For this reason, when you set mysql
as the database provider, Prisma ORM warns users to replace SetDefault
referential actions in the Prisma schema with another action.
PostgreSQL
PostgreSQL is the only database supported by Prisma ORM that allows you to define a SetNull
referential action that refers to a non-nullable field. However, this raises a foreign key constraint error when the action is triggered at runtime.
For this reason, when you set postgres
as the database provider in the (default) foreignKeys
relation mode, Prisma ORM warns users to mark as optional any fields that are included in a @relation
attribute with a SetNull
referential action. For all other database providers, Prisma ORM rejects the schema with a validation error.
SQL Server
Restrict
is not available for SQL Server databases, but you can use NoAction
instead.
Cascade
onDelete: Cascade
Deleting a referenced record will trigger the deletion of referencing record.onUpdate: Cascade
Updates the relation scalar fields if the referenced scalar fields of the dependent record are updated.
Example usage
model Post {
id Int @id @default(autoincrement())
title String
author User @relation(fields: [authorId], references: [id], onDelete: Cascade, onUpdate: Cascade)
authorId Int
}
model User {
id Int @id @default(autoincrement())
posts Post[]
}
Result of using Cascade
If a User
record is deleted, then their posts are deleted too. If the user's id
is updated, then the corresponding authorId
is also updated.
How to use cascading deletes
Restrict
onDelete: Restrict
Prevents the deletion if any referencing records exist.onUpdate: Restrict
Prevents the identifier of a referenced record from being changed.
Example usage
model Post {
id Int @id @default(autoincrement())
title String
author User @relation(fields: [authorId], references: [id], onDelete: Restrict, onUpdate: Restrict)
authorId Int
}
model User {
id Int @id @default(autoincrement())
posts Post[]
}
Result of using Restrict
User
s with posts cannot be deleted. The User
's id
cannot be changed.
The Restrict
action is not available on Microsoft SQL Server and triggers a schema validation error. Instead, you can use NoAction
, which produces the same result and is compatible with SQL Server.
NoAction
The NoAction
action is similar to Restrict
, the difference between the two is dependent on the database being used:
- PostgreSQL:
NoAction
allows the check (if a referenced row on the table exists) to be deferred until later in the transaction. See the PostgreSQL docs for more information. - MySQL:
NoAction
behaves exactly the same asRestrict
. See the MySQL docs for more information. - SQLite: When a related primary key is modified or deleted, no action is taken. See the SQLite docs for more information.
- SQL Server: When a referenced record is deleted or modified, an error is raised. See the SQL Server docs for more information.
- MongoDB (in preview from version 3.6.0): When a record is modified or deleted, nothing is done to any related records.
If you are managing relations in Prisma Client rather than using foreign keys in the database, you should be aware that currently Prisma ORM only implements the referential actions. Foreign keys also create constraints, which make it impossible to manipulate data in a way that would violate these constraints: instead of executing the query, the database responds with an error. These constraints will not be created if you emulate referential integrity in Prisma Client, so if you set the referential action to NoAction
there will be no checks to prevent you from breaking the referential integrity.